diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-08-16 18:50:22 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-08-16 18:50:22 -0400 |
commit | 45b6ae761e5259d457a797f66f4d4c16b620f268 (patch) | |
tree | 6811a3428de0b7a3eb0594cdf9b67adab5b20c34 | |
parent | ae5d68be42cd0275a91faf56d2b527b448c3caf4 (diff) | |
parent | af7752106e4f12b4ee47b4eca3e7ba4bcec6e7e5 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
Pull s390 fixes from Martin Schwidefsky:
"A couple of bug fixes, minor cleanup and a change to the default
config"
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux:
s390/dasd: fix failing CUIR assignment under LPAR
s390/pageattr: handle numpages parameter correctly
s390/dasd: fix hanging device after clear subchannel
s390/qdio: avoid reschedule of outbound tasklet once killed
s390/qdio: remove checks for ccw device internal state
s390/qdio: fix double return code evaluation
s390/qdio: get rid of spin_lock_irqsave usage
s390/cio: remove subchannel_id from ccw_device_private
s390/qdio: obtain subchannel_id via ccw_device_get_schid()
s390/cio: stop using subchannel_id from ccw_device_private
s390/config: make the vector optimized crc function builtin
s390/lib: fix memcmp and strstr
s390/crc32-vx: Fix checksum calculation for small sizes
s390: clarify compressed image code path
-rw-r--r-- | arch/s390/boot/compressed/head.S | 11 | ||||
-rw-r--r-- | arch/s390/configs/default_defconfig | 2 | ||||
-rw-r--r-- | arch/s390/configs/gcov_defconfig | 2 | ||||
-rw-r--r-- | arch/s390/configs/performance_defconfig | 2 | ||||
-rw-r--r-- | arch/s390/crypto/crc32-vx.c | 6 | ||||
-rw-r--r-- | arch/s390/defconfig | 2 | ||||
-rw-r--r-- | arch/s390/kernel/head.S | 4 | ||||
-rw-r--r-- | arch/s390/lib/string.c | 16 | ||||
-rw-r--r-- | arch/s390/mm/pageattr.c | 2 | ||||
-rw-r--r-- | drivers/s390/block/dasd.c | 10 | ||||
-rw-r--r-- | drivers/s390/block/dasd_eckd.c | 10 | ||||
-rw-r--r-- | drivers/s390/cio/device.c | 2 | ||||
-rw-r--r-- | drivers/s390/cio/device_status.c | 7 | ||||
-rw-r--r-- | drivers/s390/cio/io_sch.h | 1 | ||||
-rw-r--r-- | drivers/s390/cio/qdio_main.c | 113 |
15 files changed, 107 insertions, 83 deletions
diff --git a/arch/s390/boot/compressed/head.S b/arch/s390/boot/compressed/head.S index f86a4eef28a9..28c4f96a2d9c 100644 --- a/arch/s390/boot/compressed/head.S +++ b/arch/s390/boot/compressed/head.S | |||
@@ -21,16 +21,21 @@ ENTRY(startup_continue) | |||
21 | lg %r15,.Lstack-.LPG1(%r13) | 21 | lg %r15,.Lstack-.LPG1(%r13) |
22 | aghi %r15,-160 | 22 | aghi %r15,-160 |
23 | brasl %r14,decompress_kernel | 23 | brasl %r14,decompress_kernel |
24 | # setup registers for memory mover & branch to target | 24 | # Set up registers for memory mover. We move the decompressed image to |
25 | # 0x11000, starting at offset 0x11000 in the decompressed image so | ||
26 | # that code living at 0x11000 in the image will end up at 0x11000 in | ||
27 | # memory. | ||
25 | lgr %r4,%r2 | 28 | lgr %r4,%r2 |
26 | lg %r2,.Loffset-.LPG1(%r13) | 29 | lg %r2,.Loffset-.LPG1(%r13) |
27 | la %r4,0(%r2,%r4) | 30 | la %r4,0(%r2,%r4) |
28 | lg %r3,.Lmvsize-.LPG1(%r13) | 31 | lg %r3,.Lmvsize-.LPG1(%r13) |
29 | lgr %r5,%r3 | 32 | lgr %r5,%r3 |
30 | # move the memory mover someplace safe | 33 | # Move the memory mover someplace safe so it doesn't overwrite itself. |
31 | la %r1,0x200 | 34 | la %r1,0x200 |
32 | mvc 0(mover_end-mover,%r1),mover-.LPG1(%r13) | 35 | mvc 0(mover_end-mover,%r1),mover-.LPG1(%r13) |
33 | # decompress image is started at 0x11000 | 36 | # When the memory mover is done we pass control to |
37 | # arch/s390/kernel/head64.S:startup_continue which lives at 0x11000 in | ||
38 | # the decompressed image. | ||
34 | lgr %r6,%r2 | 39 | lgr %r6,%r2 |
35 | br %r1 | 40 | br %r1 |
36 | mover: | 41 | mover: |
diff --git a/arch/s390/configs/default_defconfig b/arch/s390/configs/default_defconfig index 889ea3450210..26e0c7f08814 100644 --- a/arch/s390/configs/default_defconfig +++ b/arch/s390/configs/default_defconfig | |||
@@ -678,7 +678,7 @@ CONFIG_CRYPTO_SHA512_S390=m | |||
678 | CONFIG_CRYPTO_DES_S390=m | 678 | CONFIG_CRYPTO_DES_S390=m |
679 | CONFIG_CRYPTO_AES_S390=m | 679 | CONFIG_CRYPTO_AES_S390=m |
680 | CONFIG_CRYPTO_GHASH_S390=m | 680 | CONFIG_CRYPTO_GHASH_S390=m |
681 | CONFIG_CRYPTO_CRC32_S390=m | 681 | CONFIG_CRYPTO_CRC32_S390=y |
682 | CONFIG_ASYMMETRIC_KEY_TYPE=y | 682 | CONFIG_ASYMMETRIC_KEY_TYPE=y |
683 | CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m | 683 | CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m |
684 | CONFIG_X509_CERTIFICATE_PARSER=m | 684 | CONFIG_X509_CERTIFICATE_PARSER=m |
diff --git a/arch/s390/configs/gcov_defconfig b/arch/s390/configs/gcov_defconfig index 1bcfd764910a..24879dab47bc 100644 --- a/arch/s390/configs/gcov_defconfig +++ b/arch/s390/configs/gcov_defconfig | |||
@@ -616,7 +616,7 @@ CONFIG_CRYPTO_SHA512_S390=m | |||
616 | CONFIG_CRYPTO_DES_S390=m | 616 | CONFIG_CRYPTO_DES_S390=m |
617 | CONFIG_CRYPTO_AES_S390=m | 617 | CONFIG_CRYPTO_AES_S390=m |
618 | CONFIG_CRYPTO_GHASH_S390=m | 618 | CONFIG_CRYPTO_GHASH_S390=m |
619 | CONFIG_CRYPTO_CRC32_S390=m | 619 | CONFIG_CRYPTO_CRC32_S390=y |
620 | CONFIG_ASYMMETRIC_KEY_TYPE=y | 620 | CONFIG_ASYMMETRIC_KEY_TYPE=y |
621 | CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m | 621 | CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m |
622 | CONFIG_X509_CERTIFICATE_PARSER=m | 622 | CONFIG_X509_CERTIFICATE_PARSER=m |
diff --git a/arch/s390/configs/performance_defconfig b/arch/s390/configs/performance_defconfig index 13ff090139c8..a5c1e5f2a0ca 100644 --- a/arch/s390/configs/performance_defconfig +++ b/arch/s390/configs/performance_defconfig | |||
@@ -615,7 +615,7 @@ CONFIG_CRYPTO_SHA512_S390=m | |||
615 | CONFIG_CRYPTO_DES_S390=m | 615 | CONFIG_CRYPTO_DES_S390=m |
616 | CONFIG_CRYPTO_AES_S390=m | 616 | CONFIG_CRYPTO_AES_S390=m |
617 | CONFIG_CRYPTO_GHASH_S390=m | 617 | CONFIG_CRYPTO_GHASH_S390=m |
618 | CONFIG_CRYPTO_CRC32_S390=m | 618 | CONFIG_CRYPTO_CRC32_S390=y |
619 | CONFIG_ASYMMETRIC_KEY_TYPE=y | 619 | CONFIG_ASYMMETRIC_KEY_TYPE=y |
620 | CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m | 620 | CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m |
621 | CONFIG_X509_CERTIFICATE_PARSER=m | 621 | CONFIG_X509_CERTIFICATE_PARSER=m |
diff --git a/arch/s390/crypto/crc32-vx.c b/arch/s390/crypto/crc32-vx.c index 577ae1d4ae89..2bad9d837029 100644 --- a/arch/s390/crypto/crc32-vx.c +++ b/arch/s390/crypto/crc32-vx.c | |||
@@ -51,6 +51,9 @@ u32 crc32c_le_vgfm_16(u32 crc, unsigned char const *buf, size_t size); | |||
51 | struct kernel_fpu vxstate; \ | 51 | struct kernel_fpu vxstate; \ |
52 | unsigned long prealign, aligned, remaining; \ | 52 | unsigned long prealign, aligned, remaining; \ |
53 | \ | 53 | \ |
54 | if (datalen < VX_MIN_LEN + VX_ALIGN_MASK) \ | ||
55 | return ___crc32_sw(crc, data, datalen); \ | ||
56 | \ | ||
54 | if ((unsigned long)data & VX_ALIGN_MASK) { \ | 57 | if ((unsigned long)data & VX_ALIGN_MASK) { \ |
55 | prealign = VX_ALIGNMENT - \ | 58 | prealign = VX_ALIGNMENT - \ |
56 | ((unsigned long)data & VX_ALIGN_MASK); \ | 59 | ((unsigned long)data & VX_ALIGN_MASK); \ |
@@ -59,9 +62,6 @@ u32 crc32c_le_vgfm_16(u32 crc, unsigned char const *buf, size_t size); | |||
59 | data = (void *)((unsigned long)data + prealign); \ | 62 | data = (void *)((unsigned long)data + prealign); \ |
60 | } \ | 63 | } \ |
61 | \ | 64 | \ |
62 | if (datalen < VX_MIN_LEN) \ | ||
63 | return ___crc32_sw(crc, data, datalen); \ | ||
64 | \ | ||
65 | aligned = datalen & ~VX_ALIGN_MASK; \ | 65 | aligned = datalen & ~VX_ALIGN_MASK; \ |
66 | remaining = datalen & VX_ALIGN_MASK; \ | 66 | remaining = datalen & VX_ALIGN_MASK; \ |
67 | \ | 67 | \ |
diff --git a/arch/s390/defconfig b/arch/s390/defconfig index ccccebeeaaf6..73610f2e3b4f 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig | |||
@@ -234,7 +234,7 @@ CONFIG_CRYPTO_SHA256_S390=m | |||
234 | CONFIG_CRYPTO_SHA512_S390=m | 234 | CONFIG_CRYPTO_SHA512_S390=m |
235 | CONFIG_CRYPTO_DES_S390=m | 235 | CONFIG_CRYPTO_DES_S390=m |
236 | CONFIG_CRYPTO_AES_S390=m | 236 | CONFIG_CRYPTO_AES_S390=m |
237 | CONFIG_CRYPTO_CRC32_S390=m | 237 | CONFIG_CRYPTO_CRC32_S390=y |
238 | CONFIG_CRC7=m | 238 | CONFIG_CRC7=m |
239 | # CONFIG_XZ_DEC_X86 is not set | 239 | # CONFIG_XZ_DEC_X86 is not set |
240 | # CONFIG_XZ_DEC_POWERPC is not set | 240 | # CONFIG_XZ_DEC_POWERPC is not set |
diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S index 56e4d8234ef2..4431905f8cfa 100644 --- a/arch/s390/kernel/head.S +++ b/arch/s390/kernel/head.S | |||
@@ -309,7 +309,9 @@ ENTRY(startup_kdump) | |||
309 | l %r15,.Lstack-.LPG0(%r13) | 309 | l %r15,.Lstack-.LPG0(%r13) |
310 | ahi %r15,-STACK_FRAME_OVERHEAD | 310 | ahi %r15,-STACK_FRAME_OVERHEAD |
311 | brasl %r14,verify_facilities | 311 | brasl %r14,verify_facilities |
312 | /* Continue with startup code in head64.S */ | 312 | # For uncompressed images, continue in |
313 | # arch/s390/kernel/head64.S. For compressed images, continue in | ||
314 | # arch/s390/boot/compressed/head.S. | ||
313 | jg startup_continue | 315 | jg startup_continue |
314 | 316 | ||
315 | .Lstack: | 317 | .Lstack: |
diff --git a/arch/s390/lib/string.c b/arch/s390/lib/string.c index e390bbb16443..48352bffbc92 100644 --- a/arch/s390/lib/string.c +++ b/arch/s390/lib/string.c | |||
@@ -237,11 +237,10 @@ char * strrchr(const char * s, int c) | |||
237 | EXPORT_SYMBOL(strrchr); | 237 | EXPORT_SYMBOL(strrchr); |
238 | 238 | ||
239 | static inline int clcle(const char *s1, unsigned long l1, | 239 | static inline int clcle(const char *s1, unsigned long l1, |
240 | const char *s2, unsigned long l2, | 240 | const char *s2, unsigned long l2) |
241 | int *diff) | ||
242 | { | 241 | { |
243 | register unsigned long r2 asm("2") = (unsigned long) s1; | 242 | register unsigned long r2 asm("2") = (unsigned long) s1; |
244 | register unsigned long r3 asm("3") = (unsigned long) l2; | 243 | register unsigned long r3 asm("3") = (unsigned long) l1; |
245 | register unsigned long r4 asm("4") = (unsigned long) s2; | 244 | register unsigned long r4 asm("4") = (unsigned long) s2; |
246 | register unsigned long r5 asm("5") = (unsigned long) l2; | 245 | register unsigned long r5 asm("5") = (unsigned long) l2; |
247 | int cc; | 246 | int cc; |
@@ -252,7 +251,6 @@ static inline int clcle(const char *s1, unsigned long l1, | |||
252 | " srl %0,28" | 251 | " srl %0,28" |
253 | : "=&d" (cc), "+a" (r2), "+a" (r3), | 252 | : "=&d" (cc), "+a" (r2), "+a" (r3), |
254 | "+a" (r4), "+a" (r5) : : "cc"); | 253 | "+a" (r4), "+a" (r5) : : "cc"); |
255 | *diff = *(char *)r2 - *(char *)r4; | ||
256 | return cc; | 254 | return cc; |
257 | } | 255 | } |
258 | 256 | ||
@@ -270,9 +268,9 @@ char * strstr(const char * s1,const char * s2) | |||
270 | return (char *) s1; | 268 | return (char *) s1; |
271 | l1 = __strend(s1) - s1; | 269 | l1 = __strend(s1) - s1; |
272 | while (l1-- >= l2) { | 270 | while (l1-- >= l2) { |
273 | int cc, dummy; | 271 | int cc; |
274 | 272 | ||
275 | cc = clcle(s1, l1, s2, l2, &dummy); | 273 | cc = clcle(s1, l2, s2, l2); |
276 | if (!cc) | 274 | if (!cc) |
277 | return (char *) s1; | 275 | return (char *) s1; |
278 | s1++; | 276 | s1++; |
@@ -313,11 +311,11 @@ EXPORT_SYMBOL(memchr); | |||
313 | */ | 311 | */ |
314 | int memcmp(const void *cs, const void *ct, size_t n) | 312 | int memcmp(const void *cs, const void *ct, size_t n) |
315 | { | 313 | { |
316 | int ret, diff; | 314 | int ret; |
317 | 315 | ||
318 | ret = clcle(cs, n, ct, n, &diff); | 316 | ret = clcle(cs, n, ct, n); |
319 | if (ret) | 317 | if (ret) |
320 | ret = diff; | 318 | ret = ret == 1 ? -1 : 1; |
321 | return ret; | 319 | return ret; |
322 | } | 320 | } |
323 | EXPORT_SYMBOL(memcmp); | 321 | EXPORT_SYMBOL(memcmp); |
diff --git a/arch/s390/mm/pageattr.c b/arch/s390/mm/pageattr.c index 7104ffb5a67f..af7cf28cf97e 100644 --- a/arch/s390/mm/pageattr.c +++ b/arch/s390/mm/pageattr.c | |||
@@ -252,6 +252,8 @@ static int change_page_attr(unsigned long addr, unsigned long end, | |||
252 | int rc = -EINVAL; | 252 | int rc = -EINVAL; |
253 | pgd_t *pgdp; | 253 | pgd_t *pgdp; |
254 | 254 | ||
255 | if (addr == end) | ||
256 | return 0; | ||
255 | if (end >= MODULES_END) | 257 | if (end >= MODULES_END) |
256 | return -EINVAL; | 258 | return -EINVAL; |
257 | mutex_lock(&cpa_mutex); | 259 | mutex_lock(&cpa_mutex); |
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 8973d34ce5ba..fb1b56a71475 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
@@ -1643,9 +1643,18 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, | |||
1643 | u8 *sense = NULL; | 1643 | u8 *sense = NULL; |
1644 | int expires; | 1644 | int expires; |
1645 | 1645 | ||
1646 | cqr = (struct dasd_ccw_req *) intparm; | ||
1646 | if (IS_ERR(irb)) { | 1647 | if (IS_ERR(irb)) { |
1647 | switch (PTR_ERR(irb)) { | 1648 | switch (PTR_ERR(irb)) { |
1648 | case -EIO: | 1649 | case -EIO: |
1650 | if (cqr && cqr->status == DASD_CQR_CLEAR_PENDING) { | ||
1651 | device = (struct dasd_device *) cqr->startdev; | ||
1652 | cqr->status = DASD_CQR_CLEARED; | ||
1653 | dasd_device_clear_timer(device); | ||
1654 | wake_up(&dasd_flush_wq); | ||
1655 | dasd_schedule_device_bh(device); | ||
1656 | return; | ||
1657 | } | ||
1649 | break; | 1658 | break; |
1650 | case -ETIMEDOUT: | 1659 | case -ETIMEDOUT: |
1651 | DBF_EVENT_DEVID(DBF_WARNING, cdev, "%s: " | 1660 | DBF_EVENT_DEVID(DBF_WARNING, cdev, "%s: " |
@@ -1661,7 +1670,6 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, | |||
1661 | } | 1670 | } |
1662 | 1671 | ||
1663 | now = get_tod_clock(); | 1672 | now = get_tod_clock(); |
1664 | cqr = (struct dasd_ccw_req *) intparm; | ||
1665 | /* check for conditions that should be handled immediately */ | 1673 | /* check for conditions that should be handled immediately */ |
1666 | if (!cqr || | 1674 | if (!cqr || |
1667 | !(scsw_dstat(&irb->scsw) == (DEV_STAT_CHN_END | DEV_STAT_DEV_END) && | 1675 | !(scsw_dstat(&irb->scsw) == (DEV_STAT_CHN_END | DEV_STAT_DEV_END) && |
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index fd2eff440098..98bbec44bcd0 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
@@ -5078,6 +5078,8 @@ static int dasd_eckd_read_message_buffer(struct dasd_device *device, | |||
5078 | return PTR_ERR(cqr); | 5078 | return PTR_ERR(cqr); |
5079 | } | 5079 | } |
5080 | 5080 | ||
5081 | cqr->lpm = lpum; | ||
5082 | retry: | ||
5081 | cqr->startdev = device; | 5083 | cqr->startdev = device; |
5082 | cqr->memdev = device; | 5084 | cqr->memdev = device; |
5083 | cqr->block = NULL; | 5085 | cqr->block = NULL; |
@@ -5122,6 +5124,14 @@ static int dasd_eckd_read_message_buffer(struct dasd_device *device, | |||
5122 | (prssdp + 1); | 5124 | (prssdp + 1); |
5123 | memcpy(messages, message_buf, | 5125 | memcpy(messages, message_buf, |
5124 | sizeof(struct dasd_rssd_messages)); | 5126 | sizeof(struct dasd_rssd_messages)); |
5127 | } else if (cqr->lpm) { | ||
5128 | /* | ||
5129 | * on z/VM we might not be able to do I/O on the requested path | ||
5130 | * but instead we get the required information on any path | ||
5131 | * so retry with open path mask | ||
5132 | */ | ||
5133 | cqr->lpm = 0; | ||
5134 | goto retry; | ||
5125 | } else | 5135 | } else |
5126 | DBF_EVENT_DEVID(DBF_WARNING, device->cdev, | 5136 | DBF_EVENT_DEVID(DBF_WARNING, device->cdev, |
5127 | "Reading messages failed with rc=%d\n" | 5137 | "Reading messages failed with rc=%d\n" |
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 7ada078ffdd0..6a58bc8f46e2 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
@@ -762,7 +762,6 @@ static int io_subchannel_initialize_dev(struct subchannel *sch, | |||
762 | priv->state = DEV_STATE_NOT_OPER; | 762 | priv->state = DEV_STATE_NOT_OPER; |
763 | priv->dev_id.devno = sch->schib.pmcw.dev; | 763 | priv->dev_id.devno = sch->schib.pmcw.dev; |
764 | priv->dev_id.ssid = sch->schid.ssid; | 764 | priv->dev_id.ssid = sch->schid.ssid; |
765 | priv->schid = sch->schid; | ||
766 | 765 | ||
767 | INIT_WORK(&priv->todo_work, ccw_device_todo); | 766 | INIT_WORK(&priv->todo_work, ccw_device_todo); |
768 | INIT_LIST_HEAD(&priv->cmb_list); | 767 | INIT_LIST_HEAD(&priv->cmb_list); |
@@ -1000,7 +999,6 @@ static int ccw_device_move_to_sch(struct ccw_device *cdev, | |||
1000 | put_device(&old_sch->dev); | 999 | put_device(&old_sch->dev); |
1001 | /* Initialize new subchannel. */ | 1000 | /* Initialize new subchannel. */ |
1002 | spin_lock_irq(sch->lock); | 1001 | spin_lock_irq(sch->lock); |
1003 | cdev->private->schid = sch->schid; | ||
1004 | cdev->ccwlock = sch->lock; | 1002 | cdev->ccwlock = sch->lock; |
1005 | if (!sch_is_pseudo_sch(sch)) | 1003 | if (!sch_is_pseudo_sch(sch)) |
1006 | sch_set_cdev(sch, cdev); | 1004 | sch_set_cdev(sch, cdev); |
diff --git a/drivers/s390/cio/device_status.c b/drivers/s390/cio/device_status.c index 15b56a15db15..9bc3512374c9 100644 --- a/drivers/s390/cio/device_status.c +++ b/drivers/s390/cio/device_status.c | |||
@@ -26,6 +26,7 @@ | |||
26 | static void | 26 | static void |
27 | ccw_device_msg_control_check(struct ccw_device *cdev, struct irb *irb) | 27 | ccw_device_msg_control_check(struct ccw_device *cdev, struct irb *irb) |
28 | { | 28 | { |
29 | struct subchannel *sch = to_subchannel(cdev->dev.parent); | ||
29 | char dbf_text[15]; | 30 | char dbf_text[15]; |
30 | 31 | ||
31 | if (!scsw_is_valid_cstat(&irb->scsw) || | 32 | if (!scsw_is_valid_cstat(&irb->scsw) || |
@@ -36,10 +37,10 @@ ccw_device_msg_control_check(struct ccw_device *cdev, struct irb *irb) | |||
36 | "received" | 37 | "received" |
37 | " ... device %04x on subchannel 0.%x.%04x, dev_stat " | 38 | " ... device %04x on subchannel 0.%x.%04x, dev_stat " |
38 | ": %02X sch_stat : %02X\n", | 39 | ": %02X sch_stat : %02X\n", |
39 | cdev->private->dev_id.devno, cdev->private->schid.ssid, | 40 | cdev->private->dev_id.devno, sch->schid.ssid, |
40 | cdev->private->schid.sch_no, | 41 | sch->schid.sch_no, |
41 | scsw_dstat(&irb->scsw), scsw_cstat(&irb->scsw)); | 42 | scsw_dstat(&irb->scsw), scsw_cstat(&irb->scsw)); |
42 | sprintf(dbf_text, "chk%x", cdev->private->schid.sch_no); | 43 | sprintf(dbf_text, "chk%x", sch->schid.sch_no); |
43 | CIO_TRACE_EVENT(0, dbf_text); | 44 | CIO_TRACE_EVENT(0, dbf_text); |
44 | CIO_HEX_EVENT(0, irb, sizeof(struct irb)); | 45 | CIO_HEX_EVENT(0, irb, sizeof(struct irb)); |
45 | } | 46 | } |
diff --git a/drivers/s390/cio/io_sch.h b/drivers/s390/cio/io_sch.h index 8975060af96c..220f49145b2f 100644 --- a/drivers/s390/cio/io_sch.h +++ b/drivers/s390/cio/io_sch.h | |||
@@ -120,7 +120,6 @@ struct ccw_device_private { | |||
120 | int state; /* device state */ | 120 | int state; /* device state */ |
121 | atomic_t onoff; | 121 | atomic_t onoff; |
122 | struct ccw_dev_id dev_id; /* device id */ | 122 | struct ccw_dev_id dev_id; /* device id */ |
123 | struct subchannel_id schid; /* subchannel number */ | ||
124 | struct ccw_request req; /* internal I/O request */ | 123 | struct ccw_request req; /* internal I/O request */ |
125 | int iretry; | 124 | int iretry; |
126 | u8 pgid_valid_mask; /* mask of valid PGIDs */ | 125 | u8 pgid_valid_mask; /* mask of valid PGIDs */ |
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 4bb5262f7aee..71bf9bded485 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c | |||
@@ -686,6 +686,15 @@ static void qdio_kick_handler(struct qdio_q *q) | |||
686 | q->qdio_error = 0; | 686 | q->qdio_error = 0; |
687 | } | 687 | } |
688 | 688 | ||
689 | static inline int qdio_tasklet_schedule(struct qdio_q *q) | ||
690 | { | ||
691 | if (likely(q->irq_ptr->state == QDIO_IRQ_STATE_ACTIVE)) { | ||
692 | tasklet_schedule(&q->tasklet); | ||
693 | return 0; | ||
694 | } | ||
695 | return -EPERM; | ||
696 | } | ||
697 | |||
689 | static void __qdio_inbound_processing(struct qdio_q *q) | 698 | static void __qdio_inbound_processing(struct qdio_q *q) |
690 | { | 699 | { |
691 | qperf_inc(q, tasklet_inbound); | 700 | qperf_inc(q, tasklet_inbound); |
@@ -698,10 +707,8 @@ static void __qdio_inbound_processing(struct qdio_q *q) | |||
698 | if (!qdio_inbound_q_done(q)) { | 707 | if (!qdio_inbound_q_done(q)) { |
699 | /* means poll time is not yet over */ | 708 | /* means poll time is not yet over */ |
700 | qperf_inc(q, tasklet_inbound_resched); | 709 | qperf_inc(q, tasklet_inbound_resched); |
701 | if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED)) { | 710 | if (!qdio_tasklet_schedule(q)) |
702 | tasklet_schedule(&q->tasklet); | ||
703 | return; | 711 | return; |
704 | } | ||
705 | } | 712 | } |
706 | 713 | ||
707 | qdio_stop_polling(q); | 714 | qdio_stop_polling(q); |
@@ -711,8 +718,7 @@ static void __qdio_inbound_processing(struct qdio_q *q) | |||
711 | */ | 718 | */ |
712 | if (!qdio_inbound_q_done(q)) { | 719 | if (!qdio_inbound_q_done(q)) { |
713 | qperf_inc(q, tasklet_inbound_resched2); | 720 | qperf_inc(q, tasklet_inbound_resched2); |
714 | if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED)) | 721 | qdio_tasklet_schedule(q); |
715 | tasklet_schedule(&q->tasklet); | ||
716 | } | 722 | } |
717 | } | 723 | } |
718 | 724 | ||
@@ -869,16 +875,15 @@ static void __qdio_outbound_processing(struct qdio_q *q) | |||
869 | * is noticed and outbound_handler is called after some time. | 875 | * is noticed and outbound_handler is called after some time. |
870 | */ | 876 | */ |
871 | if (qdio_outbound_q_done(q)) | 877 | if (qdio_outbound_q_done(q)) |
872 | del_timer(&q->u.out.timer); | 878 | del_timer_sync(&q->u.out.timer); |
873 | else | 879 | else |
874 | if (!timer_pending(&q->u.out.timer)) | 880 | if (!timer_pending(&q->u.out.timer) && |
881 | likely(q->irq_ptr->state == QDIO_IRQ_STATE_ACTIVE)) | ||
875 | mod_timer(&q->u.out.timer, jiffies + 10 * HZ); | 882 | mod_timer(&q->u.out.timer, jiffies + 10 * HZ); |
876 | return; | 883 | return; |
877 | 884 | ||
878 | sched: | 885 | sched: |
879 | if (unlikely(q->irq_ptr->state == QDIO_IRQ_STATE_STOPPED)) | 886 | qdio_tasklet_schedule(q); |
880 | return; | ||
881 | tasklet_schedule(&q->tasklet); | ||
882 | } | 887 | } |
883 | 888 | ||
884 | /* outbound tasklet */ | 889 | /* outbound tasklet */ |
@@ -892,9 +897,7 @@ void qdio_outbound_timer(unsigned long data) | |||
892 | { | 897 | { |
893 | struct qdio_q *q = (struct qdio_q *)data; | 898 | struct qdio_q *q = (struct qdio_q *)data; |
894 | 899 | ||
895 | if (unlikely(q->irq_ptr->state == QDIO_IRQ_STATE_STOPPED)) | 900 | qdio_tasklet_schedule(q); |
896 | return; | ||
897 | tasklet_schedule(&q->tasklet); | ||
898 | } | 901 | } |
899 | 902 | ||
900 | static inline void qdio_check_outbound_after_thinint(struct qdio_q *q) | 903 | static inline void qdio_check_outbound_after_thinint(struct qdio_q *q) |
@@ -907,7 +910,7 @@ static inline void qdio_check_outbound_after_thinint(struct qdio_q *q) | |||
907 | 910 | ||
908 | for_each_output_queue(q->irq_ptr, out, i) | 911 | for_each_output_queue(q->irq_ptr, out, i) |
909 | if (!qdio_outbound_q_done(out)) | 912 | if (!qdio_outbound_q_done(out)) |
910 | tasklet_schedule(&out->tasklet); | 913 | qdio_tasklet_schedule(out); |
911 | } | 914 | } |
912 | 915 | ||
913 | static void __tiqdio_inbound_processing(struct qdio_q *q) | 916 | static void __tiqdio_inbound_processing(struct qdio_q *q) |
@@ -929,10 +932,8 @@ static void __tiqdio_inbound_processing(struct qdio_q *q) | |||
929 | 932 | ||
930 | if (!qdio_inbound_q_done(q)) { | 933 | if (!qdio_inbound_q_done(q)) { |
931 | qperf_inc(q, tasklet_inbound_resched); | 934 | qperf_inc(q, tasklet_inbound_resched); |
932 | if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED)) { | 935 | if (!qdio_tasklet_schedule(q)) |
933 | tasklet_schedule(&q->tasklet); | ||
934 | return; | 936 | return; |
935 | } | ||
936 | } | 937 | } |
937 | 938 | ||
938 | qdio_stop_polling(q); | 939 | qdio_stop_polling(q); |
@@ -942,8 +943,7 @@ static void __tiqdio_inbound_processing(struct qdio_q *q) | |||
942 | */ | 943 | */ |
943 | if (!qdio_inbound_q_done(q)) { | 944 | if (!qdio_inbound_q_done(q)) { |
944 | qperf_inc(q, tasklet_inbound_resched2); | 945 | qperf_inc(q, tasklet_inbound_resched2); |
945 | if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED)) | 946 | qdio_tasklet_schedule(q); |
946 | tasklet_schedule(&q->tasklet); | ||
947 | } | 947 | } |
948 | } | 948 | } |
949 | 949 | ||
@@ -977,7 +977,7 @@ static void qdio_int_handler_pci(struct qdio_irq *irq_ptr) | |||
977 | int i; | 977 | int i; |
978 | struct qdio_q *q; | 978 | struct qdio_q *q; |
979 | 979 | ||
980 | if (unlikely(irq_ptr->state == QDIO_IRQ_STATE_STOPPED)) | 980 | if (unlikely(irq_ptr->state != QDIO_IRQ_STATE_ACTIVE)) |
981 | return; | 981 | return; |
982 | 982 | ||
983 | for_each_input_queue(irq_ptr, q, i) { | 983 | for_each_input_queue(irq_ptr, q, i) { |
@@ -1003,7 +1003,7 @@ static void qdio_int_handler_pci(struct qdio_irq *irq_ptr) | |||
1003 | continue; | 1003 | continue; |
1004 | if (need_siga_sync(q) && need_siga_sync_out_after_pci(q)) | 1004 | if (need_siga_sync(q) && need_siga_sync_out_after_pci(q)) |
1005 | qdio_siga_sync_q(q); | 1005 | qdio_siga_sync_q(q); |
1006 | tasklet_schedule(&q->tasklet); | 1006 | qdio_tasklet_schedule(q); |
1007 | } | 1007 | } |
1008 | } | 1008 | } |
1009 | 1009 | ||
@@ -1066,10 +1066,12 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm, | |||
1066 | struct irb *irb) | 1066 | struct irb *irb) |
1067 | { | 1067 | { |
1068 | struct qdio_irq *irq_ptr = cdev->private->qdio_data; | 1068 | struct qdio_irq *irq_ptr = cdev->private->qdio_data; |
1069 | struct subchannel_id schid; | ||
1069 | int cstat, dstat; | 1070 | int cstat, dstat; |
1070 | 1071 | ||
1071 | if (!intparm || !irq_ptr) { | 1072 | if (!intparm || !irq_ptr) { |
1072 | DBF_ERROR("qint:%4x", cdev->private->schid.sch_no); | 1073 | ccw_device_get_schid(cdev, &schid); |
1074 | DBF_ERROR("qint:%4x", schid.sch_no); | ||
1073 | return; | 1075 | return; |
1074 | } | 1076 | } |
1075 | 1077 | ||
@@ -1122,12 +1124,14 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm, | |||
1122 | int qdio_get_ssqd_desc(struct ccw_device *cdev, | 1124 | int qdio_get_ssqd_desc(struct ccw_device *cdev, |
1123 | struct qdio_ssqd_desc *data) | 1125 | struct qdio_ssqd_desc *data) |
1124 | { | 1126 | { |
1127 | struct subchannel_id schid; | ||
1125 | 1128 | ||
1126 | if (!cdev || !cdev->private) | 1129 | if (!cdev || !cdev->private) |
1127 | return -EINVAL; | 1130 | return -EINVAL; |
1128 | 1131 | ||
1129 | DBF_EVENT("get ssqd:%4x", cdev->private->schid.sch_no); | 1132 | ccw_device_get_schid(cdev, &schid); |
1130 | return qdio_setup_get_ssqd(NULL, &cdev->private->schid, data); | 1133 | DBF_EVENT("get ssqd:%4x", schid.sch_no); |
1134 | return qdio_setup_get_ssqd(NULL, &schid, data); | ||
1131 | } | 1135 | } |
1132 | EXPORT_SYMBOL_GPL(qdio_get_ssqd_desc); | 1136 | EXPORT_SYMBOL_GPL(qdio_get_ssqd_desc); |
1133 | 1137 | ||
@@ -1141,7 +1145,7 @@ static void qdio_shutdown_queues(struct ccw_device *cdev) | |||
1141 | tasklet_kill(&q->tasklet); | 1145 | tasklet_kill(&q->tasklet); |
1142 | 1146 | ||
1143 | for_each_output_queue(irq_ptr, q, i) { | 1147 | for_each_output_queue(irq_ptr, q, i) { |
1144 | del_timer(&q->u.out.timer); | 1148 | del_timer_sync(&q->u.out.timer); |
1145 | tasklet_kill(&q->tasklet); | 1149 | tasklet_kill(&q->tasklet); |
1146 | } | 1150 | } |
1147 | } | 1151 | } |
@@ -1154,14 +1158,15 @@ static void qdio_shutdown_queues(struct ccw_device *cdev) | |||
1154 | int qdio_shutdown(struct ccw_device *cdev, int how) | 1158 | int qdio_shutdown(struct ccw_device *cdev, int how) |
1155 | { | 1159 | { |
1156 | struct qdio_irq *irq_ptr = cdev->private->qdio_data; | 1160 | struct qdio_irq *irq_ptr = cdev->private->qdio_data; |
1161 | struct subchannel_id schid; | ||
1157 | int rc; | 1162 | int rc; |
1158 | unsigned long flags; | ||
1159 | 1163 | ||
1160 | if (!irq_ptr) | 1164 | if (!irq_ptr) |
1161 | return -ENODEV; | 1165 | return -ENODEV; |
1162 | 1166 | ||
1163 | WARN_ON_ONCE(irqs_disabled()); | 1167 | WARN_ON_ONCE(irqs_disabled()); |
1164 | DBF_EVENT("qshutdown:%4x", cdev->private->schid.sch_no); | 1168 | ccw_device_get_schid(cdev, &schid); |
1169 | DBF_EVENT("qshutdown:%4x", schid.sch_no); | ||
1165 | 1170 | ||
1166 | mutex_lock(&irq_ptr->setup_mutex); | 1171 | mutex_lock(&irq_ptr->setup_mutex); |
1167 | /* | 1172 | /* |
@@ -1184,7 +1189,7 @@ int qdio_shutdown(struct ccw_device *cdev, int how) | |||
1184 | qdio_shutdown_debug_entries(irq_ptr); | 1189 | qdio_shutdown_debug_entries(irq_ptr); |
1185 | 1190 | ||
1186 | /* cleanup subchannel */ | 1191 | /* cleanup subchannel */ |
1187 | spin_lock_irqsave(get_ccwdev_lock(cdev), flags); | 1192 | spin_lock_irq(get_ccwdev_lock(cdev)); |
1188 | 1193 | ||
1189 | if (how & QDIO_FLAG_CLEANUP_USING_CLEAR) | 1194 | if (how & QDIO_FLAG_CLEANUP_USING_CLEAR) |
1190 | rc = ccw_device_clear(cdev, QDIO_DOING_CLEANUP); | 1195 | rc = ccw_device_clear(cdev, QDIO_DOING_CLEANUP); |
@@ -1198,12 +1203,12 @@ int qdio_shutdown(struct ccw_device *cdev, int how) | |||
1198 | } | 1203 | } |
1199 | 1204 | ||
1200 | qdio_set_state(irq_ptr, QDIO_IRQ_STATE_CLEANUP); | 1205 | qdio_set_state(irq_ptr, QDIO_IRQ_STATE_CLEANUP); |
1201 | spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); | 1206 | spin_unlock_irq(get_ccwdev_lock(cdev)); |
1202 | wait_event_interruptible_timeout(cdev->private->wait_q, | 1207 | wait_event_interruptible_timeout(cdev->private->wait_q, |
1203 | irq_ptr->state == QDIO_IRQ_STATE_INACTIVE || | 1208 | irq_ptr->state == QDIO_IRQ_STATE_INACTIVE || |
1204 | irq_ptr->state == QDIO_IRQ_STATE_ERR, | 1209 | irq_ptr->state == QDIO_IRQ_STATE_ERR, |
1205 | 10 * HZ); | 1210 | 10 * HZ); |
1206 | spin_lock_irqsave(get_ccwdev_lock(cdev), flags); | 1211 | spin_lock_irq(get_ccwdev_lock(cdev)); |
1207 | 1212 | ||
1208 | no_cleanup: | 1213 | no_cleanup: |
1209 | qdio_shutdown_thinint(irq_ptr); | 1214 | qdio_shutdown_thinint(irq_ptr); |
@@ -1211,7 +1216,7 @@ no_cleanup: | |||
1211 | /* restore interrupt handler */ | 1216 | /* restore interrupt handler */ |
1212 | if ((void *)cdev->handler == (void *)qdio_int_handler) | 1217 | if ((void *)cdev->handler == (void *)qdio_int_handler) |
1213 | cdev->handler = irq_ptr->orig_handler; | 1218 | cdev->handler = irq_ptr->orig_handler; |
1214 | spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); | 1219 | spin_unlock_irq(get_ccwdev_lock(cdev)); |
1215 | 1220 | ||
1216 | qdio_set_state(irq_ptr, QDIO_IRQ_STATE_INACTIVE); | 1221 | qdio_set_state(irq_ptr, QDIO_IRQ_STATE_INACTIVE); |
1217 | mutex_unlock(&irq_ptr->setup_mutex); | 1222 | mutex_unlock(&irq_ptr->setup_mutex); |
@@ -1228,11 +1233,13 @@ EXPORT_SYMBOL_GPL(qdio_shutdown); | |||
1228 | int qdio_free(struct ccw_device *cdev) | 1233 | int qdio_free(struct ccw_device *cdev) |
1229 | { | 1234 | { |
1230 | struct qdio_irq *irq_ptr = cdev->private->qdio_data; | 1235 | struct qdio_irq *irq_ptr = cdev->private->qdio_data; |
1236 | struct subchannel_id schid; | ||
1231 | 1237 | ||
1232 | if (!irq_ptr) | 1238 | if (!irq_ptr) |
1233 | return -ENODEV; | 1239 | return -ENODEV; |
1234 | 1240 | ||
1235 | DBF_EVENT("qfree:%4x", cdev->private->schid.sch_no); | 1241 | ccw_device_get_schid(cdev, &schid); |
1242 | DBF_EVENT("qfree:%4x", schid.sch_no); | ||
1236 | DBF_DEV_EVENT(DBF_ERR, irq_ptr, "dbf abandoned"); | 1243 | DBF_DEV_EVENT(DBF_ERR, irq_ptr, "dbf abandoned"); |
1237 | mutex_lock(&irq_ptr->setup_mutex); | 1244 | mutex_lock(&irq_ptr->setup_mutex); |
1238 | 1245 | ||
@@ -1251,9 +1258,11 @@ EXPORT_SYMBOL_GPL(qdio_free); | |||
1251 | */ | 1258 | */ |
1252 | int qdio_allocate(struct qdio_initialize *init_data) | 1259 | int qdio_allocate(struct qdio_initialize *init_data) |
1253 | { | 1260 | { |
1261 | struct subchannel_id schid; | ||
1254 | struct qdio_irq *irq_ptr; | 1262 | struct qdio_irq *irq_ptr; |
1255 | 1263 | ||
1256 | DBF_EVENT("qallocate:%4x", init_data->cdev->private->schid.sch_no); | 1264 | ccw_device_get_schid(init_data->cdev, &schid); |
1265 | DBF_EVENT("qallocate:%4x", schid.sch_no); | ||
1257 | 1266 | ||
1258 | if ((init_data->no_input_qs && !init_data->input_handler) || | 1267 | if ((init_data->no_input_qs && !init_data->input_handler) || |
1259 | (init_data->no_output_qs && !init_data->output_handler)) | 1268 | (init_data->no_output_qs && !init_data->output_handler)) |
@@ -1331,20 +1340,18 @@ static void qdio_detect_hsicq(struct qdio_irq *irq_ptr) | |||
1331 | */ | 1340 | */ |
1332 | int qdio_establish(struct qdio_initialize *init_data) | 1341 | int qdio_establish(struct qdio_initialize *init_data) |
1333 | { | 1342 | { |
1334 | struct qdio_irq *irq_ptr; | ||
1335 | struct ccw_device *cdev = init_data->cdev; | 1343 | struct ccw_device *cdev = init_data->cdev; |
1336 | unsigned long saveflags; | 1344 | struct subchannel_id schid; |
1345 | struct qdio_irq *irq_ptr; | ||
1337 | int rc; | 1346 | int rc; |
1338 | 1347 | ||
1339 | DBF_EVENT("qestablish:%4x", cdev->private->schid.sch_no); | 1348 | ccw_device_get_schid(cdev, &schid); |
1349 | DBF_EVENT("qestablish:%4x", schid.sch_no); | ||
1340 | 1350 | ||
1341 | irq_ptr = cdev->private->qdio_data; | 1351 | irq_ptr = cdev->private->qdio_data; |
1342 | if (!irq_ptr) | 1352 | if (!irq_ptr) |
1343 | return -ENODEV; | 1353 | return -ENODEV; |
1344 | 1354 | ||
1345 | if (cdev->private->state != DEV_STATE_ONLINE) | ||
1346 | return -EINVAL; | ||
1347 | |||
1348 | mutex_lock(&irq_ptr->setup_mutex); | 1355 | mutex_lock(&irq_ptr->setup_mutex); |
1349 | qdio_setup_irq(init_data); | 1356 | qdio_setup_irq(init_data); |
1350 | 1357 | ||
@@ -1361,17 +1368,14 @@ int qdio_establish(struct qdio_initialize *init_data) | |||
1361 | irq_ptr->ccw.count = irq_ptr->equeue.count; | 1368 | irq_ptr->ccw.count = irq_ptr->equeue.count; |
1362 | irq_ptr->ccw.cda = (u32)((addr_t)irq_ptr->qdr); | 1369 | irq_ptr->ccw.cda = (u32)((addr_t)irq_ptr->qdr); |
1363 | 1370 | ||
1364 | spin_lock_irqsave(get_ccwdev_lock(cdev), saveflags); | 1371 | spin_lock_irq(get_ccwdev_lock(cdev)); |
1365 | ccw_device_set_options_mask(cdev, 0); | 1372 | ccw_device_set_options_mask(cdev, 0); |
1366 | 1373 | ||
1367 | rc = ccw_device_start(cdev, &irq_ptr->ccw, QDIO_DOING_ESTABLISH, 0, 0); | 1374 | rc = ccw_device_start(cdev, &irq_ptr->ccw, QDIO_DOING_ESTABLISH, 0, 0); |
1375 | spin_unlock_irq(get_ccwdev_lock(cdev)); | ||
1368 | if (rc) { | 1376 | if (rc) { |
1369 | DBF_ERROR("%4x est IO ERR", irq_ptr->schid.sch_no); | 1377 | DBF_ERROR("%4x est IO ERR", irq_ptr->schid.sch_no); |
1370 | DBF_ERROR("rc:%4x", rc); | 1378 | DBF_ERROR("rc:%4x", rc); |
1371 | } | ||
1372 | spin_unlock_irqrestore(get_ccwdev_lock(cdev), saveflags); | ||
1373 | |||
1374 | if (rc) { | ||
1375 | mutex_unlock(&irq_ptr->setup_mutex); | 1379 | mutex_unlock(&irq_ptr->setup_mutex); |
1376 | qdio_shutdown(cdev, QDIO_FLAG_CLEANUP_USING_CLEAR); | 1380 | qdio_shutdown(cdev, QDIO_FLAG_CLEANUP_USING_CLEAR); |
1377 | return rc; | 1381 | return rc; |
@@ -1407,19 +1411,17 @@ EXPORT_SYMBOL_GPL(qdio_establish); | |||
1407 | */ | 1411 | */ |
1408 | int qdio_activate(struct ccw_device *cdev) | 1412 | int qdio_activate(struct ccw_device *cdev) |
1409 | { | 1413 | { |
1414 | struct subchannel_id schid; | ||
1410 | struct qdio_irq *irq_ptr; | 1415 | struct qdio_irq *irq_ptr; |
1411 | int rc; | 1416 | int rc; |
1412 | unsigned long saveflags; | ||
1413 | 1417 | ||
1414 | DBF_EVENT("qactivate:%4x", cdev->private->schid.sch_no); | 1418 | ccw_device_get_schid(cdev, &schid); |
1419 | DBF_EVENT("qactivate:%4x", schid.sch_no); | ||
1415 | 1420 | ||
1416 | irq_ptr = cdev->private->qdio_data; | 1421 | irq_ptr = cdev->private->qdio_data; |
1417 | if (!irq_ptr) | 1422 | if (!irq_ptr) |
1418 | return -ENODEV; | 1423 | return -ENODEV; |
1419 | 1424 | ||
1420 | if (cdev->private->state != DEV_STATE_ONLINE) | ||
1421 | return -EINVAL; | ||
1422 | |||
1423 | mutex_lock(&irq_ptr->setup_mutex); | 1425 | mutex_lock(&irq_ptr->setup_mutex); |
1424 | if (irq_ptr->state == QDIO_IRQ_STATE_INACTIVE) { | 1426 | if (irq_ptr->state == QDIO_IRQ_STATE_INACTIVE) { |
1425 | rc = -EBUSY; | 1427 | rc = -EBUSY; |
@@ -1431,19 +1433,17 @@ int qdio_activate(struct ccw_device *cdev) | |||
1431 | irq_ptr->ccw.count = irq_ptr->aqueue.count; | 1433 | irq_ptr->ccw.count = irq_ptr->aqueue.count; |
1432 | irq_ptr->ccw.cda = 0; | 1434 | irq_ptr->ccw.cda = 0; |
1433 | 1435 | ||
1434 | spin_lock_irqsave(get_ccwdev_lock(cdev), saveflags); | 1436 | spin_lock_irq(get_ccwdev_lock(cdev)); |
1435 | ccw_device_set_options(cdev, CCWDEV_REPORT_ALL); | 1437 | ccw_device_set_options(cdev, CCWDEV_REPORT_ALL); |
1436 | 1438 | ||
1437 | rc = ccw_device_start(cdev, &irq_ptr->ccw, QDIO_DOING_ACTIVATE, | 1439 | rc = ccw_device_start(cdev, &irq_ptr->ccw, QDIO_DOING_ACTIVATE, |
1438 | 0, DOIO_DENY_PREFETCH); | 1440 | 0, DOIO_DENY_PREFETCH); |
1441 | spin_unlock_irq(get_ccwdev_lock(cdev)); | ||
1439 | if (rc) { | 1442 | if (rc) { |
1440 | DBF_ERROR("%4x act IO ERR", irq_ptr->schid.sch_no); | 1443 | DBF_ERROR("%4x act IO ERR", irq_ptr->schid.sch_no); |
1441 | DBF_ERROR("rc:%4x", rc); | 1444 | DBF_ERROR("rc:%4x", rc); |
1442 | } | ||
1443 | spin_unlock_irqrestore(get_ccwdev_lock(cdev), saveflags); | ||
1444 | |||
1445 | if (rc) | ||
1446 | goto out; | 1445 | goto out; |
1446 | } | ||
1447 | 1447 | ||
1448 | if (is_thinint_irq(irq_ptr)) | 1448 | if (is_thinint_irq(irq_ptr)) |
1449 | tiqdio_add_input_queues(irq_ptr); | 1449 | tiqdio_add_input_queues(irq_ptr); |
@@ -1585,10 +1585,11 @@ static int handle_outbound(struct qdio_q *q, unsigned int callflags, | |||
1585 | 1585 | ||
1586 | /* in case of SIGA errors we must process the error immediately */ | 1586 | /* in case of SIGA errors we must process the error immediately */ |
1587 | if (used >= q->u.out.scan_threshold || rc) | 1587 | if (used >= q->u.out.scan_threshold || rc) |
1588 | tasklet_schedule(&q->tasklet); | 1588 | qdio_tasklet_schedule(q); |
1589 | else | 1589 | else |
1590 | /* free the SBALs in case of no further traffic */ | 1590 | /* free the SBALs in case of no further traffic */ |
1591 | if (!timer_pending(&q->u.out.timer)) | 1591 | if (!timer_pending(&q->u.out.timer) && |
1592 | likely(q->irq_ptr->state == QDIO_IRQ_STATE_ACTIVE)) | ||
1592 | mod_timer(&q->u.out.timer, jiffies + HZ); | 1593 | mod_timer(&q->u.out.timer, jiffies + HZ); |
1593 | return rc; | 1594 | return rc; |
1594 | } | 1595 | } |