s390 patches for the 3.6-rc7
Subsystems (3)
Hi Linus,
please pull from the 'for-linus' branch of
git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux.git for-linus
to receive bug fixes for 3.6-rc7, including some important patches for large page related memory management issues.
Gerald Schaefer (3):
s390/mm: fix deadlock in unmap_hugepage_range() s390/hugetlb: use direct TLB flushing for hugetlbfs pages s390/mm: fix user access page-table walk code
Martin Schwidefsky (1):
s390/hwcaps: do not report high gprs for 31 bit kernel
Sebastian Ott (3):
s390/dasd: move wake_up call
s390/cio: fix IO subchannel event race s390/cio: invalidate cdev pointer before deregistration
Stefan Haberland (2):
s390/dasd: fix pathgroup race
s390/dasd: fix read unit address configuration loop
arch/s390/include/asm/hugetlb.h | 24 +++---- arch/s390/include/asm/tlbflush.h | 2 - arch/s390/kernel/setup.c | 2 + arch/s390/lib/uaccess_pt.c | 142 +++++++++++++++++--------------------- drivers/s390/block/dasd.c | 17 ++++- drivers/s390/block/dasd_alias.c | 27 +++++++- drivers/s390/block/dasd_eckd.c | 32 +++++++-- drivers/s390/cio/device.c | 7 +- 8 files changed, 146 insertions(+), 107 deletions(-)
arch/s390/include/asm/hugetlb.h +10 -14
@@ -66,16 +66,6 @@ static inline pte_t huge_ptep_get(pte_t *ptep)return pte; } -static inline pte_t huge_ptep_get_and_clear (struct mm_struct *mm, -unsigned long addr,pte_t *ptep) -{ -pte_t pte =huge_ptep_get (ptep); - - mm->context.flush_mm =1 ; -pmd_clear ((pmd_t *) ptep); -return pte; -} -static inline void __pmd_csp (pmd_t *pmdp) { register unsigned long reg2 asm("2") = pmd_val(*pmdp);
@@ -117,6 +107,15 @@ static inline void huge_ptep_invalidate(struct mm_struct *mm,__pmd_csp (pmdp); } +static inline pte_t huge_ptep_get_and_clear (struct mm_struct *mm, +unsigned long addr,pte_t *ptep) +{ +pte_t pte =huge_ptep_get (ptep); + +huge_ptep_invalidate (mm, addr, ptep); +return pte; +} +#define huge_ptep_set_access_flags (__vma, __addr, __ptep, __entry, __dirty) \ ({ \ int __changed = !pte_same(huge_ptep_get(__ptep), __entry); \
@@ -131,10 +130,7 @@ static inline void huge_ptep_invalidate(struct mm_struct *mm, ({ \ pte_t __pte = huge_ptep_get(__ptep); \ if (pte_write(__pte)) { \ - (__mm)->context.flush_mm = 1; \ - if (atomic_read(&(__mm)->context.attach_count) > 1 || \ - (__mm) != current->active_mm) \ - huge_ptep_invalidate(__mm, __addr, __ptep); \ + huge_ptep_invalidate(__mm, __addr, __ptep); \ set_huge_pte_at(__mm, __addr, __ptep, \ huge_pte_wrprotect(__pte)); \ } \
arch/s390/include/asm/tlbflush.h +0 -2
@@ -90,12 +90,10 @@ static inline void __tlb_flush_mm(struct mm_struct * mm)static inline void __tlb_flush_mm_cond (struct mm_struct * mm) { -spin_lock (&mm->page_table_lock);if (mm->context.flush_mm) {__tlb_flush_mm (mm); mm->context.flush_mm =0 ; } -spin_unlock (&mm->page_table_lock); }/*
arch/s390/kernel/setup.c +2 -0
@@ -974,11 +974,13 @@ static void __init setup_hwcaps(void)if (MACHINE_HAS_HPAGE ) elf_hwcap |=HWCAP_S390_HPAGE ; +#if defined(CONFIG_64BIT )/* * 64-bit register support for 31-bit processes * HWCAP_S390_HIGH_GPRS is bit 9. */ elf_hwcap |=HWCAP_S390_HIGH_GPRS ; +#endif get_cpu_id (&cpu_id);switch (cpu_id.machine) {
arch/s390/lib/uaccess_pt.c +63 -79
273 lines not on this page · raw message
drivers/s390/block/dasd.c +14 -3
@@ -534,11 +534,11 @@ static void dasd_change_state(struct dasd_device *device)if (rc) device->target = device->state; -if (device->state == device->target) -wake_up (&dasd_init_waitq); -/* let user-space know that the device status changed */ kobject_uevent (&device->cdev->dev.kobj,KOBJ_CHANGE ); + +if (device->state == device->target) +wake_up (&dasd_init_waitq); }/*
@@ -2157,6 +2157,7 @@ static int _dasd_sleep_on(struct dasd_ccw_req *maincqr, int interruptible) test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) && (!dasd_eer_enabled(device))) { cqr->status =DASD_CQR_FAILED ; + cqr->intrc = -EAGAIN ;continue ; }/* Don't try to start requests if device is stopped */
@@ -3270,6 +3271,16 @@ void dasd_generic_path_event(struct ccw_device *cdev, int *path_event)dasd_schedule_device_bh (device); }if (path_event[chp] &PE_PATHGROUP_ESTABLISHED ) { +if (!(device->path_data.opm & eventlpm) && + !(device->path_data.tbvpm & eventlpm)) { +/* +* we can not establish a pathgroup on an +* unavailable path, so trigger a path +* verification first +*/ + device->path_data.tbvpm |= eventlpm; +dasd_schedule_device_bh (device); + }DBF_DEV_EVENT (DBF_WARNING , device,"%s" ,"Pathgroup re-established\n" );if (device->discipline->kick_validate)
drivers/s390/block/dasd_alias.c +26 -1
@@ -384,6 +384,29 @@ static void _remove_device_from_lcu(struct alias_lcu *lcu, group->next =NULL ; }; +static int +suborder_not_supported (struct dasd_ccw_req *cqr) +{ +char *sense; +char reason; +char msg_format; +char msg_no; + + sense =dasd_get_sense (&cqr->irb); +if (!sense) +return 0 ; + + reason = sense[0 ]; + msg_format = (sense[7 ] &0xF0 ); + msg_no = (sense[7 ] &0x0F ); + +/* command reject, Format 0 MSG 4 - invalid parameter */ +if ((reason ==0x80 ) && (msg_format ==0x00 ) && (msg_no ==0x04 )) +return 1 ; + +return 0 ; +} +static int read_unit_address_configuration (struct dasd_device *device,struct alias_lcu *lcu) {
@@ -435,6 +458,8 @@ static int read_unit_address_configuration(struct dasd_device *device,do { rc =dasd_sleep_on (cqr); +if (rc &&suborder_not_supported (cqr)) +return -EOPNOTSUPP ; }while (rc && (cqr->retries >0 ));if (rc) {spin_lock_irqsave (&lcu->lock, flags);
@@ -521,7 +546,7 @@ static void lcu_update_work(struct work_struct *work)* processing the data */ spin_lock_irqsave (&lcu->lock, flags); -if (rc || (lcu->flags &NEED_UAC_UPDATE )) { +if ((rc && (rc != -EOPNOTSUPP )) || (lcu->flags &NEED_UAC_UPDATE )) {DBF_DEV_EVENT (DBF_WARNING , device,"could not update" " alias data in lcu (rc = %d), retry later" , rc);schedule_delayed_work (&lcu->ruac_data.dwork,30 *HZ );
drivers/s390/block/dasd_eckd.c +25 -7
@@ -1507,7 +1507,8 @@ static struct dasd_ccw_req *dasd_eckd_build_psf_ssc(struct dasd_device *device,* call might change behaviour of DASD devices. */ static int -dasd_eckd_psf_ssc (struct dasd_device *device,int enable_pav) +dasd_eckd_psf_ssc (struct dasd_device *device,int enable_pav, +unsigned long flags) {struct dasd_ccw_req *cqr;int rc;
@@ -1516,10 +1517,19 @@ dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav)if (IS_ERR (cqr))return PTR_ERR (cqr); +/* +* set flags e.g. turn on failfast, to prevent blocking +* the calling function should handle failed requests +*/ + cqr->flags |= flags; + rc =dasd_sleep_on (cqr);if (!rc)/* trigger CIO to reprobe devices */ css_schedule_reprobe (); +else if (cqr->intrc == -EAGAIN ) + rc = -EAGAIN ; +dasd_sfree_request (cqr, cqr->memdev);return rc; }
@@ -1527,7 +1537,8 @@ dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav)/* * Valide storage server of current device. */ -static void dasd_eckd_validate_server (struct dasd_device *device) +static int dasd_eckd_validate_server (struct dasd_device *device, +unsigned long flags) {int rc;struct dasd_eckd_private *private;
@@ -1536,17 +1547,18 @@ static void dasd_eckd_validate_server(struct dasd_device *device) private = (struct dasd_eckd_private *) device->private;if (private->uid.type ==UA_BASE_PAV_ALIAS || private->uid.type ==UA_HYPER_PAV_ALIAS ) -return ; +return 0 ;if (dasd_nopav ||MACHINE_IS_VM ) enable_pav =0 ;else enable_pav =1 ; - rc =dasd_eckd_psf_ssc (device, enable_pav); + rc =dasd_eckd_psf_ssc (device, enable_pav, flags);/* may be requested feature is not available on server, * therefore just report error and go ahead */ DBF_EVENT_DEVID (DBF_WARNING , device->cdev,"PSF-SSC for SSID %04x " "returned rc=%d" , private->uid.ssid, rc); +return rc; }/*
@@ -1556,7 +1568,13 @@ static void dasd_eckd_do_validate_server(struct work_struct *work) { struct dasd_device *device = container_of(work, struct dasd_device, kick_validate); -dasd_eckd_validate_server (device); +if (dasd_eckd_validate_server (device,DASD_CQR_FLAGS_FAILFAST ) + == -EAGAIN ) { +/* schedule worker again if failed */ +schedule_work (&device->kick_validate); +return ; + } +dasd_put_device (device); }
@@ -1685,7 +1703,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device)if (rc) goto out_err2; -dasd_eckd_validate_server (device); +dasd_eckd_validate_server (device,0 );/* device may report different configuration data after LCU setup */ rc =dasd_eckd_read_conf (device);
@@ -4153,7 +4171,7 @@ static int dasd_eckd_restore_device(struct dasd_device *device) rc =dasd_alias_make_device_known_to_lcu (device);if (rc)return rc; -dasd_eckd_validate_server (device); +dasd_eckd_validate_server (device,DASD_CQR_FLAGS_FAILFAST );/* RE-Read Configuration Data */ rc =dasd_eckd_read_conf (device);
drivers/s390/cio/device.c +6 -1
@@ -1426,6 +1426,8 @@ static enum io_sch_action sch_get_action(struct subchannel *sch)return IO_SCH_REPROBE ;if (cdev->online)return IO_SCH_VERIFY ; +if (cdev->private->state ==DEV_STATE_NOT_OPER ) +return IO_SCH_UNREG_ATTACH ;return IO_SCH_NOP ; }
@@ -1519,11 +1521,14 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process) goto out;break ;case IO_SCH_UNREG_ATTACH : +spin_lock_irqsave (sch->lock, flags);if (cdev->private->flags.resuming) {/* Device will be handled later. */ rc =0 ; - goto out; + goto out_unlock; } +sch_set_cdev (sch,NULL ); +spin_unlock_irqrestore (sch->lock, flags);/* Unregister ccw device. */ ccw_device_unregister (cdev);break ;