diff options
author | Cornelia Huck <cohuck@de.ibm.com> | 2006-01-06 03:19:25 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-06 11:33:52 -0500 |
commit | fb6958a594da49ece869793e6ec163b89fc5f79f (patch) | |
tree | 0746cc23ab13a059f9a34d7fc134aaf6410d07b8 /drivers/s390/cio/qdio.c | |
parent | 678a395b356a98368a93c3640252502b70c3676f (diff) |
[PATCH] s390: multiple subchannel sets support
Add support for multiple subchannel sets. Works with arbitrary devices in
subchannel set 1 and is transparent to device drivers. Although currently
only two subchannel sets are available, this will work with the architectured
maximum number of subchannel sets as well.
Signed-off-by: Cornelia Huck <cohuck@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/s390/cio/qdio.c')
-rw-r--r-- | drivers/s390/cio/qdio.c | 81 |
1 files changed, 48 insertions, 33 deletions
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c index 5c7001b5c7a1..035c77af9cd3 100644 --- a/drivers/s390/cio/qdio.c +++ b/drivers/s390/cio/qdio.c | |||
@@ -56,7 +56,7 @@ | |||
56 | #include "ioasm.h" | 56 | #include "ioasm.h" |
57 | #include "chsc.h" | 57 | #include "chsc.h" |
58 | 58 | ||
59 | #define VERSION_QDIO_C "$Revision: 1.113 $" | 59 | #define VERSION_QDIO_C "$Revision: 1.114 $" |
60 | 60 | ||
61 | /****************** MODULE PARAMETER VARIABLES ********************/ | 61 | /****************** MODULE PARAMETER VARIABLES ********************/ |
62 | MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>"); | 62 | MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>"); |
@@ -2066,21 +2066,22 @@ qdio_timeout_handler(struct ccw_device *cdev) | |||
2066 | 2066 | ||
2067 | switch (irq_ptr->state) { | 2067 | switch (irq_ptr->state) { |
2068 | case QDIO_IRQ_STATE_INACTIVE: | 2068 | case QDIO_IRQ_STATE_INACTIVE: |
2069 | QDIO_PRINT_ERR("establish queues on irq %04x: timed out\n", | 2069 | QDIO_PRINT_ERR("establish queues on irq 0.%x.%04x: timed out\n", |
2070 | irq_ptr->schid.sch_no); | 2070 | irq_ptr->schid.ssid, irq_ptr->schid.sch_no); |
2071 | QDIO_DBF_TEXT2(1,setup,"eq:timeo"); | 2071 | QDIO_DBF_TEXT2(1,setup,"eq:timeo"); |
2072 | qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR); | 2072 | qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR); |
2073 | break; | 2073 | break; |
2074 | case QDIO_IRQ_STATE_CLEANUP: | 2074 | case QDIO_IRQ_STATE_CLEANUP: |
2075 | QDIO_PRINT_INFO("Did not get interrupt on cleanup, irq=0x%x.\n", | 2075 | QDIO_PRINT_INFO("Did not get interrupt on cleanup, " |
2076 | irq_ptr->schid.sch_no); | 2076 | "irq=0.%x.%x.\n", |
2077 | irq_ptr->schid.ssid, irq_ptr->schid.sch_no); | ||
2077 | qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR); | 2078 | qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR); |
2078 | break; | 2079 | break; |
2079 | case QDIO_IRQ_STATE_ESTABLISHED: | 2080 | case QDIO_IRQ_STATE_ESTABLISHED: |
2080 | case QDIO_IRQ_STATE_ACTIVE: | 2081 | case QDIO_IRQ_STATE_ACTIVE: |
2081 | /* I/O has been terminated by common I/O layer. */ | 2082 | /* I/O has been terminated by common I/O layer. */ |
2082 | QDIO_PRINT_INFO("Queues on irq %04x killed by cio.\n", | 2083 | QDIO_PRINT_INFO("Queues on irq 0.%x.%04x killed by cio.\n", |
2083 | irq_ptr->schid.sch_no); | 2084 | irq_ptr->schid.ssid, irq_ptr->schid.sch_no); |
2084 | QDIO_DBF_TEXT2(1, trace, "cio:term"); | 2085 | QDIO_DBF_TEXT2(1, trace, "cio:term"); |
2085 | qdio_set_state(irq_ptr, QDIO_IRQ_STATE_STOPPED); | 2086 | qdio_set_state(irq_ptr, QDIO_IRQ_STATE_STOPPED); |
2086 | if (get_device(&cdev->dev)) { | 2087 | if (get_device(&cdev->dev)) { |
@@ -2273,7 +2274,9 @@ qdio_get_ssqd_information(struct qdio_irq *irq_ptr) | |||
2273 | unsigned char qdioac; | 2274 | unsigned char qdioac; |
2274 | struct { | 2275 | struct { |
2275 | struct chsc_header request; | 2276 | struct chsc_header request; |
2276 | u16 reserved1; | 2277 | u16 reserved1:10; |
2278 | u16 ssid:2; | ||
2279 | u16 fmt:4; | ||
2277 | u16 first_sch; | 2280 | u16 first_sch; |
2278 | u16 reserved2; | 2281 | u16 reserved2; |
2279 | u16 last_sch; | 2282 | u16 last_sch; |
@@ -2318,12 +2321,13 @@ qdio_get_ssqd_information(struct qdio_irq *irq_ptr) | |||
2318 | }; | 2321 | }; |
2319 | ssqd_area->first_sch = irq_ptr->schid.sch_no; | 2322 | ssqd_area->first_sch = irq_ptr->schid.sch_no; |
2320 | ssqd_area->last_sch = irq_ptr->schid.sch_no; | 2323 | ssqd_area->last_sch = irq_ptr->schid.sch_no; |
2324 | ssqd_area->ssid = irq_ptr->schid.ssid; | ||
2321 | result = chsc(ssqd_area); | 2325 | result = chsc(ssqd_area); |
2322 | 2326 | ||
2323 | if (result) { | 2327 | if (result) { |
2324 | QDIO_PRINT_WARN("CHSC returned cc %i. Using all " \ | 2328 | QDIO_PRINT_WARN("CHSC returned cc %i. Using all " \ |
2325 | "SIGAs for sch x%x.\n", | 2329 | "SIGAs for sch 0.%x.%x.\n", result, |
2326 | result, irq_ptr->schid.sch_no); | 2330 | irq_ptr->schid.ssid, irq_ptr->schid.sch_no); |
2327 | qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY || | 2331 | qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY || |
2328 | CHSC_FLAG_SIGA_OUTPUT_NECESSARY || | 2332 | CHSC_FLAG_SIGA_OUTPUT_NECESSARY || |
2329 | CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */ | 2333 | CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */ |
@@ -2333,8 +2337,9 @@ qdio_get_ssqd_information(struct qdio_irq *irq_ptr) | |||
2333 | 2337 | ||
2334 | if (ssqd_area->response.code != QDIO_CHSC_RESPONSE_CODE_OK) { | 2338 | if (ssqd_area->response.code != QDIO_CHSC_RESPONSE_CODE_OK) { |
2335 | QDIO_PRINT_WARN("response upon checking SIGA needs " \ | 2339 | QDIO_PRINT_WARN("response upon checking SIGA needs " \ |
2336 | "is 0x%x. Using all SIGAs for sch x%x.\n", | 2340 | "is 0x%x. Using all SIGAs for sch 0.%x.%x.\n", |
2337 | ssqd_area->response.code, irq_ptr->schid.sch_no); | 2341 | ssqd_area->response.code, |
2342 | irq_ptr->schid.ssid, irq_ptr->schid.sch_no); | ||
2338 | qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY || | 2343 | qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY || |
2339 | CHSC_FLAG_SIGA_OUTPUT_NECESSARY || | 2344 | CHSC_FLAG_SIGA_OUTPUT_NECESSARY || |
2340 | CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */ | 2345 | CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */ |
@@ -2344,8 +2349,9 @@ qdio_get_ssqd_information(struct qdio_irq *irq_ptr) | |||
2344 | if (!(ssqd_area->flags & CHSC_FLAG_QDIO_CAPABILITY) || | 2349 | if (!(ssqd_area->flags & CHSC_FLAG_QDIO_CAPABILITY) || |
2345 | !(ssqd_area->flags & CHSC_FLAG_VALIDITY) || | 2350 | !(ssqd_area->flags & CHSC_FLAG_VALIDITY) || |
2346 | (ssqd_area->sch != irq_ptr->schid.sch_no)) { | 2351 | (ssqd_area->sch != irq_ptr->schid.sch_no)) { |
2347 | QDIO_PRINT_WARN("huh? problems checking out sch x%x... " \ | 2352 | QDIO_PRINT_WARN("huh? problems checking out sch 0.%x.%x... " \ |
2348 | "using all SIGAs.\n",irq_ptr->schid.sch_no); | 2353 | "using all SIGAs.\n", |
2354 | irq_ptr->schid.ssid, irq_ptr->schid.sch_no); | ||
2349 | qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY | | 2355 | qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY | |
2350 | CHSC_FLAG_SIGA_OUTPUT_NECESSARY | | 2356 | CHSC_FLAG_SIGA_OUTPUT_NECESSARY | |
2351 | CHSC_FLAG_SIGA_SYNC_NECESSARY; /* worst case */ | 2357 | CHSC_FLAG_SIGA_SYNC_NECESSARY; /* worst case */ |
@@ -2453,7 +2459,8 @@ tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero) | |||
2453 | scssc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); | 2459 | scssc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); |
2454 | if (!scssc_area) { | 2460 | if (!scssc_area) { |
2455 | QDIO_PRINT_WARN("No memory for setting indicators on " \ | 2461 | QDIO_PRINT_WARN("No memory for setting indicators on " \ |
2456 | "subchannel x%x.\n", irq_ptr->schid.sch_no); | 2462 | "subchannel 0.%x.%x.\n", |
2463 | irq_ptr->schid.ssid, irq_ptr->schid.sch_no); | ||
2457 | return -ENOMEM; | 2464 | return -ENOMEM; |
2458 | } | 2465 | } |
2459 | scssc_area->request = (struct chsc_header) { | 2466 | scssc_area->request = (struct chsc_header) { |
@@ -2479,8 +2486,9 @@ tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero) | |||
2479 | 2486 | ||
2480 | result = chsc(scssc_area); | 2487 | result = chsc(scssc_area); |
2481 | if (result) { | 2488 | if (result) { |
2482 | QDIO_PRINT_WARN("could not set indicators on irq x%x, " \ | 2489 | QDIO_PRINT_WARN("could not set indicators on irq 0.%x.%x, " \ |
2483 | "cc=%i.\n",irq_ptr->schid.sch_no,result); | 2490 | "cc=%i.\n", |
2491 | irq_ptr->schid.ssid, irq_ptr->schid.sch_no,result); | ||
2484 | result = -EIO; | 2492 | result = -EIO; |
2485 | goto out; | 2493 | goto out; |
2486 | } | 2494 | } |
@@ -2536,7 +2544,8 @@ tiqdio_set_delay_target(struct qdio_irq *irq_ptr, unsigned long delay_target) | |||
2536 | scsscf_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); | 2544 | scsscf_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); |
2537 | if (!scsscf_area) { | 2545 | if (!scsscf_area) { |
2538 | QDIO_PRINT_WARN("No memory for setting delay target on " \ | 2546 | QDIO_PRINT_WARN("No memory for setting delay target on " \ |
2539 | "subchannel x%x.\n", irq_ptr->schid.sch_no); | 2547 | "subchannel 0.%x.%x.\n", |
2548 | irq_ptr->schid.ssid, irq_ptr->schid.sch_no); | ||
2540 | return -ENOMEM; | 2549 | return -ENOMEM; |
2541 | } | 2550 | } |
2542 | scsscf_area->request = (struct chsc_header) { | 2551 | scsscf_area->request = (struct chsc_header) { |
@@ -2548,8 +2557,9 @@ tiqdio_set_delay_target(struct qdio_irq *irq_ptr, unsigned long delay_target) | |||
2548 | 2557 | ||
2549 | result=chsc(scsscf_area); | 2558 | result=chsc(scsscf_area); |
2550 | if (result) { | 2559 | if (result) { |
2551 | QDIO_PRINT_WARN("could not set delay target on irq x%x, " \ | 2560 | QDIO_PRINT_WARN("could not set delay target on irq 0.%x.%x, " \ |
2552 | "cc=%i. Continuing.\n",irq_ptr->schid.sch_no, | 2561 | "cc=%i. Continuing.\n", |
2562 | irq_ptr->schid.ssid, irq_ptr->schid.sch_no, | ||
2553 | result); | 2563 | result); |
2554 | result = -EIO; | 2564 | result = -EIO; |
2555 | goto out; | 2565 | goto out; |
@@ -2870,8 +2880,9 @@ qdio_establish_irq_check_for_errors(struct ccw_device *cdev, int cstat, | |||
2870 | QDIO_DBF_HEX2(0,trace,&dstat,sizeof(int)); | 2880 | QDIO_DBF_HEX2(0,trace,&dstat,sizeof(int)); |
2871 | QDIO_DBF_HEX2(0,trace,&cstat,sizeof(int)); | 2881 | QDIO_DBF_HEX2(0,trace,&cstat,sizeof(int)); |
2872 | QDIO_PRINT_ERR("received check condition on establish " \ | 2882 | QDIO_PRINT_ERR("received check condition on establish " \ |
2873 | "queues on irq 0x%x (cs=x%x, ds=x%x).\n", | 2883 | "queues on irq 0.%x.%x (cs=x%x, ds=x%x).\n", |
2874 | irq_ptr->schid.sch_no,cstat,dstat); | 2884 | irq_ptr->schid.ssid, irq_ptr->schid.sch_no, |
2885 | cstat,dstat); | ||
2875 | qdio_set_state(irq_ptr,QDIO_IRQ_STATE_ERR); | 2886 | qdio_set_state(irq_ptr,QDIO_IRQ_STATE_ERR); |
2876 | } | 2887 | } |
2877 | 2888 | ||
@@ -2879,9 +2890,10 @@ qdio_establish_irq_check_for_errors(struct ccw_device *cdev, int cstat, | |||
2879 | QDIO_DBF_TEXT2(1,setup,"eq:no de"); | 2890 | QDIO_DBF_TEXT2(1,setup,"eq:no de"); |
2880 | QDIO_DBF_HEX2(0,setup,&dstat, sizeof(dstat)); | 2891 | QDIO_DBF_HEX2(0,setup,&dstat, sizeof(dstat)); |
2881 | QDIO_DBF_HEX2(0,setup,&cstat, sizeof(cstat)); | 2892 | QDIO_DBF_HEX2(0,setup,&cstat, sizeof(cstat)); |
2882 | QDIO_PRINT_ERR("establish queues on irq %04x: didn't get " | 2893 | QDIO_PRINT_ERR("establish queues on irq 0.%x.%04x: didn't get " |
2883 | "device end: dstat=%02x, cstat=%02x\n", | 2894 | "device end: dstat=%02x, cstat=%02x\n", |
2884 | irq_ptr->schid.sch_no, dstat, cstat); | 2895 | irq_ptr->schid.ssid, irq_ptr->schid.sch_no, |
2896 | dstat, cstat); | ||
2885 | qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR); | 2897 | qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR); |
2886 | return 1; | 2898 | return 1; |
2887 | } | 2899 | } |
@@ -2890,9 +2902,9 @@ qdio_establish_irq_check_for_errors(struct ccw_device *cdev, int cstat, | |||
2890 | QDIO_DBF_TEXT2(1,setup,"eq:badio"); | 2902 | QDIO_DBF_TEXT2(1,setup,"eq:badio"); |
2891 | QDIO_DBF_HEX2(0,setup,&dstat, sizeof(dstat)); | 2903 | QDIO_DBF_HEX2(0,setup,&dstat, sizeof(dstat)); |
2892 | QDIO_DBF_HEX2(0,setup,&cstat, sizeof(cstat)); | 2904 | QDIO_DBF_HEX2(0,setup,&cstat, sizeof(cstat)); |
2893 | QDIO_PRINT_ERR("establish queues on irq %04x: got " | 2905 | QDIO_PRINT_ERR("establish queues on irq 0.%x.%04x: got " |
2894 | "the following devstat: dstat=%02x, " | 2906 | "the following devstat: dstat=%02x, " |
2895 | "cstat=%02x\n", | 2907 | "cstat=%02x\n", irq_ptr->schid.ssid, |
2896 | irq_ptr->schid.sch_no, dstat, cstat); | 2908 | irq_ptr->schid.sch_no, dstat, cstat); |
2897 | qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR); | 2909 | qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR); |
2898 | return 1; | 2910 | return 1; |
@@ -3041,7 +3053,8 @@ int qdio_fill_irq(struct qdio_initialize *init_data) | |||
3041 | QDIO_DBF_HEX1(0,setup,&irq_ptr->dev_st_chg_ind,sizeof(void*)); | 3053 | QDIO_DBF_HEX1(0,setup,&irq_ptr->dev_st_chg_ind,sizeof(void*)); |
3042 | if (!irq_ptr->dev_st_chg_ind) { | 3054 | if (!irq_ptr->dev_st_chg_ind) { |
3043 | QDIO_PRINT_WARN("no indicator location available " \ | 3055 | QDIO_PRINT_WARN("no indicator location available " \ |
3044 | "for irq 0x%x\n",irq_ptr->schid.sch_no); | 3056 | "for irq 0.%x.%x\n", |
3057 | irq_ptr->schid.ssid, irq_ptr->schid.sch_no); | ||
3045 | qdio_release_irq_memory(irq_ptr); | 3058 | qdio_release_irq_memory(irq_ptr); |
3046 | return -ENOBUFS; | 3059 | return -ENOBUFS; |
3047 | } | 3060 | } |
@@ -3198,9 +3211,10 @@ qdio_establish(struct qdio_initialize *init_data) | |||
3198 | sprintf(dbf_text,"eq:io%4x",result); | 3211 | sprintf(dbf_text,"eq:io%4x",result); |
3199 | QDIO_DBF_TEXT2(1,setup,dbf_text); | 3212 | QDIO_DBF_TEXT2(1,setup,dbf_text); |
3200 | } | 3213 | } |
3201 | QDIO_PRINT_WARN("establish queues on irq %04x: do_IO " \ | 3214 | QDIO_PRINT_WARN("establish queues on irq 0.%x.%04x: do_IO " \ |
3202 | "returned %i, next try returned %i\n", | 3215 | "returned %i, next try returned %i\n", |
3203 | irq_ptr->schid.sch_no,result,result2); | 3216 | irq_ptr->schid.ssid, irq_ptr->schid.sch_no, |
3217 | result, result2); | ||
3204 | result=result2; | 3218 | result=result2; |
3205 | if (result) | 3219 | if (result) |
3206 | ccw_device_set_timeout(cdev, 0); | 3220 | ccw_device_set_timeout(cdev, 0); |
@@ -3298,9 +3312,10 @@ qdio_activate(struct ccw_device *cdev, int flags) | |||
3298 | sprintf(dbf_text,"aq:io%4x",result); | 3312 | sprintf(dbf_text,"aq:io%4x",result); |
3299 | QDIO_DBF_TEXT2(1,setup,dbf_text); | 3313 | QDIO_DBF_TEXT2(1,setup,dbf_text); |
3300 | } | 3314 | } |
3301 | QDIO_PRINT_WARN("activate queues on irq %04x: do_IO " \ | 3315 | QDIO_PRINT_WARN("activate queues on irq 0.%x.%04x: do_IO " \ |
3302 | "returned %i, next try returned %i\n", | 3316 | "returned %i, next try returned %i\n", |
3303 | irq_ptr->schid.sch_no,result,result2); | 3317 | irq_ptr->schid.ssid, irq_ptr->schid.sch_no, |
3318 | result, result2); | ||
3304 | result=result2; | 3319 | result=result2; |
3305 | } | 3320 | } |
3306 | 3321 | ||