diff options
Diffstat (limited to 'drivers/s390/cio')
-rw-r--r-- | drivers/s390/cio/chsc.c | 29 | ||||
-rw-r--r-- | drivers/s390/cio/chsc_sch.c | 3 | ||||
-rw-r--r-- | drivers/s390/cio/cio.c | 21 | ||||
-rw-r--r-- | drivers/s390/cio/css.c | 24 | ||||
-rw-r--r-- | drivers/s390/cio/device_fsm.c | 2 | ||||
-rw-r--r-- | drivers/s390/cio/qdio.h | 15 | ||||
-rw-r--r-- | drivers/s390/cio/qdio_main.c | 67 | ||||
-rw-r--r-- | drivers/s390/cio/qdio_setup.c | 8 | ||||
-rw-r--r-- | drivers/s390/cio/qdio_thinint.c | 4 |
9 files changed, 67 insertions, 106 deletions
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 4038f5b4f144..ce7cb87479fe 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include "chsc.h" | 29 | #include "chsc.h" |
30 | 30 | ||
31 | static void *sei_page; | 31 | static void *sei_page; |
32 | static DEFINE_SPINLOCK(sda_lock); | ||
32 | 33 | ||
33 | /** | 34 | /** |
34 | * chsc_error_from_response() - convert a chsc response to an error | 35 | * chsc_error_from_response() - convert a chsc response to an error |
@@ -832,11 +833,10 @@ void __init chsc_free_sei_area(void) | |||
832 | kfree(sei_page); | 833 | kfree(sei_page); |
833 | } | 834 | } |
834 | 835 | ||
835 | int __init | 836 | int chsc_enable_facility(int operation_code) |
836 | chsc_enable_facility(int operation_code) | ||
837 | { | 837 | { |
838 | int ret; | 838 | int ret; |
839 | struct { | 839 | static struct { |
840 | struct chsc_header request; | 840 | struct chsc_header request; |
841 | u8 reserved1:4; | 841 | u8 reserved1:4; |
842 | u8 format:4; | 842 | u8 format:4; |
@@ -849,33 +849,32 @@ chsc_enable_facility(int operation_code) | |||
849 | u32 reserved5:4; | 849 | u32 reserved5:4; |
850 | u32 format2:4; | 850 | u32 format2:4; |
851 | u32 reserved6:24; | 851 | u32 reserved6:24; |
852 | } __attribute__ ((packed)) *sda_area; | 852 | } __attribute__ ((packed, aligned(4096))) sda_area; |
853 | 853 | ||
854 | sda_area = (void *)get_zeroed_page(GFP_KERNEL|GFP_DMA); | 854 | spin_lock(&sda_lock); |
855 | if (!sda_area) | 855 | memset(&sda_area, 0, sizeof(sda_area)); |
856 | return -ENOMEM; | 856 | sda_area.request.length = 0x0400; |
857 | sda_area->request.length = 0x0400; | 857 | sda_area.request.code = 0x0031; |
858 | sda_area->request.code = 0x0031; | 858 | sda_area.operation_code = operation_code; |
859 | sda_area->operation_code = operation_code; | ||
860 | 859 | ||
861 | ret = chsc(sda_area); | 860 | ret = chsc(&sda_area); |
862 | if (ret > 0) { | 861 | if (ret > 0) { |
863 | ret = (ret == 3) ? -ENODEV : -EBUSY; | 862 | ret = (ret == 3) ? -ENODEV : -EBUSY; |
864 | goto out; | 863 | goto out; |
865 | } | 864 | } |
866 | 865 | ||
867 | switch (sda_area->response.code) { | 866 | switch (sda_area.response.code) { |
868 | case 0x0101: | 867 | case 0x0101: |
869 | ret = -EOPNOTSUPP; | 868 | ret = -EOPNOTSUPP; |
870 | break; | 869 | break; |
871 | default: | 870 | default: |
872 | ret = chsc_error_from_response(sda_area->response.code); | 871 | ret = chsc_error_from_response(sda_area.response.code); |
873 | } | 872 | } |
874 | if (ret != 0) | 873 | if (ret != 0) |
875 | CIO_CRW_EVENT(2, "chsc: sda (oc=%x) failed (rc=%04x)\n", | 874 | CIO_CRW_EVENT(2, "chsc: sda (oc=%x) failed (rc=%04x)\n", |
876 | operation_code, sda_area->response.code); | 875 | operation_code, sda_area.response.code); |
877 | out: | 876 | out: |
878 | free_page((unsigned long)sda_area); | 877 | spin_unlock(&sda_lock); |
879 | return ret; | 878 | return ret; |
880 | } | 879 | } |
881 | 880 | ||
diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c index 404f630c27ca..a83877c664a6 100644 --- a/drivers/s390/cio/chsc_sch.c +++ b/drivers/s390/cio/chsc_sch.c | |||
@@ -124,7 +124,7 @@ static int chsc_subchannel_prepare(struct subchannel *sch) | |||
124 | * since we don't have a way to clear the subchannel and | 124 | * since we don't have a way to clear the subchannel and |
125 | * cannot disable it with a request running. | 125 | * cannot disable it with a request running. |
126 | */ | 126 | */ |
127 | cc = stsch(sch->schid, &schib); | 127 | cc = stsch_err(sch->schid, &schib); |
128 | if (!cc && scsw_stctl(&schib.scsw)) | 128 | if (!cc && scsw_stctl(&schib.scsw)) |
129 | return -EAGAIN; | 129 | return -EAGAIN; |
130 | return 0; | 130 | return 0; |
@@ -803,6 +803,7 @@ static long chsc_ioctl(struct file *filp, unsigned int cmd, | |||
803 | 803 | ||
804 | static const struct file_operations chsc_fops = { | 804 | static const struct file_operations chsc_fops = { |
805 | .owner = THIS_MODULE, | 805 | .owner = THIS_MODULE, |
806 | .open = nonseekable_open, | ||
806 | .unlocked_ioctl = chsc_ioctl, | 807 | .unlocked_ioctl = chsc_ioctl, |
807 | .compat_ioctl = chsc_ioctl, | 808 | .compat_ioctl = chsc_ioctl, |
808 | }; | 809 | }; |
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index f736cdcf08ad..f4e6cf3aceb8 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c | |||
@@ -361,7 +361,7 @@ int cio_commit_config(struct subchannel *sch) | |||
361 | struct schib schib; | 361 | struct schib schib; |
362 | int ccode, retry, ret = 0; | 362 | int ccode, retry, ret = 0; |
363 | 363 | ||
364 | if (stsch(sch->schid, &schib) || !css_sch_is_valid(&schib)) | 364 | if (stsch_err(sch->schid, &schib) || !css_sch_is_valid(&schib)) |
365 | return -ENODEV; | 365 | return -ENODEV; |
366 | 366 | ||
367 | for (retry = 0; retry < 5; retry++) { | 367 | for (retry = 0; retry < 5; retry++) { |
@@ -372,7 +372,7 @@ int cio_commit_config(struct subchannel *sch) | |||
372 | return ccode; | 372 | return ccode; |
373 | switch (ccode) { | 373 | switch (ccode) { |
374 | case 0: /* successful */ | 374 | case 0: /* successful */ |
375 | if (stsch(sch->schid, &schib) || | 375 | if (stsch_err(sch->schid, &schib) || |
376 | !css_sch_is_valid(&schib)) | 376 | !css_sch_is_valid(&schib)) |
377 | return -ENODEV; | 377 | return -ENODEV; |
378 | if (cio_check_config(sch, &schib)) { | 378 | if (cio_check_config(sch, &schib)) { |
@@ -404,7 +404,7 @@ int cio_update_schib(struct subchannel *sch) | |||
404 | { | 404 | { |
405 | struct schib schib; | 405 | struct schib schib; |
406 | 406 | ||
407 | if (stsch(sch->schid, &schib) || !css_sch_is_valid(&schib)) | 407 | if (stsch_err(sch->schid, &schib) || !css_sch_is_valid(&schib)) |
408 | return -ENODEV; | 408 | return -ENODEV; |
409 | 409 | ||
410 | memcpy(&sch->schib, &schib, sizeof(schib)); | 410 | memcpy(&sch->schib, &schib, sizeof(schib)); |
@@ -616,7 +616,8 @@ void __irq_entry do_IRQ(struct pt_regs *regs) | |||
616 | struct pt_regs *old_regs; | 616 | struct pt_regs *old_regs; |
617 | 617 | ||
618 | old_regs = set_irq_regs(regs); | 618 | old_regs = set_irq_regs(regs); |
619 | s390_idle_check(); | 619 | s390_idle_check(regs, S390_lowcore.int_clock, |
620 | S390_lowcore.async_enter_timer); | ||
620 | irq_enter(); | 621 | irq_enter(); |
621 | __get_cpu_var(s390_idle).nohz_delay = 1; | 622 | __get_cpu_var(s390_idle).nohz_delay = 1; |
622 | if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator) | 623 | if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator) |
@@ -771,7 +772,7 @@ cio_get_console_sch_no(void) | |||
771 | if (console_irq != -1) { | 772 | if (console_irq != -1) { |
772 | /* VM provided us with the irq number of the console. */ | 773 | /* VM provided us with the irq number of the console. */ |
773 | schid.sch_no = console_irq; | 774 | schid.sch_no = console_irq; |
774 | if (stsch(schid, &console_subchannel.schib) != 0 || | 775 | if (stsch_err(schid, &console_subchannel.schib) != 0 || |
775 | (console_subchannel.schib.pmcw.st != SUBCHANNEL_TYPE_IO) || | 776 | (console_subchannel.schib.pmcw.st != SUBCHANNEL_TYPE_IO) || |
776 | !console_subchannel.schib.pmcw.dnv) | 777 | !console_subchannel.schib.pmcw.dnv) |
777 | return -1; | 778 | return -1; |
@@ -863,10 +864,10 @@ __disable_subchannel_easy(struct subchannel_id schid, struct schib *schib) | |||
863 | cc = 0; | 864 | cc = 0; |
864 | for (retry=0;retry<3;retry++) { | 865 | for (retry=0;retry<3;retry++) { |
865 | schib->pmcw.ena = 0; | 866 | schib->pmcw.ena = 0; |
866 | cc = msch(schid, schib); | 867 | cc = msch_err(schid, schib); |
867 | if (cc) | 868 | if (cc) |
868 | return (cc==3?-ENODEV:-EBUSY); | 869 | return (cc==3?-ENODEV:-EBUSY); |
869 | if (stsch(schid, schib) || !css_sch_is_valid(schib)) | 870 | if (stsch_err(schid, schib) || !css_sch_is_valid(schib)) |
870 | return -ENODEV; | 871 | return -ENODEV; |
871 | if (!schib->pmcw.ena) | 872 | if (!schib->pmcw.ena) |
872 | return 0; | 873 | return 0; |
@@ -913,7 +914,7 @@ static int stsch_reset(struct subchannel_id schid, struct schib *addr) | |||
913 | 914 | ||
914 | pgm_check_occured = 0; | 915 | pgm_check_occured = 0; |
915 | s390_base_pgm_handler_fn = cio_reset_pgm_check_handler; | 916 | s390_base_pgm_handler_fn = cio_reset_pgm_check_handler; |
916 | rc = stsch(schid, addr); | 917 | rc = stsch_err(schid, addr); |
917 | s390_base_pgm_handler_fn = NULL; | 918 | s390_base_pgm_handler_fn = NULL; |
918 | 919 | ||
919 | /* The program check handler could have changed pgm_check_occured. */ | 920 | /* The program check handler could have changed pgm_check_occured. */ |
@@ -950,7 +951,7 @@ static int __shutdown_subchannel_easy(struct subchannel_id schid, void *data) | |||
950 | /* No default clear strategy */ | 951 | /* No default clear strategy */ |
951 | break; | 952 | break; |
952 | } | 953 | } |
953 | stsch(schid, &schib); | 954 | stsch_err(schid, &schib); |
954 | __disable_subchannel_easy(schid, &schib); | 955 | __disable_subchannel_easy(schid, &schib); |
955 | } | 956 | } |
956 | out: | 957 | out: |
@@ -1086,7 +1087,7 @@ int __init cio_get_iplinfo(struct cio_iplinfo *iplinfo) | |||
1086 | schid = *(struct subchannel_id *)&S390_lowcore.subchannel_id; | 1087 | schid = *(struct subchannel_id *)&S390_lowcore.subchannel_id; |
1087 | if (!schid.one) | 1088 | if (!schid.one) |
1088 | return -ENODEV; | 1089 | return -ENODEV; |
1089 | if (stsch(schid, &schib)) | 1090 | if (stsch_err(schid, &schib)) |
1090 | return -ENODEV; | 1091 | return -ENODEV; |
1091 | if (schib.pmcw.st != SUBCHANNEL_TYPE_IO) | 1092 | if (schib.pmcw.st != SUBCHANNEL_TYPE_IO) |
1092 | return -ENODEV; | 1093 | return -ENODEV; |
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 2769da54f2b9..ac94ac751459 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c | |||
@@ -648,6 +648,8 @@ static void css_process_crw(struct crw *crw0, struct crw *crw1, int overflow) | |||
648 | static void __init | 648 | static void __init |
649 | css_generate_pgid(struct channel_subsystem *css, u32 tod_high) | 649 | css_generate_pgid(struct channel_subsystem *css, u32 tod_high) |
650 | { | 650 | { |
651 | struct cpuid cpu_id; | ||
652 | |||
651 | if (css_general_characteristics.mcss) { | 653 | if (css_general_characteristics.mcss) { |
652 | css->global_pgid.pgid_high.ext_cssid.version = 0x80; | 654 | css->global_pgid.pgid_high.ext_cssid.version = 0x80; |
653 | css->global_pgid.pgid_high.ext_cssid.cssid = css->cssid; | 655 | css->global_pgid.pgid_high.ext_cssid.cssid = css->cssid; |
@@ -658,8 +660,9 @@ css_generate_pgid(struct channel_subsystem *css, u32 tod_high) | |||
658 | css->global_pgid.pgid_high.cpu_addr = 0; | 660 | css->global_pgid.pgid_high.cpu_addr = 0; |
659 | #endif | 661 | #endif |
660 | } | 662 | } |
661 | css->global_pgid.cpu_id = S390_lowcore.cpu_id.ident; | 663 | get_cpu_id(&cpu_id); |
662 | css->global_pgid.cpu_model = S390_lowcore.cpu_id.machine; | 664 | css->global_pgid.cpu_id = cpu_id.ident; |
665 | css->global_pgid.cpu_model = cpu_id.machine; | ||
663 | css->global_pgid.tod_high = tod_high; | 666 | css->global_pgid.tod_high = tod_high; |
664 | 667 | ||
665 | } | 668 | } |
@@ -870,15 +873,10 @@ static int __init css_bus_init(void) | |||
870 | 873 | ||
871 | /* Try to enable MSS. */ | 874 | /* Try to enable MSS. */ |
872 | ret = chsc_enable_facility(CHSC_SDA_OC_MSS); | 875 | ret = chsc_enable_facility(CHSC_SDA_OC_MSS); |
873 | switch (ret) { | 876 | if (ret) |
874 | case 0: /* Success. */ | ||
875 | max_ssid = __MAX_SSID; | ||
876 | break; | ||
877 | case -ENOMEM: | ||
878 | goto out; | ||
879 | default: | ||
880 | max_ssid = 0; | 877 | max_ssid = 0; |
881 | } | 878 | else /* Success. */ |
879 | max_ssid = __MAX_SSID; | ||
882 | 880 | ||
883 | ret = slow_subchannel_init(); | 881 | ret = slow_subchannel_init(); |
884 | if (ret) | 882 | if (ret) |
@@ -1048,6 +1046,11 @@ static int __init channel_subsystem_init_sync(void) | |||
1048 | } | 1046 | } |
1049 | subsys_initcall_sync(channel_subsystem_init_sync); | 1047 | subsys_initcall_sync(channel_subsystem_init_sync); |
1050 | 1048 | ||
1049 | void channel_subsystem_reinit(void) | ||
1050 | { | ||
1051 | chsc_enable_facility(CHSC_SDA_OC_MSS); | ||
1052 | } | ||
1053 | |||
1051 | #ifdef CONFIG_PROC_FS | 1054 | #ifdef CONFIG_PROC_FS |
1052 | static ssize_t cio_settle_write(struct file *file, const char __user *buf, | 1055 | static ssize_t cio_settle_write(struct file *file, const char __user *buf, |
1053 | size_t count, loff_t *ppos) | 1056 | size_t count, loff_t *ppos) |
@@ -1062,6 +1065,7 @@ static ssize_t cio_settle_write(struct file *file, const char __user *buf, | |||
1062 | } | 1065 | } |
1063 | 1066 | ||
1064 | static const struct file_operations cio_settle_proc_fops = { | 1067 | static const struct file_operations cio_settle_proc_fops = { |
1068 | .open = nonseekable_open, | ||
1065 | .write = cio_settle_write, | 1069 | .write = cio_settle_write, |
1066 | }; | 1070 | }; |
1067 | 1071 | ||
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index c56ab94612f9..c9b852647f01 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c | |||
@@ -45,7 +45,7 @@ static void ccw_timeout_log(struct ccw_device *cdev) | |||
45 | sch = to_subchannel(cdev->dev.parent); | 45 | sch = to_subchannel(cdev->dev.parent); |
46 | private = to_io_private(sch); | 46 | private = to_io_private(sch); |
47 | orb = &private->orb; | 47 | orb = &private->orb; |
48 | cc = stsch(sch->schid, &schib); | 48 | cc = stsch_err(sch->schid, &schib); |
49 | 49 | ||
50 | printk(KERN_WARNING "cio: ccw device timeout occurred at %llx, " | 50 | printk(KERN_WARNING "cio: ccw device timeout occurred at %llx, " |
51 | "device information:\n", get_clock()); | 51 | "device information:\n", get_clock()); |
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index 48aa0647432b..f0037eefd44e 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h | |||
@@ -13,8 +13,8 @@ | |||
13 | #include <asm/debug.h> | 13 | #include <asm/debug.h> |
14 | #include "chsc.h" | 14 | #include "chsc.h" |
15 | 15 | ||
16 | #define QDIO_BUSY_BIT_PATIENCE 100 /* 100 microseconds */ | 16 | #define QDIO_BUSY_BIT_PATIENCE (100 << 12) /* 100 microseconds */ |
17 | #define QDIO_INPUT_THRESHOLD 500 /* 500 microseconds */ | 17 | #define QDIO_INPUT_THRESHOLD (500 << 12) /* 500 microseconds */ |
18 | 18 | ||
19 | /* | 19 | /* |
20 | * if an asynchronous HiperSockets queue runs full, the 10 seconds timer wait | 20 | * if an asynchronous HiperSockets queue runs full, the 10 seconds timer wait |
@@ -296,10 +296,8 @@ struct qdio_q { | |||
296 | struct qdio_irq *irq_ptr; | 296 | struct qdio_irq *irq_ptr; |
297 | struct sl *sl; | 297 | struct sl *sl; |
298 | /* | 298 | /* |
299 | * Warning: Leave this member at the end so it won't be cleared in | 299 | * A page is allocated under this pointer and used for slib and sl. |
300 | * qdio_fill_qs. A page is allocated under this pointer and used for | 300 | * slib is 2048 bytes big and sl points to offset PAGE_SIZE / 2. |
301 | * slib and sl. slib is 2048 bytes big and sl points to offset | ||
302 | * PAGE_SIZE / 2. | ||
303 | */ | 301 | */ |
304 | struct slib *slib; | 302 | struct slib *slib; |
305 | } __attribute__ ((aligned(256))); | 303 | } __attribute__ ((aligned(256))); |
@@ -372,11 +370,6 @@ static inline int multicast_outbound(struct qdio_q *q) | |||
372 | (q->nr == q->irq_ptr->nr_output_qs - 1); | 370 | (q->nr == q->irq_ptr->nr_output_qs - 1); |
373 | } | 371 | } |
374 | 372 | ||
375 | static inline unsigned long long get_usecs(void) | ||
376 | { | ||
377 | return monotonic_clock() >> 12; | ||
378 | } | ||
379 | |||
380 | #define pci_out_supported(q) \ | 373 | #define pci_out_supported(q) \ |
381 | (q->irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED) | 374 | (q->irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED) |
382 | #define is_qebsm(q) (q->irq_ptr->sch_token != 0) | 375 | #define is_qebsm(q) (q->irq_ptr->sch_token != 0) |
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 88be7b9ea6e1..00520f9a7a8e 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c | |||
@@ -336,10 +336,10 @@ again: | |||
336 | WARN_ON(queue_type(q) != QDIO_IQDIO_QFMT || cc != 2); | 336 | WARN_ON(queue_type(q) != QDIO_IQDIO_QFMT || cc != 2); |
337 | 337 | ||
338 | if (!start_time) { | 338 | if (!start_time) { |
339 | start_time = get_usecs(); | 339 | start_time = get_clock(); |
340 | goto again; | 340 | goto again; |
341 | } | 341 | } |
342 | if ((get_usecs() - start_time) < QDIO_BUSY_BIT_PATIENCE) | 342 | if ((get_clock() - start_time) < QDIO_BUSY_BIT_PATIENCE) |
343 | goto again; | 343 | goto again; |
344 | } | 344 | } |
345 | return cc; | 345 | return cc; |
@@ -536,7 +536,7 @@ static int qdio_inbound_q_moved(struct qdio_q *q) | |||
536 | if ((bufnr != q->last_move) || q->qdio_error) { | 536 | if ((bufnr != q->last_move) || q->qdio_error) { |
537 | q->last_move = bufnr; | 537 | q->last_move = bufnr; |
538 | if (!is_thinint_irq(q->irq_ptr) && MACHINE_IS_LPAR) | 538 | if (!is_thinint_irq(q->irq_ptr) && MACHINE_IS_LPAR) |
539 | q->u.in.timestamp = get_usecs(); | 539 | q->u.in.timestamp = get_clock(); |
540 | return 1; | 540 | return 1; |
541 | } else | 541 | } else |
542 | return 0; | 542 | return 0; |
@@ -567,7 +567,7 @@ static inline int qdio_inbound_q_done(struct qdio_q *q) | |||
567 | * At this point we know, that inbound first_to_check | 567 | * At this point we know, that inbound first_to_check |
568 | * has (probably) not moved (see qdio_inbound_processing). | 568 | * has (probably) not moved (see qdio_inbound_processing). |
569 | */ | 569 | */ |
570 | if (get_usecs() > q->u.in.timestamp + QDIO_INPUT_THRESHOLD) { | 570 | if (get_clock() > q->u.in.timestamp + QDIO_INPUT_THRESHOLD) { |
571 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in done:%02x", | 571 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in done:%02x", |
572 | q->first_to_check); | 572 | q->first_to_check); |
573 | return 1; | 573 | return 1; |
@@ -606,7 +606,7 @@ static void qdio_kick_handler(struct qdio_q *q) | |||
606 | static void __qdio_inbound_processing(struct qdio_q *q) | 606 | static void __qdio_inbound_processing(struct qdio_q *q) |
607 | { | 607 | { |
608 | qperf_inc(q, tasklet_inbound); | 608 | qperf_inc(q, tasklet_inbound); |
609 | again: | 609 | |
610 | if (!qdio_inbound_q_moved(q)) | 610 | if (!qdio_inbound_q_moved(q)) |
611 | return; | 611 | return; |
612 | 612 | ||
@@ -615,7 +615,10 @@ again: | |||
615 | if (!qdio_inbound_q_done(q)) { | 615 | if (!qdio_inbound_q_done(q)) { |
616 | /* means poll time is not yet over */ | 616 | /* means poll time is not yet over */ |
617 | qperf_inc(q, tasklet_inbound_resched); | 617 | qperf_inc(q, tasklet_inbound_resched); |
618 | goto again; | 618 | if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED)) { |
619 | tasklet_schedule(&q->tasklet); | ||
620 | return; | ||
621 | } | ||
619 | } | 622 | } |
620 | 623 | ||
621 | qdio_stop_polling(q); | 624 | qdio_stop_polling(q); |
@@ -625,7 +628,8 @@ again: | |||
625 | */ | 628 | */ |
626 | if (!qdio_inbound_q_done(q)) { | 629 | if (!qdio_inbound_q_done(q)) { |
627 | qperf_inc(q, tasklet_inbound_resched2); | 630 | qperf_inc(q, tasklet_inbound_resched2); |
628 | goto again; | 631 | if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED)) |
632 | tasklet_schedule(&q->tasklet); | ||
629 | } | 633 | } |
630 | } | 634 | } |
631 | 635 | ||
@@ -955,6 +959,9 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm, | |||
955 | return; | 959 | return; |
956 | } | 960 | } |
957 | 961 | ||
962 | if (irq_ptr->perf_stat_enabled) | ||
963 | irq_ptr->perf_stat.qdio_int++; | ||
964 | |||
958 | if (IS_ERR(irb)) { | 965 | if (IS_ERR(irb)) { |
959 | switch (PTR_ERR(irb)) { | 966 | switch (PTR_ERR(irb)) { |
960 | case -EIO: | 967 | case -EIO: |
@@ -1016,30 +1023,6 @@ int qdio_get_ssqd_desc(struct ccw_device *cdev, | |||
1016 | } | 1023 | } |
1017 | EXPORT_SYMBOL_GPL(qdio_get_ssqd_desc); | 1024 | EXPORT_SYMBOL_GPL(qdio_get_ssqd_desc); |
1018 | 1025 | ||
1019 | /** | ||
1020 | * qdio_cleanup - shutdown queues and free data structures | ||
1021 | * @cdev: associated ccw device | ||
1022 | * @how: use halt or clear to shutdown | ||
1023 | * | ||
1024 | * This function calls qdio_shutdown() for @cdev with method @how. | ||
1025 | * and qdio_free(). The qdio_free() return value is ignored since | ||
1026 | * !irq_ptr is already checked. | ||
1027 | */ | ||
1028 | int qdio_cleanup(struct ccw_device *cdev, int how) | ||
1029 | { | ||
1030 | struct qdio_irq *irq_ptr = cdev->private->qdio_data; | ||
1031 | int rc; | ||
1032 | |||
1033 | if (!irq_ptr) | ||
1034 | return -ENODEV; | ||
1035 | |||
1036 | rc = qdio_shutdown(cdev, how); | ||
1037 | |||
1038 | qdio_free(cdev); | ||
1039 | return rc; | ||
1040 | } | ||
1041 | EXPORT_SYMBOL_GPL(qdio_cleanup); | ||
1042 | |||
1043 | static void qdio_shutdown_queues(struct ccw_device *cdev) | 1026 | static void qdio_shutdown_queues(struct ccw_device *cdev) |
1044 | { | 1027 | { |
1045 | struct qdio_irq *irq_ptr = cdev->private->qdio_data; | 1028 | struct qdio_irq *irq_ptr = cdev->private->qdio_data; |
@@ -1157,28 +1140,6 @@ int qdio_free(struct ccw_device *cdev) | |||
1157 | EXPORT_SYMBOL_GPL(qdio_free); | 1140 | EXPORT_SYMBOL_GPL(qdio_free); |
1158 | 1141 | ||
1159 | /** | 1142 | /** |
1160 | * qdio_initialize - allocate and establish queues for a qdio subchannel | ||
1161 | * @init_data: initialization data | ||
1162 | * | ||
1163 | * This function first allocates queues via qdio_allocate() and on success | ||
1164 | * establishes them via qdio_establish(). | ||
1165 | */ | ||
1166 | int qdio_initialize(struct qdio_initialize *init_data) | ||
1167 | { | ||
1168 | int rc; | ||
1169 | |||
1170 | rc = qdio_allocate(init_data); | ||
1171 | if (rc) | ||
1172 | return rc; | ||
1173 | |||
1174 | rc = qdio_establish(init_data); | ||
1175 | if (rc) | ||
1176 | qdio_free(init_data->cdev); | ||
1177 | return rc; | ||
1178 | } | ||
1179 | EXPORT_SYMBOL_GPL(qdio_initialize); | ||
1180 | |||
1181 | /** | ||
1182 | * qdio_allocate - allocate qdio queues and associated data | 1143 | * qdio_allocate - allocate qdio queues and associated data |
1183 | * @init_data: initialization data | 1144 | * @init_data: initialization data |
1184 | */ | 1145 | */ |
diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c index 7f4a75465140..6326b67c45d2 100644 --- a/drivers/s390/cio/qdio_setup.c +++ b/drivers/s390/cio/qdio_setup.c | |||
@@ -106,10 +106,12 @@ int qdio_allocate_qs(struct qdio_irq *irq_ptr, int nr_input_qs, int nr_output_qs | |||
106 | static void setup_queues_misc(struct qdio_q *q, struct qdio_irq *irq_ptr, | 106 | static void setup_queues_misc(struct qdio_q *q, struct qdio_irq *irq_ptr, |
107 | qdio_handler_t *handler, int i) | 107 | qdio_handler_t *handler, int i) |
108 | { | 108 | { |
109 | /* must be cleared by every qdio_establish */ | 109 | struct slib *slib = q->slib; |
110 | memset(q, 0, ((char *)&q->slib) - ((char *)q)); | ||
111 | memset(q->slib, 0, PAGE_SIZE); | ||
112 | 110 | ||
111 | /* queue must be cleared for qdio_establish */ | ||
112 | memset(q, 0, sizeof(*q)); | ||
113 | memset(slib, 0, PAGE_SIZE); | ||
114 | q->slib = slib; | ||
113 | q->irq_ptr = irq_ptr; | 115 | q->irq_ptr = irq_ptr; |
114 | q->mask = 1 << (31 - i); | 116 | q->mask = 1 << (31 - i); |
115 | q->nr = i; | 117 | q->nr = i; |
diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c index ce5f8910ff83..8daf1b99f153 100644 --- a/drivers/s390/cio/qdio_thinint.c +++ b/drivers/s390/cio/qdio_thinint.c | |||
@@ -95,7 +95,7 @@ void tiqdio_add_input_queues(struct qdio_irq *irq_ptr) | |||
95 | for_each_input_queue(irq_ptr, q, i) | 95 | for_each_input_queue(irq_ptr, q, i) |
96 | list_add_rcu(&q->entry, &tiq_list); | 96 | list_add_rcu(&q->entry, &tiq_list); |
97 | mutex_unlock(&tiq_list_lock); | 97 | mutex_unlock(&tiq_list_lock); |
98 | xchg(irq_ptr->dsci, 1); | 98 | xchg(irq_ptr->dsci, 1 << 7); |
99 | } | 99 | } |
100 | 100 | ||
101 | void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr) | 101 | void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr) |
@@ -173,7 +173,7 @@ static void tiqdio_thinint_handler(void *ind, void *drv_data) | |||
173 | 173 | ||
174 | /* prevent racing */ | 174 | /* prevent racing */ |
175 | if (*tiqdio_alsi) | 175 | if (*tiqdio_alsi) |
176 | xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 1); | 176 | xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 1 << 7); |
177 | } | 177 | } |
178 | } | 178 | } |
179 | 179 | ||