Merge branch 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6

* 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6:
  [S390] zcore: Fix reipl device detection
  [S390] vdso: use ntp adjusted clock multiplier
  [S390] cio: use exception-save stsch
  [S390] add hook to reenable mss after hibernation
  [S390] cio: allow enable_facility from outside init functions
  [S390] dasd: fix endless loop in erp
This commit is contained in:
Linus Torvalds 2010-04-22 08:43:59 -07:00
commit c81eddb0e3
16 changed files with 60 additions and 53 deletions

View file

@ -29,6 +29,7 @@ struct vdso_data {
__u32 tz_minuteswest; /* Minutes west of Greenwich 0x30 */ __u32 tz_minuteswest; /* Minutes west of Greenwich 0x30 */
__u32 tz_dsttime; /* Type of dst correction 0x34 */ __u32 tz_dsttime; /* Type of dst correction 0x34 */
__u32 ectg_available; __u32 ectg_available;
__u32 ntp_mult; /* NTP adjusted multiplier 0x3C */
}; };
struct vdso_per_cpu_data { struct vdso_per_cpu_data {

View file

@ -61,6 +61,7 @@ int main(void)
DEFINE(__VDSO_WTOM_NSEC, offsetof(struct vdso_data, wtom_clock_nsec)); DEFINE(__VDSO_WTOM_NSEC, offsetof(struct vdso_data, wtom_clock_nsec));
DEFINE(__VDSO_TIMEZONE, offsetof(struct vdso_data, tz_minuteswest)); DEFINE(__VDSO_TIMEZONE, offsetof(struct vdso_data, tz_minuteswest));
DEFINE(__VDSO_ECTG_OK, offsetof(struct vdso_data, ectg_available)); DEFINE(__VDSO_ECTG_OK, offsetof(struct vdso_data, ectg_available));
DEFINE(__VDSO_NTP_MULT, offsetof(struct vdso_data, ntp_mult));
DEFINE(__VDSO_ECTG_BASE, offsetof(struct vdso_per_cpu_data, ectg_timer_base)); DEFINE(__VDSO_ECTG_BASE, offsetof(struct vdso_per_cpu_data, ectg_timer_base));
DEFINE(__VDSO_ECTG_USER, offsetof(struct vdso_per_cpu_data, ectg_user_time)); DEFINE(__VDSO_ECTG_USER, offsetof(struct vdso_per_cpu_data, ectg_user_time));
/* constants used by the vdso */ /* constants used by the vdso */

View file

@ -256,6 +256,9 @@ restore_registers:
lghi %r2,0 lghi %r2,0
brasl %r14,arch_set_page_states brasl %r14,arch_set_page_states
/* Reinitialize the channel subsystem */
brasl %r14,channel_subsystem_reinit
/* Return 0 */ /* Return 0 */
lmg %r6,%r15,STACK_FRAME_OVERHEAD + __SF_GPRS(%r15) lmg %r6,%r15,STACK_FRAME_OVERHEAD + __SF_GPRS(%r15)
lghi %r2,0 lghi %r2,0

View file

@ -221,6 +221,7 @@ void update_vsyscall(struct timespec *wall_time, struct clocksource *clock,
vdso_data->xtime_clock_nsec = wall_time->tv_nsec; vdso_data->xtime_clock_nsec = wall_time->tv_nsec;
vdso_data->wtom_clock_sec = wall_to_monotonic.tv_sec; vdso_data->wtom_clock_sec = wall_to_monotonic.tv_sec;
vdso_data->wtom_clock_nsec = wall_to_monotonic.tv_nsec; vdso_data->wtom_clock_nsec = wall_to_monotonic.tv_nsec;
vdso_data->ntp_mult = mult;
smp_wmb(); smp_wmb();
++vdso_data->tb_update_count; ++vdso_data->tb_update_count;
} }

View file

@ -38,13 +38,13 @@ __kernel_clock_gettime:
sl %r1,__VDSO_XTIME_STAMP+4(%r5) sl %r1,__VDSO_XTIME_STAMP+4(%r5)
brc 3,2f brc 3,2f
ahi %r0,-1 ahi %r0,-1
2: mhi %r0,1000 /* cyc2ns(clock,cycle_delta) */ 2: ms %r0,__VDSO_NTP_MULT(%r5) /* cyc2ns(clock,cycle_delta) */
lr %r2,%r0 lr %r2,%r0
lhi %r0,1000 l %r0,__VDSO_NTP_MULT(%r5)
ltr %r1,%r1 ltr %r1,%r1
mr %r0,%r0 mr %r0,%r0
jnm 3f jnm 3f
ahi %r0,1000 a %r0,__VDSO_NTP_MULT(%r5)
3: alr %r0,%r2 3: alr %r0,%r2
srdl %r0,12 srdl %r0,12
al %r0,__VDSO_XTIME_NSEC(%r5) /* + xtime */ al %r0,__VDSO_XTIME_NSEC(%r5) /* + xtime */
@ -86,13 +86,13 @@ __kernel_clock_gettime:
sl %r1,__VDSO_XTIME_STAMP+4(%r5) sl %r1,__VDSO_XTIME_STAMP+4(%r5)
brc 3,12f brc 3,12f
ahi %r0,-1 ahi %r0,-1
12: mhi %r0,1000 /* cyc2ns(clock,cycle_delta) */ 12: ms %r0,__VDSO_NTP_MULT(%r5) /* cyc2ns(clock,cycle_delta) */
lr %r2,%r0 lr %r2,%r0
lhi %r0,1000 l %r0,__VDSO_NTP_MULT(%r5)
ltr %r1,%r1 ltr %r1,%r1
mr %r0,%r0 mr %r0,%r0
jnm 13f jnm 13f
ahi %r0,1000 a %r0,__VDSO_NTP_MULT(%r5)
13: alr %r0,%r2 13: alr %r0,%r2
srdl %r0,12 srdl %r0,12
al %r0,__VDSO_XTIME_NSEC(%r5) /* + xtime */ al %r0,__VDSO_XTIME_NSEC(%r5) /* + xtime */

View file

@ -35,13 +35,13 @@ __kernel_gettimeofday:
sl %r1,__VDSO_XTIME_STAMP+4(%r5) sl %r1,__VDSO_XTIME_STAMP+4(%r5)
brc 3,3f brc 3,3f
ahi %r0,-1 ahi %r0,-1
3: mhi %r0,1000 /* cyc2ns(clock,cycle_delta) */ 3: ms %r0,__VDSO_NTP_MULT(%r5) /* cyc2ns(clock,cycle_delta) */
st %r0,24(%r15) st %r0,24(%r15)
lhi %r0,1000 l %r0,__VDSO_NTP_MULT(%r5)
ltr %r1,%r1 ltr %r1,%r1
mr %r0,%r0 mr %r0,%r0
jnm 4f jnm 4f
ahi %r0,1000 a %r0,__VDSO_NTP_MULT(%r5)
4: al %r0,24(%r15) 4: al %r0,24(%r15)
srdl %r0,12 srdl %r0,12
al %r0,__VDSO_XTIME_NSEC(%r5) /* + xtime */ al %r0,__VDSO_XTIME_NSEC(%r5) /* + xtime */

View file

@ -36,7 +36,7 @@ __kernel_clock_gettime:
stck 48(%r15) /* Store TOD clock */ stck 48(%r15) /* Store TOD clock */
lg %r1,48(%r15) lg %r1,48(%r15)
sg %r1,__VDSO_XTIME_STAMP(%r5) /* TOD - cycle_last */ sg %r1,__VDSO_XTIME_STAMP(%r5) /* TOD - cycle_last */
mghi %r1,1000 msgf %r1,__VDSO_NTP_MULT(%r5) /* * NTP adjustment */
srlg %r1,%r1,12 /* cyc2ns(clock,cycle_delta) */ srlg %r1,%r1,12 /* cyc2ns(clock,cycle_delta) */
alg %r1,__VDSO_XTIME_NSEC(%r5) /* + xtime */ alg %r1,__VDSO_XTIME_NSEC(%r5) /* + xtime */
lg %r0,__VDSO_XTIME_SEC(%r5) lg %r0,__VDSO_XTIME_SEC(%r5)
@ -64,7 +64,7 @@ __kernel_clock_gettime:
stck 48(%r15) /* Store TOD clock */ stck 48(%r15) /* Store TOD clock */
lg %r1,48(%r15) lg %r1,48(%r15)
sg %r1,__VDSO_XTIME_STAMP(%r5) /* TOD - cycle_last */ sg %r1,__VDSO_XTIME_STAMP(%r5) /* TOD - cycle_last */
mghi %r1,1000 msgf %r1,__VDSO_NTP_MULT(%r5) /* * NTP adjustment */
srlg %r1,%r1,12 /* cyc2ns(clock,cycle_delta) */ srlg %r1,%r1,12 /* cyc2ns(clock,cycle_delta) */
alg %r1,__VDSO_XTIME_NSEC(%r5) /* + xtime */ alg %r1,__VDSO_XTIME_NSEC(%r5) /* + xtime */
lg %r0,__VDSO_XTIME_SEC(%r5) lg %r0,__VDSO_XTIME_SEC(%r5)

View file

@ -31,7 +31,7 @@ __kernel_gettimeofday:
stck 48(%r15) /* Store TOD clock */ stck 48(%r15) /* Store TOD clock */
lg %r1,48(%r15) lg %r1,48(%r15)
sg %r1,__VDSO_XTIME_STAMP(%r5) /* TOD - cycle_last */ sg %r1,__VDSO_XTIME_STAMP(%r5) /* TOD - cycle_last */
mghi %r1,1000 msgf %r1,__VDSO_NTP_MULT(%r5) /* * NTP adjustment */
srlg %r1,%r1,12 /* cyc2ns(clock,cycle_delta) */ srlg %r1,%r1,12 /* cyc2ns(clock,cycle_delta) */
alg %r1,__VDSO_XTIME_NSEC(%r5) /* + xtime.tv_nsec */ alg %r1,__VDSO_XTIME_NSEC(%r5) /* + xtime.tv_nsec */
lg %r0,__VDSO_XTIME_SEC(%r5) /* xtime.tv_sec */ lg %r0,__VDSO_XTIME_SEC(%r5) /* xtime.tv_sec */

View file

@ -1899,7 +1899,8 @@ restart:
/* Process requests that may be recovered */ /* Process requests that may be recovered */
if (cqr->status == DASD_CQR_NEED_ERP) { if (cqr->status == DASD_CQR_NEED_ERP) {
erp_fn = base->discipline->erp_action(cqr); erp_fn = base->discipline->erp_action(cqr);
erp_fn(cqr); if (IS_ERR(erp_fn(cqr)))
continue;
goto restart; goto restart;
} }

View file

@ -2309,7 +2309,7 @@ static struct dasd_ccw_req *dasd_3990_erp_add_erp(struct dasd_ccw_req *cqr)
cqr->retries); cqr->retries);
dasd_block_set_timer(device->block, (HZ << 3)); dasd_block_set_timer(device->block, (HZ << 3));
} }
return cqr; return erp;
} }
ccw = cqr->cpaddr; ccw = cqr->cpaddr;
@ -2372,6 +2372,9 @@ dasd_3990_erp_additional_erp(struct dasd_ccw_req * cqr)
/* add erp and initialize with default TIC */ /* add erp and initialize with default TIC */
erp = dasd_3990_erp_add_erp(cqr); erp = dasd_3990_erp_add_erp(cqr);
if (IS_ERR(erp))
return erp;
/* inspect sense, determine specific ERP if possible */ /* inspect sense, determine specific ERP if possible */
if (erp != cqr) { if (erp != cqr) {
@ -2711,6 +2714,8 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr)
if (erp == NULL) { if (erp == NULL) {
/* no matching erp found - set up erp */ /* no matching erp found - set up erp */
erp = dasd_3990_erp_additional_erp(cqr); erp = dasd_3990_erp_additional_erp(cqr);
if (IS_ERR(erp))
return erp;
} else { } else {
/* matching erp found - set all leading erp's to DONE */ /* matching erp found - set all leading erp's to DONE */
erp = dasd_3990_erp_handle_match_erp(cqr, erp); erp = dasd_3990_erp_handle_match_erp(cqr, erp);

View file

@ -638,11 +638,7 @@ static int __init zcore_reipl_init(void)
rc = memcpy_hsa_kernel(ipl_block, ipib_info.ipib, PAGE_SIZE); rc = memcpy_hsa_kernel(ipl_block, ipib_info.ipib, PAGE_SIZE);
else else
rc = memcpy_real(ipl_block, (void *) ipib_info.ipib, PAGE_SIZE); rc = memcpy_real(ipl_block, (void *) ipib_info.ipib, PAGE_SIZE);
if (rc) { if (rc || csum_partial(ipl_block, ipl_block->hdr.len, 0) !=
free_page((unsigned long) ipl_block);
return rc;
}
if (csum_partial(ipl_block, ipl_block->hdr.len, 0) !=
ipib_info.checksum) { ipib_info.checksum) {
TRACE("Checksum does not match\n"); TRACE("Checksum does not match\n");
free_page((unsigned long) ipl_block); free_page((unsigned long) ipl_block);

View file

@ -29,6 +29,7 @@
#include "chsc.h" #include "chsc.h"
static void *sei_page; static void *sei_page;
static DEFINE_SPINLOCK(sda_lock);
/** /**
* chsc_error_from_response() - convert a chsc response to an error * chsc_error_from_response() - convert a chsc response to an error
@ -832,11 +833,10 @@ void __init chsc_free_sei_area(void)
kfree(sei_page); kfree(sei_page);
} }
int __init int chsc_enable_facility(int operation_code)
chsc_enable_facility(int operation_code)
{ {
int ret; int ret;
struct { static struct {
struct chsc_header request; struct chsc_header request;
u8 reserved1:4; u8 reserved1:4;
u8 format:4; u8 format:4;
@ -849,33 +849,32 @@ chsc_enable_facility(int operation_code)
u32 reserved5:4; u32 reserved5:4;
u32 format2:4; u32 format2:4;
u32 reserved6:24; u32 reserved6:24;
} __attribute__ ((packed)) *sda_area; } __attribute__ ((packed, aligned(4096))) sda_area;
sda_area = (void *)get_zeroed_page(GFP_KERNEL|GFP_DMA); spin_lock(&sda_lock);
if (!sda_area) memset(&sda_area, 0, sizeof(sda_area));
return -ENOMEM; sda_area.request.length = 0x0400;
sda_area->request.length = 0x0400; sda_area.request.code = 0x0031;
sda_area->request.code = 0x0031; sda_area.operation_code = operation_code;
sda_area->operation_code = operation_code;
ret = chsc(sda_area); ret = chsc(&sda_area);
if (ret > 0) { if (ret > 0) {
ret = (ret == 3) ? -ENODEV : -EBUSY; ret = (ret == 3) ? -ENODEV : -EBUSY;
goto out; goto out;
} }
switch (sda_area->response.code) { switch (sda_area.response.code) {
case 0x0101: case 0x0101:
ret = -EOPNOTSUPP; ret = -EOPNOTSUPP;
break; break;
default: default:
ret = chsc_error_from_response(sda_area->response.code); ret = chsc_error_from_response(sda_area.response.code);
} }
if (ret != 0) if (ret != 0)
CIO_CRW_EVENT(2, "chsc: sda (oc=%x) failed (rc=%04x)\n", CIO_CRW_EVENT(2, "chsc: sda (oc=%x) failed (rc=%04x)\n",
operation_code, sda_area->response.code); operation_code, sda_area.response.code);
out: out:
free_page((unsigned long)sda_area); spin_unlock(&sda_lock);
return ret; return ret;
} }

View file

@ -124,7 +124,7 @@ static int chsc_subchannel_prepare(struct subchannel *sch)
* since we don't have a way to clear the subchannel and * since we don't have a way to clear the subchannel and
* cannot disable it with a request running. * cannot disable it with a request running.
*/ */
cc = stsch(sch->schid, &schib); cc = stsch_err(sch->schid, &schib);
if (!cc && scsw_stctl(&schib.scsw)) if (!cc && scsw_stctl(&schib.scsw))
return -EAGAIN; return -EAGAIN;
return 0; return 0;

View file

@ -361,7 +361,7 @@ int cio_commit_config(struct subchannel *sch)
struct schib schib; struct schib schib;
int ccode, retry, ret = 0; int ccode, retry, ret = 0;
if (stsch(sch->schid, &schib) || !css_sch_is_valid(&schib)) if (stsch_err(sch->schid, &schib) || !css_sch_is_valid(&schib))
return -ENODEV; return -ENODEV;
for (retry = 0; retry < 5; retry++) { for (retry = 0; retry < 5; retry++) {
@ -372,7 +372,7 @@ int cio_commit_config(struct subchannel *sch)
return ccode; return ccode;
switch (ccode) { switch (ccode) {
case 0: /* successful */ case 0: /* successful */
if (stsch(sch->schid, &schib) || if (stsch_err(sch->schid, &schib) ||
!css_sch_is_valid(&schib)) !css_sch_is_valid(&schib))
return -ENODEV; return -ENODEV;
if (cio_check_config(sch, &schib)) { if (cio_check_config(sch, &schib)) {
@ -404,7 +404,7 @@ int cio_update_schib(struct subchannel *sch)
{ {
struct schib schib; struct schib schib;
if (stsch(sch->schid, &schib) || !css_sch_is_valid(&schib)) if (stsch_err(sch->schid, &schib) || !css_sch_is_valid(&schib))
return -ENODEV; return -ENODEV;
memcpy(&sch->schib, &schib, sizeof(schib)); memcpy(&sch->schib, &schib, sizeof(schib));
@ -771,7 +771,7 @@ cio_get_console_sch_no(void)
if (console_irq != -1) { if (console_irq != -1) {
/* VM provided us with the irq number of the console. */ /* VM provided us with the irq number of the console. */
schid.sch_no = console_irq; schid.sch_no = console_irq;
if (stsch(schid, &console_subchannel.schib) != 0 || if (stsch_err(schid, &console_subchannel.schib) != 0 ||
(console_subchannel.schib.pmcw.st != SUBCHANNEL_TYPE_IO) || (console_subchannel.schib.pmcw.st != SUBCHANNEL_TYPE_IO) ||
!console_subchannel.schib.pmcw.dnv) !console_subchannel.schib.pmcw.dnv)
return -1; return -1;
@ -863,10 +863,10 @@ __disable_subchannel_easy(struct subchannel_id schid, struct schib *schib)
cc = 0; cc = 0;
for (retry=0;retry<3;retry++) { for (retry=0;retry<3;retry++) {
schib->pmcw.ena = 0; schib->pmcw.ena = 0;
cc = msch(schid, schib); cc = msch_err(schid, schib);
if (cc) if (cc)
return (cc==3?-ENODEV:-EBUSY); return (cc==3?-ENODEV:-EBUSY);
if (stsch(schid, schib) || !css_sch_is_valid(schib)) if (stsch_err(schid, schib) || !css_sch_is_valid(schib))
return -ENODEV; return -ENODEV;
if (!schib->pmcw.ena) if (!schib->pmcw.ena)
return 0; return 0;
@ -913,7 +913,7 @@ static int stsch_reset(struct subchannel_id schid, struct schib *addr)
pgm_check_occured = 0; pgm_check_occured = 0;
s390_base_pgm_handler_fn = cio_reset_pgm_check_handler; s390_base_pgm_handler_fn = cio_reset_pgm_check_handler;
rc = stsch(schid, addr); rc = stsch_err(schid, addr);
s390_base_pgm_handler_fn = NULL; s390_base_pgm_handler_fn = NULL;
/* The program check handler could have changed pgm_check_occured. */ /* The program check handler could have changed pgm_check_occured. */
@ -950,7 +950,7 @@ static int __shutdown_subchannel_easy(struct subchannel_id schid, void *data)
/* No default clear strategy */ /* No default clear strategy */
break; break;
} }
stsch(schid, &schib); stsch_err(schid, &schib);
__disable_subchannel_easy(schid, &schib); __disable_subchannel_easy(schid, &schib);
} }
out: out:
@ -1086,7 +1086,7 @@ int __init cio_get_iplinfo(struct cio_iplinfo *iplinfo)
schid = *(struct subchannel_id *)&S390_lowcore.subchannel_id; schid = *(struct subchannel_id *)&S390_lowcore.subchannel_id;
if (!schid.one) if (!schid.one)
return -ENODEV; return -ENODEV;
if (stsch(schid, &schib)) if (stsch_err(schid, &schib))
return -ENODEV; return -ENODEV;
if (schib.pmcw.st != SUBCHANNEL_TYPE_IO) if (schib.pmcw.st != SUBCHANNEL_TYPE_IO)
return -ENODEV; return -ENODEV;

View file

@ -870,15 +870,10 @@ static int __init css_bus_init(void)
/* Try to enable MSS. */ /* Try to enable MSS. */
ret = chsc_enable_facility(CHSC_SDA_OC_MSS); ret = chsc_enable_facility(CHSC_SDA_OC_MSS);
switch (ret) { if (ret)
case 0: /* Success. */
max_ssid = __MAX_SSID;
break;
case -ENOMEM:
goto out;
default:
max_ssid = 0; max_ssid = 0;
} else /* Success. */
max_ssid = __MAX_SSID;
ret = slow_subchannel_init(); ret = slow_subchannel_init();
if (ret) if (ret)
@ -1048,6 +1043,11 @@ static int __init channel_subsystem_init_sync(void)
} }
subsys_initcall_sync(channel_subsystem_init_sync); subsys_initcall_sync(channel_subsystem_init_sync);
void channel_subsystem_reinit(void)
{
chsc_enable_facility(CHSC_SDA_OC_MSS);
}
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
static ssize_t cio_settle_write(struct file *file, const char __user *buf, static ssize_t cio_settle_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)

View file

@ -45,7 +45,7 @@ static void ccw_timeout_log(struct ccw_device *cdev)
sch = to_subchannel(cdev->dev.parent); sch = to_subchannel(cdev->dev.parent);
private = to_io_private(sch); private = to_io_private(sch);
orb = &private->orb; orb = &private->orb;
cc = stsch(sch->schid, &schib); cc = stsch_err(sch->schid, &schib);
printk(KERN_WARNING "cio: ccw device timeout occurred at %llx, " printk(KERN_WARNING "cio: ccw device timeout occurred at %llx, "
"device information:\n", get_clock()); "device information:\n", get_clock());