diff options
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/block/dasd_devmap.c | 8 | ||||
-rw-r--r-- | drivers/s390/block/dasd_eckd.c | 54 | ||||
-rw-r--r-- | drivers/s390/block/dasd_erp.c | 14 | ||||
-rw-r--r-- | drivers/s390/char/sclp_config.c | 2 | ||||
-rw-r--r-- | drivers/s390/cio/airq.c | 174 | ||||
-rw-r--r-- | drivers/s390/cio/ccwgroup.c | 2 | ||||
-rw-r--r-- | drivers/s390/cio/cio.c | 46 | ||||
-rw-r--r-- | drivers/s390/cio/cio.h | 3 | ||||
-rw-r--r-- | drivers/s390/cio/cmf.c | 2 | ||||
-rw-r--r-- | drivers/s390/cio/css.c | 4 | ||||
-rw-r--r-- | drivers/s390/cio/css.h | 2 | ||||
-rw-r--r-- | drivers/s390/cio/device.c | 2 | ||||
-rw-r--r-- | drivers/s390/net/qeth_l3_sys.c | 2 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_aux.c | 4 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_erp.c | 29 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_ext.h | 2 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_fsf.c | 12 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_qdio.c | 12 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_sysfs.c | 26 |
19 files changed, 312 insertions, 88 deletions
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index 58bc6eb49de1..2ead7e78c456 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c @@ -930,7 +930,7 @@ dasd_use_raw_store(struct device *dev, struct device_attribute *attr, if (IS_ERR(devmap)) return PTR_ERR(devmap); - if ((strict_strtoul(buf, 10, &val) != 0) || val > 1) + if ((kstrtoul(buf, 10, &val) != 0) || val > 1) return -EINVAL; spin_lock(&dasd_devmap_lock); @@ -1225,7 +1225,7 @@ dasd_expires_store(struct device *dev, struct device_attribute *attr, if (IS_ERR(device)) return -ENODEV; - if ((strict_strtoul(buf, 10, &val) != 0) || + if ((kstrtoul(buf, 10, &val) != 0) || (val > DASD_EXPIRES_MAX) || val == 0) { dasd_put_device(device); return -EINVAL; @@ -1265,7 +1265,7 @@ dasd_retries_store(struct device *dev, struct device_attribute *attr, if (IS_ERR(device)) return -ENODEV; - if ((strict_strtoul(buf, 10, &val) != 0) || + if ((kstrtoul(buf, 10, &val) != 0) || (val > DASD_RETRIES_MAX)) { dasd_put_device(device); return -EINVAL; @@ -1307,7 +1307,7 @@ dasd_timeout_store(struct device *dev, struct device_attribute *attr, if (IS_ERR(device) || !device->block) return -ENODEV; - if ((strict_strtoul(buf, 10, &val) != 0) || + if ((kstrtoul(buf, 10, &val) != 0) || val > UINT_MAX / HZ) { dasd_put_device(device); return -EINVAL; diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index e61a6deea3c0..5adb2042e824 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -85,6 +85,8 @@ MODULE_DEVICE_TABLE(ccw, dasd_eckd_ids); static struct ccw_driver dasd_eckd_driver; /* see below */ +static void *rawpadpage; + #define INIT_CQR_OK 0 #define INIT_CQR_UNFORMATTED 1 #define INIT_CQR_ERROR 2 @@ -3237,18 +3239,26 @@ static struct dasd_ccw_req *dasd_raw_build_cp(struct dasd_device *startdev, unsigned int seg_len, len_to_track_end; unsigned int first_offs; unsigned int cidaw, cplength, datasize; - sector_t first_trk, last_trk; + sector_t first_trk, last_trk, sectors; + sector_t start_padding_sectors, end_sector_offset, end_padding_sectors; unsigned int pfx_datasize; /* * raw track access needs to be mutiple of 64k and on 64k boundary + * For read requests we can fix an incorrect alignment by padding + * the request with dummy pages. */ - if ((blk_rq_pos(req) % DASD_RAW_SECTORS_PER_TRACK) != 0) { - cqr = ERR_PTR(-EINVAL); - goto out; - } - if (((blk_rq_pos(req) + blk_rq_sectors(req)) % - DASD_RAW_SECTORS_PER_TRACK) != 0) { + start_padding_sectors = blk_rq_pos(req) % DASD_RAW_SECTORS_PER_TRACK; + end_sector_offset = (blk_rq_pos(req) + blk_rq_sectors(req)) % + DASD_RAW_SECTORS_PER_TRACK; + end_padding_sectors = (DASD_RAW_SECTORS_PER_TRACK - end_sector_offset) % + DASD_RAW_SECTORS_PER_TRACK; + basedev = block->base; + if ((start_padding_sectors || end_padding_sectors) && + (rq_data_dir(req) == WRITE)) { + DBF_DEV_EVENT(DBF_ERR, basedev, + "raw write not track aligned (%lu,%lu) req %p", + start_padding_sectors, end_padding_sectors, req); cqr = ERR_PTR(-EINVAL); goto out; } @@ -3258,7 +3268,6 @@ static struct dasd_ccw_req *dasd_raw_build_cp(struct dasd_device *startdev, DASD_RAW_SECTORS_PER_TRACK; trkcount = last_trk - first_trk + 1; first_offs = 0; - basedev = block->base; if (rq_data_dir(req) == READ) cmd = DASD_ECKD_CCW_READ_TRACK; @@ -3307,12 +3316,26 @@ static struct dasd_ccw_req *dasd_raw_build_cp(struct dasd_device *startdev, } idaws = (unsigned long *)(cqr->data + pfx_datasize); - len_to_track_end = 0; - + if (start_padding_sectors) { + ccw[-1].flags |= CCW_FLAG_CC; + ccw->cmd_code = cmd; + /* maximum 3390 track size */ + ccw->count = 57326; + /* 64k map to one track */ + len_to_track_end = 65536 - start_padding_sectors * 512; + ccw->cda = (__u32)(addr_t)idaws; + ccw->flags |= CCW_FLAG_IDA; + ccw->flags |= CCW_FLAG_SLI; + ccw++; + for (sectors = 0; sectors < start_padding_sectors; sectors += 8) + idaws = idal_create_words(idaws, rawpadpage, PAGE_SIZE); + } rq_for_each_segment(bv, req, iter) { dst = page_address(bv->bv_page) + bv->bv_offset; seg_len = bv->bv_len; + if (cmd == DASD_ECKD_CCW_READ_TRACK) + memset(dst, 0, seg_len); if (!len_to_track_end) { ccw[-1].flags |= CCW_FLAG_CC; ccw->cmd_code = cmd; @@ -3328,7 +3351,8 @@ static struct dasd_ccw_req *dasd_raw_build_cp(struct dasd_device *startdev, len_to_track_end -= seg_len; idaws = idal_create_words(idaws, dst, seg_len); } - + for (sectors = 0; sectors < end_padding_sectors; sectors += 8) + idaws = idal_create_words(idaws, rawpadpage, PAGE_SIZE); if (blk_noretry_request(req) || block->base->features & DASD_FEATURE_FAILFAST) set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags); @@ -4479,12 +4503,19 @@ dasd_eckd_init(void) kfree(dasd_reserve_req); return -ENOMEM; } + rawpadpage = (void *)__get_free_page(GFP_KERNEL); + if (!rawpadpage) { + kfree(path_verification_worker); + kfree(dasd_reserve_req); + return -ENOMEM; + } ret = ccw_driver_register(&dasd_eckd_driver); if (!ret) wait_for_device_probe(); else { kfree(path_verification_worker); kfree(dasd_reserve_req); + free_page((unsigned long)rawpadpage); } return ret; } @@ -4495,6 +4526,7 @@ dasd_eckd_cleanup(void) ccw_driver_unregister(&dasd_eckd_driver); kfree(path_verification_worker); kfree(dasd_reserve_req); + free_page((unsigned long)rawpadpage); } module_init(dasd_eckd_init); diff --git a/drivers/s390/block/dasd_erp.c b/drivers/s390/block/dasd_erp.c index 8d11f773a752..e1e88486b2b4 100644 --- a/drivers/s390/block/dasd_erp.c +++ b/drivers/s390/block/dasd_erp.c @@ -124,10 +124,15 @@ dasd_default_erp_action(struct dasd_ccw_req *cqr) struct dasd_ccw_req *dasd_default_erp_postaction(struct dasd_ccw_req *cqr) { int success; + unsigned long long startclk, stopclk; + struct dasd_device *startdev; BUG_ON(cqr->refers == NULL || cqr->function == NULL); success = cqr->status == DASD_CQR_DONE; + startclk = cqr->startclk; + stopclk = cqr->stopclk; + startdev = cqr->startdev; /* free all ERPs - but NOT the original cqr */ while (cqr->refers != NULL) { @@ -142,6 +147,9 @@ struct dasd_ccw_req *dasd_default_erp_postaction(struct dasd_ccw_req *cqr) } /* set corresponding status to original cqr */ + cqr->startclk = startclk; + cqr->stopclk = stopclk; + cqr->startdev = startdev; if (success) cqr->status = DASD_CQR_DONE; else { @@ -160,11 +168,13 @@ dasd_log_sense(struct dasd_ccw_req *cqr, struct irb *irb) device = cqr->startdev; if (cqr->intrc == -ETIMEDOUT) { - dev_err(&device->cdev->dev, "cqr %p timeout error", cqr); + dev_err(&device->cdev->dev, + "A timeout error occurred for cqr %p", cqr); return; } if (cqr->intrc == -ENOLINK) { - dev_err(&device->cdev->dev, "cqr %p transport error", cqr); + dev_err(&device->cdev->dev, + "A transport error occurred for cqr %p", cqr); return; } /* dump sense data */ diff --git a/drivers/s390/char/sclp_config.c b/drivers/s390/char/sclp_config.c index 444d36183a25..944156207477 100644 --- a/drivers/s390/char/sclp_config.c +++ b/drivers/s390/char/sclp_config.c @@ -32,7 +32,7 @@ static void sclp_cpu_capability_notify(struct work_struct *work) struct device *dev; s390_adjust_jiffies(); - pr_warning("cpu capability changed.\n"); + pr_info("CPU capability may have changed\n"); get_online_cpus(); for_each_online_cpu(cpu) { dev = get_cpu_device(cpu); diff --git a/drivers/s390/cio/airq.c b/drivers/s390/cio/airq.c index 91edbd7ee806..d028fd800c9c 100644 --- a/drivers/s390/cio/airq.c +++ b/drivers/s390/cio/airq.c @@ -81,15 +81,185 @@ void unregister_adapter_interrupt(struct airq_struct *airq) } EXPORT_SYMBOL(unregister_adapter_interrupt); -void do_adapter_IO(u8 isc) +static irqreturn_t do_airq_interrupt(int irq, void *dummy) { + struct tpi_info *tpi_info; struct airq_struct *airq; struct hlist_head *head; - head = &airq_lists[isc]; + __this_cpu_write(s390_idle.nohz_delay, 1); + tpi_info = (struct tpi_info *) &get_irq_regs()->int_code; + head = &airq_lists[tpi_info->isc]; rcu_read_lock(); hlist_for_each_entry_rcu(airq, head, list) if ((*airq->lsi_ptr & airq->lsi_mask) != 0) airq->handler(airq); rcu_read_unlock(); + + return IRQ_HANDLED; +} + +static struct irqaction airq_interrupt = { + .name = "AIO", + .handler = do_airq_interrupt, +}; + +void __init init_airq_interrupts(void) +{ + irq_set_chip_and_handler(THIN_INTERRUPT, + &dummy_irq_chip, handle_percpu_irq); + setup_irq(THIN_INTERRUPT, &airq_interrupt); +} + +/** + * airq_iv_create - create an interrupt vector + * @bits: number of bits in the interrupt vector + * @flags: allocation flags + * + * Returns a pointer to an interrupt vector structure + */ +struct airq_iv *airq_iv_create(unsigned long bits, unsigned long flags) +{ + struct airq_iv *iv; + unsigned long size; + + iv = kzalloc(sizeof(*iv), GFP_KERNEL); + if (!iv) + goto out; + iv->bits = bits; + size = BITS_TO_LONGS(bits) * sizeof(unsigned long); + iv->vector = kzalloc(size, GFP_KERNEL); + if (!iv->vector) + goto out_free; + if (flags & AIRQ_IV_ALLOC) { + iv->avail = kmalloc(size, GFP_KERNEL); + if (!iv->avail) + goto out_free; + memset(iv->avail, 0xff, size); + iv->end = 0; + } else + iv->end = bits; + if (flags & AIRQ_IV_BITLOCK) { + iv->bitlock = kzalloc(size, GFP_KERNEL); + if (!iv->bitlock) + goto out_free; + } + if (flags & AIRQ_IV_PTR) { + size = bits * sizeof(unsigned long); + iv->ptr = kzalloc(size, GFP_KERNEL); + if (!iv->ptr) + goto out_free; + } + if (flags & AIRQ_IV_DATA) { + size = bits * sizeof(unsigned int); + iv->data = kzalloc(size, GFP_KERNEL); + if (!iv->data) + goto out_free; + } + spin_lock_init(&iv->lock); + return iv; + +out_free: + kfree(iv->ptr); + kfree(iv->bitlock); + kfree(iv->avail); + kfree(iv->vector); + kfree(iv); +out: + return NULL; +} +EXPORT_SYMBOL(airq_iv_create); + +/** + * airq_iv_release - release an interrupt vector + * @iv: pointer to interrupt vector structure + */ +void airq_iv_release(struct airq_iv *iv) +{ + kfree(iv->data); + kfree(iv->ptr); + kfree(iv->bitlock); + kfree(iv->vector); + kfree(iv->avail); + kfree(iv); +} +EXPORT_SYMBOL(airq_iv_release); + +/** + * airq_iv_alloc_bit - allocate an irq bit from an interrupt vector + * @iv: pointer to an interrupt vector structure + * + * Returns the bit number of the allocated irq, or -1UL if no bit + * is available or the AIRQ_IV_ALLOC flag has not been specified + */ +unsigned long airq_iv_alloc_bit(struct airq_iv *iv) +{ + const unsigned long be_to_le = BITS_PER_LONG - 1; + unsigned long bit; + + if (!iv->avail) + return -1UL; + spin_lock(&iv->lock); + bit = find_first_bit_left(iv->avail, iv->bits); + if (bit < iv->bits) { + clear_bit(bit ^ be_to_le, iv->avail); + if (bit >= iv->end) + iv->end = bit + 1; + } else + bit = -1UL; + spin_unlock(&iv->lock); + return bit; + +} +EXPORT_SYMBOL(airq_iv_alloc_bit); + +/** + * airq_iv_free_bit - free an irq bit of an interrupt vector + * @iv: pointer to interrupt vector structure + * @bit: number of the irq bit to free + */ +void airq_iv_free_bit(struct airq_iv *iv, unsigned long bit) +{ + const unsigned long be_to_le = BITS_PER_LONG - 1; + + if (!iv->avail) + return; + spin_lock(&iv->lock); + /* Clear (possibly left over) interrupt bit */ + clear_bit(bit ^ be_to_le, iv->vector); + /* Make the bit position available again */ + set_bit(bit ^ be_to_le, iv->avail); + if (bit == iv->end - 1) { + /* Find new end of bit-field */ + while (--iv->end > 0) + if (!test_bit((iv->end - 1) ^ be_to_le, iv->avail)) + break; + } + spin_unlock(&iv->lock); +} +EXPORT_SYMBOL(airq_iv_free_bit); + +/** + * airq_iv_scan - scan interrupt vector for non-zero bits + * @iv: pointer to interrupt vector structure + * @start: bit number to start the search + * @end: bit number to end the search + * + * Returns the bit number of the next non-zero interrupt bit, or + * -1UL if the scan completed without finding any more any non-zero bits. + */ +unsigned long airq_iv_scan(struct airq_iv *iv, unsigned long start, + unsigned long end) +{ + const unsigned long be_to_le = BITS_PER_LONG - 1; + unsigned long bit; + + /* Find non-zero bit starting from 'ivs->next'. */ + bit = find_next_bit_left(iv->vector, end, start); + if (bit >= end) + return -1UL; + /* Clear interrupt bit (find left uses big-endian bit numbers) */ + clear_bit(bit ^ be_to_le, iv->vector); + return bit; } +EXPORT_SYMBOL(airq_iv_scan); diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 84846c2b96d3..959135a01847 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -137,7 +137,7 @@ static ssize_t ccwgroup_online_store(struct device *dev, if (!try_module_get(gdrv->driver.owner)) return -EINVAL; - ret = strict_strtoul(buf, 0, &value); + ret = kstrtoul(buf, 0, &value); if (ret) goto out; diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 4eeb4a6bf207..d7da67a31c77 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -561,37 +561,23 @@ out: } /* - * do_IRQ() handles all normal I/O device IRQ's (the special - * SMP cross-CPU interrupts have their own specific - * handlers). - * + * do_cio_interrupt() handles all normal I/O device IRQ's */ -void __irq_entry do_IRQ(struct pt_regs *regs) +static irqreturn_t do_cio_interrupt(int irq, void *dummy) { - struct tpi_info *tpi_info = (struct tpi_info *) ®s->int_code; + struct tpi_info *tpi_info; struct subchannel *sch; struct irb *irb; - struct pt_regs *old_regs; - old_regs = set_irq_regs(regs); - irq_enter(); __this_cpu_write(s390_idle.nohz_delay, 1); - if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator) - /* Serve timer interrupts first. */ - clock_comparator_work(); - - kstat_incr_irqs_this_cpu(IO_INTERRUPT, NULL); + tpi_info = (struct tpi_info *) &get_irq_regs()->int_code; irb = (struct irb *) &S390_lowcore.irb; - if (tpi_info->adapter_IO) { - do_adapter_IO(tpi_info->isc); - goto out; - } sch = (struct subchannel *)(unsigned long) tpi_info->intparm; if (!sch) { /* Clear pending interrupt condition. */ inc_irq_stat(IRQIO_CIO); tsch(tpi_info->schid, irb); - goto out; + return IRQ_HANDLED; } spin_lock(sch->lock); /* Store interrupt response block to lowcore. */ @@ -606,9 +592,23 @@ void __irq_entry do_IRQ(struct pt_regs *regs) } else inc_irq_stat(IRQIO_CIO); spin_unlock(sch->lock); -out: - irq_exit(); - set_irq_regs(old_regs); + + return IRQ_HANDLED; +} + +static struct irq_desc *irq_desc_io; + +static struct irqaction io_interrupt = { + .name = "IO", + .handler = do_cio_interrupt, +}; + +void __init init_cio_interrupts(void) +{ + irq_set_chip_and_handler(IO_INTERRUPT, + &dummy_irq_chip, handle_percpu_irq); + setup_irq(IO_INTERRUPT, &io_interrupt); + irq_desc_io = irq_to_desc(IO_INTERRUPT); } #ifdef CONFIG_CCW_CONSOLE @@ -635,7 +635,7 @@ void cio_tsch(struct subchannel *sch) local_bh_disable(); irq_enter(); } - kstat_incr_irqs_this_cpu(IO_INTERRUPT, NULL); + kstat_incr_irqs_this_cpu(IO_INTERRUPT, irq_desc_io); if (sch->driver && sch->driver->irq) sch->driver->irq(sch); else diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h index d62f5e7f3cf1..d42f67412bd8 100644 --- a/drivers/s390/cio/cio.h +++ b/drivers/s390/cio/cio.h @@ -121,9 +121,6 @@ extern int cio_commit_config(struct subchannel *sch); int cio_tm_start_key(struct subchannel *sch, struct tcw *tcw, u8 lpm, u8 key); int cio_tm_intrg(struct subchannel *sch); -void do_adapter_IO(u8 isc); -void do_IRQ(struct pt_regs *); - /* Use with care. */ #ifdef CONFIG_CCW_CONSOLE extern struct subchannel *cio_probe_console(void); diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c index 4495e0627a40..23054f8fa9fc 100644 --- a/drivers/s390/cio/cmf.c +++ b/drivers/s390/cio/cmf.c @@ -1182,7 +1182,7 @@ static ssize_t cmb_enable_store(struct device *dev, int ret; unsigned long val; - ret = strict_strtoul(buf, 16, &val); + ret = kstrtoul(buf, 16, &val); if (ret) return ret; diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 1ebe5d3ddebb..8c2cb87bccc5 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -546,7 +546,9 @@ static int slow_eval_unknown_fn(struct subchannel_id schid, void *data) case -ENOMEM: case -EIO: /* These should abort looping */ + spin_lock_irq(&slow_subchannel_lock); idset_sch_del_subseq(slow_subchannel_set, schid); + spin_unlock_irq(&slow_subchannel_lock); break; default: rc = 0; @@ -740,7 +742,7 @@ css_cm_enable_store(struct device *dev, struct device_attribute *attr, int ret; unsigned long val; - ret = strict_strtoul(buf, 16, &val); + ret = kstrtoul(buf, 16, &val); if (ret) return ret; mutex_lock(&css->mutex); diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h index b1de60335238..29351321bad6 100644 --- a/drivers/s390/cio/css.h +++ b/drivers/s390/cio/css.h @@ -130,8 +130,6 @@ struct channel_subsystem { extern struct channel_subsystem *channel_subsystems[]; -void channel_subsystem_reinit(void); - /* Helper functions to build lists for the slow path. */ void css_schedule_eval(struct subchannel_id schid); void css_schedule_eval_all(void); diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 1ab5f6c36d9b..e4a7ab2bb629 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -564,7 +564,7 @@ static ssize_t online_store (struct device *dev, struct device_attribute *attr, ret = 0; } else { force = 0; - ret = strict_strtoul(buf, 16, &i); + ret = kstrtoul(buf, 16, &i); } if (ret) goto out; diff --git a/drivers/s390/net/qeth_l3_sys.c b/drivers/s390/net/qeth_l3_sys.c index d1c8025b0b03..adef5f5de118 100644 --- a/drivers/s390/net/qeth_l3_sys.c +++ b/drivers/s390/net/qeth_l3_sys.c @@ -208,7 +208,7 @@ static ssize_t qeth_l3_dev_sniffer_store(struct device *dev, goto out; } - rc = strict_strtoul(buf, 16, &i); + rc = kstrtoul(buf, 16, &i); if (rc) { rc = -EINVAL; goto out; diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 1b9e4aee914b..8004b071a9f2 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -104,11 +104,11 @@ static void __init zfcp_init_device_setup(char *devstr) strncpy(busid, token, ZFCP_BUS_ID_SIZE); token = strsep(&str, ","); - if (!token || strict_strtoull(token, 0, (unsigned long long *) &wwpn)) + if (!token || kstrtoull(token, 0, (unsigned long long *) &wwpn)) goto err_out; token = strsep(&str, ","); - if (!token || strict_strtoull(token, 0, (unsigned long long *) &lun)) + if (!token || kstrtoull(token, 0, (unsigned long long *) &lun)) goto err_out; kfree(str_saved); diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 1d4c8fe72752..c82fe65c4128 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -102,10 +102,13 @@ static void zfcp_erp_action_dismiss_port(struct zfcp_port *port) if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_INUSE) zfcp_erp_action_dismiss(&port->erp_action); - else - shost_for_each_device(sdev, port->adapter->scsi_host) + else { + spin_lock(port->adapter->scsi_host->host_lock); + __shost_for_each_device(sdev, port->adapter->scsi_host) if (sdev_to_zfcp(sdev)->port == port) zfcp_erp_action_dismiss_lun(sdev); + spin_unlock(port->adapter->scsi_host->host_lock); + } } static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter) @@ -592,9 +595,11 @@ static void _zfcp_erp_lun_reopen_all(struct zfcp_port *port, int clear, { struct scsi_device *sdev; - shost_for_each_device(sdev, port->adapter->scsi_host) + spin_lock(port->adapter->scsi_host->host_lock); + __shost_for_each_device(sdev, port->adapter->scsi_host) if (sdev_to_zfcp(sdev)->port == port) _zfcp_erp_lun_reopen(sdev, clear, id, 0); + spin_unlock(port->adapter->scsi_host->host_lock); } static void zfcp_erp_strategy_followup_failed(struct zfcp_erp_action *act) @@ -1434,8 +1439,10 @@ void zfcp_erp_set_adapter_status(struct zfcp_adapter *adapter, u32 mask) atomic_set_mask(common_mask, &port->status); read_unlock_irqrestore(&adapter->port_list_lock, flags); - shost_for_each_device(sdev, adapter->scsi_host) + spin_lock_irqsave(adapter->scsi_host->host_lock, flags); + __shost_for_each_device(sdev, adapter->scsi_host) atomic_set_mask(common_mask, &sdev_to_zfcp(sdev)->status); + spin_unlock_irqrestore(adapter->scsi_host->host_lock, flags); } /** @@ -1469,11 +1476,13 @@ void zfcp_erp_clear_adapter_status(struct zfcp_adapter *adapter, u32 mask) } read_unlock_irqrestore(&adapter->port_list_lock, flags); - shost_for_each_device(sdev, adapter->scsi_host) { + spin_lock_irqsave(adapter->scsi_host->host_lock, flags); + __shost_for_each_device(sdev, adapter->scsi_host) { atomic_clear_mask(common_mask, &sdev_to_zfcp(sdev)->status); if (clear_counter) atomic_set(&sdev_to_zfcp(sdev)->erp_counter, 0); } + spin_unlock_irqrestore(adapter->scsi_host->host_lock, flags); } /** @@ -1487,16 +1496,19 @@ void zfcp_erp_set_port_status(struct zfcp_port *port, u32 mask) { struct scsi_device *sdev; u32 common_mask = mask & ZFCP_COMMON_FLAGS; + unsigned long flags; atomic_set_mask(mask, &port->status); if (!common_mask) return; - shost_for_each_device(sdev, port->adapter->scsi_host) + spin_lock_irqsave(port->adapter->scsi_host->host_lock, flags); + __shost_for_each_device(sdev, port->adapter->scsi_host) if (sdev_to_zfcp(sdev)->port == port) atomic_set_mask(common_mask, &sdev_to_zfcp(sdev)->status); + spin_unlock_irqrestore(port->adapter->scsi_host->host_lock, flags); } /** @@ -1511,6 +1523,7 @@ void zfcp_erp_clear_port_status(struct zfcp_port *port, u32 mask) struct scsi_device *sdev; u32 common_mask = mask & ZFCP_COMMON_FLAGS; u32 clear_counter = mask & ZFCP_STATUS_COMMON_ERP_FAILED; + unsigned long flags; atomic_clear_mask(mask, &port->status); @@ -1520,13 +1533,15 @@ void zfcp_erp_clear_port_status(struct zfcp_port *port, u32 mask) if (clear_counter) atomic_set(&port->erp_counter, 0); - shost_for_each_device(sdev, port->adapter->scsi_host) + spin_lock_irqsave(port->adapter->scsi_host->host_lock, flags); + __shost_for_each_device(sdev, port->adapter->scsi_host) if (sdev_to_zfcp(sdev)->port == port) { atomic_clear_mask(common_mask, &sdev_to_zfcp(sdev)->status); if (clear_counter) atomic_set(&sdev_to_zfcp(sdev)->erp_counter, 0); } + spin_unlock_irqrestore(port->adapter->scsi_host->host_lock, flags); } /** diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index 83e3f1408c38..a9c570a09b85 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -126,8 +126,6 @@ extern int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *, struct zfcp_qdio_req *, extern int zfcp_qdio_open(struct zfcp_qdio *); extern void zfcp_qdio_close(struct zfcp_qdio *); extern void zfcp_qdio_siosl(struct zfcp_adapter *); -extern struct zfcp_fsf_req *zfcp_fsf_get_req(struct zfcp_qdio *, - struct qdio_buffer *); /* zfcp_scsi.c */ extern struct scsi_transport_template *zfcp_scsi_transport_template; diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 510e9b06c1a1..0fe8d5d95119 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -770,7 +770,8 @@ int zfcp_fsf_status_read(struct zfcp_qdio *qdio) if (zfcp_qdio_sbal_get(qdio)) goto out; - req = zfcp_fsf_req_create(qdio, FSF_QTCB_UNSOLICITED_STATUS, 0, + req = zfcp_fsf_req_create(qdio, FSF_QTCB_UNSOLICITED_STATUS, + SBAL_SFLAGS0_TYPE_STATUS, adapter->pool.status_read_req); if (IS_ERR(req)) { retval = PTR_ERR(req); @@ -2387,12 +2388,3 @@ void zfcp_fsf_reqid_check(struct zfcp_qdio *qdio, int sbal_idx) break; } } - -struct zfcp_fsf_req *zfcp_fsf_get_req(struct zfcp_qdio *qdio, - struct qdio_buffer *sbal) -{ - struct qdio_buffer_element *sbale = &sbal->element[0]; - u64 req_id = (unsigned long) sbale->addr; - - return zfcp_reqlist_find(qdio->adapter->req_list, req_id); -} diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index 665e3cfaaf85..06025cdaa4ad 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c @@ -16,9 +16,9 @@ #define QBUFF_PER_PAGE (PAGE_SIZE / sizeof(struct qdio_buffer)) -static bool enable_multibuffer; +static bool enable_multibuffer = 1; module_param_named(datarouter, enable_multibuffer, bool, 0400); -MODULE_PARM_DESC(datarouter, "Enable hardware data router support"); +MODULE_PARM_DESC(datarouter, "Enable hardware data router support (default on)"); static int zfcp_qdio_buffers_enqueue(struct qdio_buffer **sbal) { @@ -224,11 +224,9 @@ int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req, static int zfcp_qdio_sbal_check(struct zfcp_qdio *qdio) { - spin_lock_irq(&qdio->req_q_lock); if (atomic_read(&qdio->req_q_free) || !(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP)) return 1; - spin_unlock_irq(&qdio->req_q_lock); return 0; } @@ -246,9 +244,8 @@ int zfcp_qdio_sbal_get(struct zfcp_qdio *qdio) { long ret; - spin_unlock_irq(&qdio->req_q_lock); - ret = wait_event_interruptible_timeout(qdio->req_q_wq, - zfcp_qdio_sbal_check(qdio), 5 * HZ); + ret = wait_event_interruptible_lock_irq_timeout(qdio->req_q_wq, + zfcp_qdio_sbal_check(qdio), qdio->req_q_lock, 5 * HZ); if (!(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP)) return -EIO; @@ -262,7 +259,6 @@ int zfcp_qdio_sbal_get(struct zfcp_qdio *qdio) zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdsbg_1"); } - spin_lock_irq(&qdio->req_q_lock); return -EIO; } diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c index 3f01bbf0609f..672b57219e11 100644 --- a/drivers/s390/scsi/zfcp_sysfs.c +++ b/drivers/s390/scsi/zfcp_sysfs.c @@ -27,6 +27,16 @@ static ssize_t zfcp_sysfs_##_feat##_##_name##_show(struct device *dev, \ static ZFCP_DEV_ATTR(_feat, _name, S_IRUGO, \ zfcp_sysfs_##_feat##_##_name##_show, NULL); +#define ZFCP_DEFINE_ATTR_CONST(_feat, _name, _format, _value) \ +static ssize_t zfcp_sysfs_##_feat##_##_name##_show(struct device *dev, \ + struct device_attribute *at,\ + char *buf) \ +{ \ + return sprintf(buf, _format, _value); \ +} \ +static ZFCP_DEV_ATTR(_feat, _name, S_IRUGO, \ + zfcp_sysfs_##_feat##_##_name##_show, NULL); + #define ZFCP_DEFINE_A_ATTR(_name, _format, _value) \ static ssize_t zfcp_sysfs_adapter_##_name##_show(struct device *dev, \ struct device_attribute *at,\ @@ -75,6 +85,8 @@ ZFCP_DEFINE_ATTR(zfcp_unit, unit, in_recovery, "%d\n", ZFCP_DEFINE_ATTR(zfcp_unit, unit, access_denied, "%d\n", (zfcp_unit_sdev_status(unit) & ZFCP_STATUS_COMMON_ACCESS_DENIED) != 0); +ZFCP_DEFINE_ATTR_CONST(unit, access_shared, "%d\n", 0); +ZFCP_DEFINE_ATTR_CONST(unit, access_readonly, "%d\n", 0); static ssize_t zfcp_sysfs_port_failed_show(struct device *dev, struct device_attribute *attr, @@ -95,7 +107,7 @@ static ssize_t zfcp_sysfs_port_failed_store(struct device *dev, struct zfcp_port *port = container_of(dev, struct zfcp_port, dev); unsigned long val; - if (strict_strtoul(buf, 0, &val) || val != 0) + if (kstrtoul(buf, 0, &val) || val != 0) return -EINVAL; zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_RUNNING); @@ -134,7 +146,7 @@ static ssize_t zfcp_sysfs_unit_failed_store(struct device *dev, unsigned long val; struct scsi_device *sdev; - if (strict_strtoul(buf, 0, &val) || val != 0) + if (kstrtoul(buf, 0, &val) || val != 0) return -EINVAL; sdev = zfcp_unit_sdev(unit); @@ -184,7 +196,7 @@ static ssize_t zfcp_sysfs_adapter_failed_store(struct device *dev, if (!adapter) return -ENODEV; - if (strict_strtoul(buf, 0, &val) || val != 0) { + if (kstrtoul(buf, 0, &val) || val != 0) { retval = -EINVAL; goto out; } @@ -236,7 +248,7 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev, if (!adapter) return -ENODEV; - if (strict_strtoull(buf, 0, (unsigned long long *) &wwpn)) + if (kstrtoull(buf, 0, (unsigned long long *) &wwpn)) goto out; port = zfcp_get_port_by_wwpn(adapter, wwpn); @@ -297,7 +309,7 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev, u64 fcp_lun; int retval; - if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun)) + if (kstrtoull(buf, 0, (unsigned long long *) &fcp_lun)) return -EINVAL; retval = zfcp_unit_add(port, fcp_lun); @@ -315,7 +327,7 @@ static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev, struct zfcp_port *port = container_of(dev, struct zfcp_port, dev); u64 fcp_lun; - if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun)) + if (kstrtoull(buf, 0, (unsigned long long *) &fcp_lun)) return -EINVAL; if (zfcp_unit_remove(port, fcp_lun)) @@ -347,6 +359,8 @@ static struct attribute *zfcp_unit_attrs[] = { &dev_attr_unit_in_recovery.attr, &dev_attr_unit_status.attr, &dev_attr_unit_access_denied.attr, + &dev_attr_unit_access_shared.attr, + &dev_attr_unit_access_readonly.attr, NULL }; static struct attribute_group zfcp_unit_attr_group = { |