Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 's390-6.9-4' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux

Pull s390 updates from Alexander Gordeev:

- Fix NULL pointer dereference in program check handler

- Fake IRBs are important events relevant for problem analysis. Add
traces when queueing and delivering

- Fix a race condition in ccw_device_set_online() that can cause the
online process to fail

- Deferred condition code 1 response indicates that I/O was not started
and should be retried. The current QDIO implementation handles a cc1
response as an error, resulting in a failed QDIO setup. Fix that by
retrying the setup when a cc1 response is received

* tag 's390-6.9-4' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux:
s390/mm: Fix NULL pointer dereference
s390/cio: log fake IRB events
s390/cio: fix race condition during online processing
s390/qdio: handle deferred cc1

+46 -11
+2 -1
arch/s390/kernel/entry.S
··· 340 340 mvc __PT_LAST_BREAK(8,%r11),__LC_PGM_LAST_BREAK 341 341 stctg %c1,%c1,__PT_CR1(%r11) 342 342 #if IS_ENABLED(CONFIG_KVM) 343 - lg %r12,__LC_GMAP 343 + ltg %r12,__LC_GMAP 344 + jz 5f 344 345 clc __GMAP_ASCE(8,%r12), __PT_CR1(%r11) 345 346 jne 5f 346 347 BPENTER __SF_SIE_FLAGS(%r10),_TIF_ISOLATE_BP_GUEST
+8 -5
drivers/s390/cio/device.c
··· 363 363 364 364 spin_lock_irq(cdev->ccwlock); 365 365 ret = ccw_device_online(cdev); 366 - spin_unlock_irq(cdev->ccwlock); 367 - if (ret == 0) 368 - wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev)); 369 - else { 366 + if (ret) { 367 + spin_unlock_irq(cdev->ccwlock); 370 368 CIO_MSG_EVENT(0, "ccw_device_online returned %d, " 371 369 "device 0.%x.%04x\n", 372 370 ret, cdev->private->dev_id.ssid, ··· 373 375 put_device(&cdev->dev); 374 376 return ret; 375 377 } 376 - spin_lock_irq(cdev->ccwlock); 378 + /* Wait until a final state is reached */ 379 + while (!dev_fsm_final_state(cdev)) { 380 + spin_unlock_irq(cdev->ccwlock); 381 + wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev)); 382 + spin_lock_irq(cdev->ccwlock); 383 + } 377 384 /* Check if online processing was successful */ 378 385 if ((cdev->private->state != DEV_STATE_ONLINE) && 379 386 (cdev->private->state != DEV_STATE_W4SENSE)) {
+5
drivers/s390/cio/device_fsm.c
··· 504 504 ccw_device_done(cdev, DEV_STATE_ONLINE); 505 505 /* Deliver fake irb to device driver, if needed. */ 506 506 if (cdev->private->flags.fake_irb) { 507 + CIO_MSG_EVENT(2, "fakeirb: deliver device 0.%x.%04x intparm %lx type=%d\n", 508 + cdev->private->dev_id.ssid, 509 + cdev->private->dev_id.devno, 510 + cdev->private->intparm, 511 + cdev->private->flags.fake_irb); 507 512 create_fake_irb(&cdev->private->dma_area->irb, 508 513 cdev->private->flags.fake_irb); 509 514 cdev->private->flags.fake_irb = 0;
+8
drivers/s390/cio/device_ops.c
··· 208 208 if (!cdev->private->flags.fake_irb) { 209 209 cdev->private->flags.fake_irb = FAKE_CMD_IRB; 210 210 cdev->private->intparm = intparm; 211 + CIO_MSG_EVENT(2, "fakeirb: queue device 0.%x.%04x intparm %lx type=%d\n", 212 + cdev->private->dev_id.ssid, 213 + cdev->private->dev_id.devno, intparm, 214 + cdev->private->flags.fake_irb); 211 215 return 0; 212 216 } else 213 217 /* There's already a fake I/O around. */ ··· 555 551 if (!cdev->private->flags.fake_irb) { 556 552 cdev->private->flags.fake_irb = FAKE_TM_IRB; 557 553 cdev->private->intparm = intparm; 554 + CIO_MSG_EVENT(2, "fakeirb: queue device 0.%x.%04x intparm %lx type=%d\n", 555 + cdev->private->dev_id.ssid, 556 + cdev->private->dev_id.devno, intparm, 557 + cdev->private->flags.fake_irb); 558 558 return 0; 559 559 } else 560 560 /* There's already a fake I/O around. */
+23 -5
drivers/s390/cio/qdio_main.c
··· 722 722 lgr_info_log(); 723 723 } 724 724 725 - static void qdio_establish_handle_irq(struct qdio_irq *irq_ptr, int cstat, 726 - int dstat) 725 + static int qdio_establish_handle_irq(struct qdio_irq *irq_ptr, int cstat, 726 + int dstat, int dcc) 727 727 { 728 728 DBF_DEV_EVENT(DBF_INFO, irq_ptr, "qest irq"); 729 729 ··· 731 731 goto error; 732 732 if (dstat & ~(DEV_STAT_DEV_END | DEV_STAT_CHN_END)) 733 733 goto error; 734 + if (dcc == 1) 735 + return -EAGAIN; 734 736 if (!(dstat & DEV_STAT_DEV_END)) 735 737 goto error; 736 738 qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ESTABLISHED); 737 - return; 739 + return 0; 738 740 739 741 error: 740 742 DBF_ERROR("%4x EQ:error", irq_ptr->schid.sch_no); 741 743 DBF_ERROR("ds: %2x cs:%2x", dstat, cstat); 742 744 qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR); 745 + return -EIO; 743 746 } 744 747 745 748 /* qdio interrupt handler */ ··· 751 748 { 752 749 struct qdio_irq *irq_ptr = cdev->private->qdio_data; 753 750 struct subchannel_id schid; 754 - int cstat, dstat; 751 + int cstat, dstat, rc, dcc; 755 752 756 753 if (!intparm || !irq_ptr) { 757 754 ccw_device_get_schid(cdev, &schid); ··· 771 768 qdio_irq_check_sense(irq_ptr, irb); 772 769 cstat = irb->scsw.cmd.cstat; 773 770 dstat = irb->scsw.cmd.dstat; 771 + dcc = scsw_cmd_is_valid_cc(&irb->scsw) ? irb->scsw.cmd.cc : 0; 772 + rc = 0; 774 773 775 774 switch (irq_ptr->state) { 776 775 case QDIO_IRQ_STATE_INACTIVE: 777 - qdio_establish_handle_irq(irq_ptr, cstat, dstat); 776 + rc = qdio_establish_handle_irq(irq_ptr, cstat, dstat, dcc); 778 777 break; 779 778 case QDIO_IRQ_STATE_CLEANUP: 780 779 qdio_set_state(irq_ptr, QDIO_IRQ_STATE_INACTIVE); ··· 790 785 if (cstat || dstat) 791 786 qdio_handle_activate_check(irq_ptr, intparm, cstat, 792 787 dstat); 788 + else if (dcc == 1) 789 + rc = -EAGAIN; 793 790 break; 794 791 case QDIO_IRQ_STATE_STOPPED: 795 792 break; 796 793 default: 797 794 WARN_ON_ONCE(1); 798 795 } 796 + 797 + if (rc == -EAGAIN) { 798 + DBF_DEV_EVENT(DBF_INFO, irq_ptr, "qint retry"); 799 + rc = ccw_device_start(cdev, irq_ptr->ccw, intparm, 0, 0); 800 + if (!rc) 801 + return; 802 + DBF_ERROR("%4x RETRY ERR", irq_ptr->schid.sch_no); 803 + DBF_ERROR("rc:%4x", rc); 804 + qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR); 805 + } 806 + 799 807 wake_up(&cdev->private->wait_q); 800 808 } 801 809