diff options
Diffstat (limited to 'drivers/s390')
29 files changed, 378 insertions, 892 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 04143c08bd6e..cb9b685118da 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -3034,7 +3034,8 @@ static blk_status_t do_dasd_request(struct blk_mq_hw_ctx *hctx, cqr->callback_data = req; cqr->status = DASD_CQR_FILLED; cqr->dq = dq; - req->completion_data = cqr; + *((struct dasd_ccw_req **) blk_mq_rq_to_pdu(req)) = cqr; + blk_mq_start_request(req); spin_lock(&block->queue_lock); list_add_tail(&cqr->blocklist, &block->ccw_queue); @@ -3053,19 +3054,20 @@ out: * * Return values: * BLK_EH_RESET_TIMER if the request should be left running - * BLK_EH_NOT_HANDLED if the request is handled or terminated + * BLK_EH_DONE if the request is handled or terminated * by the driver. */ enum blk_eh_timer_return dasd_times_out(struct request *req, bool reserved) { - struct dasd_ccw_req *cqr = req->completion_data; struct dasd_block *block = req->q->queuedata; struct dasd_device *device; + struct dasd_ccw_req *cqr; unsigned long flags; int rc = 0; + cqr = *((struct dasd_ccw_req **) blk_mq_rq_to_pdu(req)); if (!cqr) - return BLK_EH_NOT_HANDLED; + return BLK_EH_DONE; spin_lock_irqsave(&cqr->dq->lock, flags); device = cqr->startdev ? cqr->startdev : block->base; @@ -3124,7 +3126,7 @@ enum blk_eh_timer_return dasd_times_out(struct request *req, bool reserved) spin_unlock(&block->queue_lock); spin_unlock_irqrestore(&cqr->dq->lock, flags); - return rc ? BLK_EH_RESET_TIMER : BLK_EH_NOT_HANDLED; + return rc ? BLK_EH_RESET_TIMER : BLK_EH_DONE; } static int dasd_init_hctx(struct blk_mq_hw_ctx *hctx, void *data, @@ -3169,6 +3171,7 @@ static int dasd_alloc_queue(struct dasd_block *block) int rc; block->tag_set.ops = &dasd_mq_ops; + block->tag_set.cmd_size = sizeof(struct dasd_ccw_req *); block->tag_set.nr_hw_queues = DASD_NR_HW_QUEUES; block->tag_set.queue_depth = DASD_MAX_LCU_DEV * DASD_REQ_PER_DEV; block->tag_set.flags = BLK_MQ_F_SHOULD_MERGE; diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c index 62f5f04d8f61..5e963fe0e38d 100644 --- a/drivers/s390/block/dasd_alias.c +++ b/drivers/s390/block/dasd_alias.c @@ -592,13 +592,22 @@ static int _schedule_lcu_update(struct alias_lcu *lcu, int dasd_alias_add_device(struct dasd_device *device) { struct dasd_eckd_private *private = device->private; - struct alias_lcu *lcu; + __u8 uaddr = private->uid.real_unit_addr; + struct alias_lcu *lcu = private->lcu; unsigned long flags; int rc; - lcu = private->lcu; rc = 0; spin_lock_irqsave(&lcu->lock, flags); + /* + * Check if device and lcu type differ. If so, the uac data may be + * outdated and needs to be updated. + */ + if (private->uid.type != lcu->uac->unit[uaddr].ua_type) { + lcu->flags |= UPDATE_PENDING; + DBF_DEV_EVENT(DBF_WARNING, device, "%s", + "uid type mismatch - trigger rescan"); + } if (!(lcu->flags & UPDATE_PENDING)) { rc = _add_device_to_lcu(lcu, device, device); if (rc) diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index f035c2f25d35..131f1989f6f3 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c @@ -27,7 +27,6 @@ #include <asm/io.h> #include <asm/irq.h> #include <asm/vtoc.h> -#include <asm/diag.h> #include "dasd_int.h" #include "dasd_diag.h" diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c index c33788a829c3..5cb80c645489 100644 --- a/drivers/s390/block/dasd_proc.c +++ b/drivers/s390/block/dasd_proc.c @@ -131,19 +131,6 @@ static const struct seq_operations dasd_devices_seq_ops = { .show = dasd_devices_show, }; -static int dasd_devices_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &dasd_devices_seq_ops); -} - -static const struct file_operations dasd_devices_file_ops = { - .owner = THIS_MODULE, - .open = dasd_devices_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - #ifdef CONFIG_DASD_PROFILE static int dasd_stats_all_block_on(void) { @@ -352,10 +339,10 @@ dasd_proc_init(void) dasd_proc_root_entry = proc_mkdir("dasd", NULL); if (!dasd_proc_root_entry) goto out_nodasd; - dasd_devices_entry = proc_create("devices", + dasd_devices_entry = proc_create_seq("devices", S_IFREG | S_IRUGO | S_IWUSR, dasd_proc_root_entry, - &dasd_devices_file_ops); + &dasd_devices_seq_ops); if (!dasd_devices_entry) goto out_nodevices; dasd_statistics_entry = proc_create("statistics", diff --git a/drivers/s390/char/sclp_early_core.c b/drivers/s390/char/sclp_early_core.c index 5f8d9ea69ebd..eceba3858cef 100644 --- a/drivers/s390/char/sclp_early_core.c +++ b/drivers/s390/char/sclp_early_core.c @@ -18,7 +18,7 @@ int sclp_init_state __section(.data) = sclp_init_state_uninitialized; * Used to keep track of the size of the event masks. Qemu until version 2.11 * only supports 4 and needs a workaround. */ -bool sclp_mask_compat_mode; +bool sclp_mask_compat_mode __section(.data); void sclp_early_wait_irq(void) { diff --git a/drivers/s390/char/tape_proc.c b/drivers/s390/char/tape_proc.c index faae30476f4b..32a14ee31c6b 100644 --- a/drivers/s390/char/tape_proc.c +++ b/drivers/s390/char/tape_proc.c @@ -105,29 +105,14 @@ static const struct seq_operations tape_proc_seq = { .show = tape_proc_show, }; -static int tape_proc_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &tape_proc_seq); -} - -static const struct file_operations tape_proc_ops = -{ - .owner = THIS_MODULE, - .open = tape_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - /* * Initialize procfs stuff on startup */ void tape_proc_init(void) { - tape_proc_devices = - proc_create("tapedevices", S_IFREG | S_IRUGO | S_IWUSR, NULL, - &tape_proc_ops); + tape_proc_devices = proc_create_seq("tapedevices", + S_IFREG | S_IRUGO | S_IWUSR, NULL, &tape_proc_seq); if (tape_proc_devices == NULL) { return; } diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index bfec1485ca23..5535312602af 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -323,6 +323,9 @@ int ccwgroup_create_dev(struct device *parent, struct ccwgroup_driver *gdrv, struct ccw_dev_id dev_id; int rc, i; + if (num_devices < 1) + return -EINVAL; + gdev = kzalloc(sizeof(*gdev) + num_devices * sizeof(gdev->cdev[0]), GFP_KERNEL); if (!gdev) @@ -375,7 +378,7 @@ int ccwgroup_create_dev(struct device *parent, struct ccwgroup_driver *gdrv, goto error; } /* Check if the devices are bound to the required ccw driver. */ - if (gdev->count && gdrv && gdrv->ccw_driver && + if (gdrv && gdrv->ccw_driver && gdev->cdev[0]->drv != gdrv->ccw_driver) { rc = -EINVAL; goto error; diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 6652a49a49b1..9029804dcd22 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -452,6 +452,7 @@ static void chsc_process_sei_link_incident(struct chsc_sei_nt0_area *sei_area) static void chsc_process_sei_res_acc(struct chsc_sei_nt0_area *sei_area) { + struct channel_path *chp; struct chp_link link; struct chp_id chpid; int status; @@ -464,10 +465,17 @@ static void chsc_process_sei_res_acc(struct chsc_sei_nt0_area *sei_area) chpid.id = sei_area->rsid; /* allocate a new channel path structure, if needed */ status = chp_get_status(chpid); - if (status < 0) - chp_new(chpid); - else if (!status) + if (!status) return; + + if (status < 0) { + chp_new(chpid); + } else { + chp = chpid_to_chp(chpid); + mutex_lock(&chp->lock); + chp_update_desc(chp); + mutex_unlock(&chp->lock); + } memset(&link, 0, sizeof(struct chp_link)); link.chpid = chpid; if ((sei_area->vf & 0xc0) != 0) { diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 6886b3d34cf8..5130d7c67239 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -25,7 +25,6 @@ #include <asm/irq.h> #include <asm/irq_regs.h> #include <asm/setup.h> -#include <asm/reset.h> #include <asm/ipl.h> #include <asm/chpid.h> #include <asm/airq.h> @@ -767,262 +766,6 @@ void cio_register_early_subchannels(void) } #endif /* CONFIG_CCW_CONSOLE */ -static int -__disable_subchannel_easy(struct subchannel_id schid, struct schib *schib) -{ - int retry, cc; - - cc = 0; - for (retry=0;retry<3;retry++) { - schib->pmcw.ena = 0; - cc = msch(schid, schib); - if (cc) - return (cc==3?-ENODEV:-EBUSY); - if (stsch(schid, schib) || !css_sch_is_valid(schib)) - return -ENODEV; - if (!schib->pmcw.ena) - return 0; - } - return -EBUSY; /* uhm... */ -} - -static int -__clear_io_subchannel_easy(struct subchannel_id schid) -{ - int retry; - - if (csch(schid)) - return -ENODEV; - for (retry=0;retry<20;retry++) { - struct tpi_info ti; - - if (tpi(&ti)) { - tsch(ti.schid, this_cpu_ptr(&cio_irb)); - if (schid_equal(&ti.schid, &schid)) - return 0; - } - udelay_simple(100); - } - return -EBUSY; -} - -static void __clear_chsc_subchannel_easy(void) -{ - /* It seems we can only wait for a bit here :/ */ - udelay_simple(100); -} - -static int pgm_check_occured; - -static void cio_reset_pgm_check_handler(void) -{ - pgm_check_occured = 1; -} - -static int stsch_reset(struct subchannel_id schid, struct schib *addr) -{ - int rc; - - pgm_check_occured = 0; - s390_base_pgm_handler_fn = cio_reset_pgm_check_handler; - rc = stsch(schid, addr); - s390_base_pgm_handler_fn = NULL; - - /* The program check handler could have changed pgm_check_occured. */ - barrier(); - - if (pgm_check_occured) - return -EIO; - else - return rc; -} - -static int __shutdown_subchannel_easy(struct subchannel_id schid, void *data) -{ - struct schib schib; - - if (stsch_reset(schid, &schib)) - return -ENXIO; - if (!schib.pmcw.ena) - return 0; - switch(__disable_subchannel_easy(schid, &schib)) { - case 0: - case -ENODEV: - break; - default: /* -EBUSY */ - switch (schib.pmcw.st) { - case SUBCHANNEL_TYPE_IO: - if (__clear_io_subchannel_easy(schid)) - goto out; /* give up... */ - break; - case SUBCHANNEL_TYPE_CHSC: - __clear_chsc_subchannel_easy(); - break; - default: - /* No default clear strategy */ - break; - } - stsch(schid, &schib); - __disable_subchannel_easy(schid, &schib); - } -out: - return 0; -} - -static atomic_t chpid_reset_count; - -static void s390_reset_chpids_mcck_handler(void) -{ - struct crw crw; - union mci mci; - - /* Check for pending channel report word. */ - mci.val = S390_lowcore.mcck_interruption_code; - if (!mci.cp) - return; - /* Process channel report words. */ - while (stcrw(&crw) == 0) { - /* Check for responses to RCHP. */ - if (crw.slct && crw.rsc == CRW_RSC_CPATH) - atomic_dec(&chpid_reset_count); - } -} - -#define RCHP_TIMEOUT (30 * USEC_PER_SEC) -static void css_reset(void) -{ - int i, ret; - unsigned long long timeout; - struct chp_id chpid; - - /* Reset subchannels. */ - for_each_subchannel(__shutdown_subchannel_easy, NULL); - /* Reset channel paths. */ - s390_base_mcck_handler_fn = s390_reset_chpids_mcck_handler; - /* Enable channel report machine checks. */ - __ctl_set_bit(14, 28); - /* Temporarily reenable machine checks. */ - local_mcck_enable(); - chp_id_init(&chpid); - for (i = 0; i <= __MAX_CHPID; i++) { - chpid.id = i; - ret = rchp(chpid); - if ((ret == 0) || (ret == 2)) - /* - * rchp either succeeded, or another rchp is already - * in progress. In either case, we'll get a crw. - */ - atomic_inc(&chpid_reset_count); - } - /* Wait for machine check for all channel paths. */ - timeout = get_tod_clock_fast() + (RCHP_TIMEOUT << 12); - while (atomic_read(&chpid_reset_count) != 0) { - if (get_tod_clock_fast() > timeout) - break; - cpu_relax(); - } - /* Disable machine checks again. */ - local_mcck_disable(); - /* Disable channel report machine checks. */ - __ctl_clear_bit(14, 28); - s390_base_mcck_handler_fn = NULL; -} - -static struct reset_call css_reset_call = { - .fn = css_reset, -}; - -static int __init init_css_reset_call(void) -{ - atomic_set(&chpid_reset_count, 0); - register_reset_call(&css_reset_call); - return 0; -} - -arch_initcall(init_css_reset_call); - -struct sch_match_id { - struct subchannel_id schid; - struct ccw_dev_id devid; - int rc; -}; - -static int __reipl_subchannel_match(struct subchannel_id schid, void *data) -{ - struct schib schib; - struct sch_match_id *match_id = data; - - if (stsch_reset(schid, &schib)) - return -ENXIO; - if ((schib.pmcw.st == SUBCHANNEL_TYPE_IO) && schib.pmcw.dnv && - (schib.pmcw.dev == match_id->devid.devno) && - (schid.ssid == match_id->devid.ssid)) { - match_id->schid = schid; - match_id->rc = 0; - return 1; - } - return 0; -} - -static int reipl_find_schid(struct ccw_dev_id *devid, - struct subchannel_id *schid) -{ - struct sch_match_id match_id; - - match_id.devid = *devid; - match_id.rc = -ENODEV; - for_each_subchannel(__reipl_subchannel_match, &match_id); - if (match_id.rc == 0) - *schid = match_id.schid; - return match_id.rc; -} - -extern void do_reipl_asm(__u32 schid); - -/* Make sure all subchannels are quiet before we re-ipl an lpar. */ -void reipl_ccw_dev(struct ccw_dev_id *devid) -{ - struct subchannel_id uninitialized_var(schid); - - s390_reset_system(); - if (reipl_find_schid(devid, &schid) != 0) - panic("IPL Device not found\n"); - do_reipl_asm(*((__u32*)&schid)); -} - -int __init cio_get_iplinfo(struct cio_iplinfo *iplinfo) -{ - static struct chsc_sda_area sda_area __initdata; - struct subchannel_id schid; - struct schib schib; - - schid = *(struct subchannel_id *)&S390_lowcore.subchannel_id; - if (!schid.one) - return -ENODEV; - - if (schid.ssid) { - /* - * Firmware should have already enabled MSS but whoever started - * the kernel might have initiated a channel subsystem reset. - * Ensure that MSS is enabled. - */ - memset(&sda_area, 0, sizeof(sda_area)); - if (__chsc_enable_facility(&sda_area, CHSC_SDA_OC_MSS)) - return -ENODEV; - } - if (stsch(schid, &schib)) - return -ENODEV; - if (schib.pmcw.st != SUBCHANNEL_TYPE_IO) - return -ENODEV; - if (!schib.pmcw.dnv) - return -ENODEV; - - iplinfo->ssid = schid.ssid; - iplinfo->devno = schib.pmcw.dev; - iplinfo->is_qdio = schib.pmcw.qf; - return 0; -} - /** * cio_tm_start_key - perform start function * @sch: subchannel on which to perform the start function diff --git a/drivers/s390/cio/ioasm.c b/drivers/s390/cio/ioasm.c index 4fa9ee1d09fa..14d328338ce2 100644 --- a/drivers/s390/cio/ioasm.c +++ b/drivers/s390/cio/ioasm.c @@ -183,30 +183,6 @@ int chsc(void *chsc_area) } EXPORT_SYMBOL(chsc); -static inline int __rchp(struct chp_id chpid) -{ - register struct chp_id reg1 asm ("1") = chpid; - int ccode; - - asm volatile( - " lr 1,%1\n" - " rchp\n" - " ipm %0\n" - " srl %0,28" - : "=d" (ccode) : "d" (reg1) : "cc"); - return ccode; -} - -int rchp(struct chp_id chpid) -{ - int ccode; - - ccode = __rchp(chpid); - trace_s390_cio_rchp(chpid, ccode); - - return ccode; -} - static inline int __rsch(struct subchannel_id schid) { register struct subchannel_id reg1 asm("1") = schid; diff --git a/drivers/s390/cio/ioasm.h b/drivers/s390/cio/ioasm.h index 35ad4ddd61e0..4be539cb9adc 100644 --- a/drivers/s390/cio/ioasm.h +++ b/drivers/s390/cio/ioasm.h @@ -20,7 +20,6 @@ int ssch(struct subchannel_id schid, union orb *addr); int csch(struct subchannel_id schid); int tpi(struct tpi_info *addr); int chsc(void *chsc_area); -int rchp(struct chp_id chpid); int rsch(struct subchannel_id schid); int hsch(struct subchannel_id schid); int xsch(struct subchannel_id schid); diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index a337281337a7..f4ca72dd862f 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -1207,8 +1207,10 @@ no_cleanup: qdio_shutdown_thinint(irq_ptr); /* restore interrupt handler */ - if ((void *)cdev->handler == (void *)qdio_int_handler) + if ((void *)cdev->handler == (void *)qdio_int_handler) { cdev->handler = irq_ptr->orig_handler; + cdev->private->intparm = 0; + } spin_unlock_irq(get_ccwdev_lock(cdev)); qdio_set_state(irq_ptr, QDIO_IRQ_STATE_INACTIVE); diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c index 98f3cfdc0d02..4c14ce428e92 100644 --- a/drivers/s390/cio/qdio_setup.c +++ b/drivers/s390/cio/qdio_setup.c @@ -141,7 +141,7 @@ static int __qdio_allocate_qs(struct qdio_q **irq_ptr_qs, int nr_queues) int i; for (i = 0; i < nr_queues; i++) { - q = kmem_cache_alloc(qdio_q_cache, GFP_KERNEL); + q = kmem_cache_zalloc(qdio_q_cache, GFP_KERNEL); if (!q) return -ENOMEM; @@ -456,7 +456,6 @@ int qdio_setup_irq(struct qdio_initialize *init_data) { struct ciw *ciw; struct qdio_irq *irq_ptr = init_data->cdev->private->qdio_data; - int rc; memset(&irq_ptr->qib, 0, sizeof(irq_ptr->qib)); memset(&irq_ptr->siga_flag, 0, sizeof(irq_ptr->siga_flag)); @@ -493,26 +492,23 @@ int qdio_setup_irq(struct qdio_initialize *init_data) ciw = ccw_device_get_ciw(init_data->cdev, CIW_TYPE_EQUEUE); if (!ciw) { DBF_ERROR("%4x NO EQ", irq_ptr->schid.sch_no); - rc = -EINVAL; - goto out_err; + return -EINVAL; } irq_ptr->equeue = *ciw; ciw = ccw_device_get_ciw(init_data->cdev, CIW_TYPE_AQUEUE); if (!ciw) { DBF_ERROR("%4x NO AQ", irq_ptr->schid.sch_no); - rc = -EINVAL; - goto out_err; + return -EINVAL; } irq_ptr->aqueue = *ciw; /* set new interrupt handler */ + spin_lock_irq(get_ccwdev_lock(irq_ptr->cdev)); irq_ptr->orig_handler = init_data->cdev->handler; init_data->cdev->handler = qdio_int_handler; + spin_unlock_irq(get_ccwdev_lock(irq_ptr->cdev)); return 0; -out_err: - qdio_release_memory(irq_ptr); - return rc; } void qdio_print_subchannel_info(struct qdio_irq *irq_ptr, diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c index 2c7550797ec2..dce92b2a895d 100644 --- a/drivers/s390/cio/vfio_ccw_cp.c +++ b/drivers/s390/cio/vfio_ccw_cp.c @@ -715,6 +715,10 @@ void cp_free(struct channel_program *cp) * and stores the result to ccwchain list. @cp must have been * initialized by a previous call with cp_init(). Otherwise, undefined * behavior occurs. + * For each chain composing the channel program: + * - On entry ch_len holds the count of CCWs to be translated. + * - On exit ch_len is adjusted to the count of successfully translated CCWs. + * This allows cp_free to find in ch_len the count of CCWs to free in a chain. * * The S/390 CCW Translation APIS (prefixed by 'cp_') are introduced * as helpers to do ccw chain translation inside the kernel. Basically @@ -749,11 +753,18 @@ int cp_prefetch(struct channel_program *cp) for (idx = 0; idx < len; idx++) { ret = ccwchain_fetch_one(chain, idx, cp); if (ret) - return ret; + goto out_err; } } return 0; +out_err: + /* Only cleanup the chain elements that were actually translated. */ + chain->ch_len = idx; + list_for_each_entry_continue(chain, &cp->ccwchain_list, next) { + chain->ch_len = 0; + } + return ret; } /** diff --git a/drivers/s390/cio/vfio_ccw_fsm.c b/drivers/s390/cio/vfio_ccw_fsm.c index ff6963ad6e39..3c800642134e 100644 --- a/drivers/s390/cio/vfio_ccw_fsm.c +++ b/drivers/s390/cio/vfio_ccw_fsm.c @@ -20,12 +20,12 @@ static int fsm_io_helper(struct vfio_ccw_private *private) int ccode; __u8 lpm; unsigned long flags; + int ret; sch = private->sch; spin_lock_irqsave(sch->lock, flags); private->state = VFIO_CCW_STATE_BUSY; - spin_unlock_irqrestore(sch->lock, flags); orb = cp_get_orb(&private->cp, (u32)(addr_t)sch, sch->lpm); @@ -38,10 +38,12 @@ static int fsm_io_helper(struct vfio_ccw_private *private) * Initialize device status information */ sch->schib.scsw.cmd.actl |= SCSW_ACTL_START_PEND; - return 0; + ret = 0; + break; case 1: /* Status pending */ case 2: /* Busy */ - return -EBUSY; + ret = -EBUSY; + break; case 3: /* Device/path not operational */ { lpm = orb->cmd.lpm; @@ -51,13 +53,16 @@ static int fsm_io_helper(struct vfio_ccw_private *private) sch->lpm = 0; if (cio_update_schib(sch)) - return -ENODEV; - - return sch->lpm ? -EACCES : -ENODEV; + ret = -ENODEV; + else + ret = sch->lpm ? -EACCES : -ENODEV; + break; } default: - return ccode; + ret = ccode; } + spin_unlock_irqrestore(sch->lock, flags); + return ret; } static void fsm_notoper(struct vfio_ccw_private *private, diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 48d55dc9e986..35a0c2b52f82 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c @@ -25,7 +25,6 @@ #include <linux/kthread.h> #include <linux/mutex.h> #include <linux/suspend.h> -#include <asm/reset.h> #include <asm/airq.h> #include <linux/atomic.h> #include <asm/isc.h> @@ -1197,26 +1196,7 @@ static void ap_config_timeout(struct timer_list *unused) queue_work(system_long_wq, &ap_scan_work); } -static void ap_reset_all(void) -{ - int i, j; - - for (i = 0; i < AP_DOMAINS; i++) { - if (!ap_test_config_domain(i)) - continue; - for (j = 0; j < AP_DEVICES; j++) { - if (!ap_test_config_card_id(j)) - continue; - ap_rapq(AP_MKQID(j, i)); - } - } -} - -static struct reset_call ap_reset_call = { - .fn = ap_reset_all, -}; - -int __init ap_debug_init(void) +static int __init ap_debug_init(void) { ap_dbf_info = debug_register("ap", 1, 1, DBF_MAX_SPRINTF_ARGS * sizeof(long)); @@ -1226,17 +1206,12 @@ int __init ap_debug_init(void) return 0; } -void ap_debug_exit(void) -{ - debug_unregister(ap_dbf_info); -} - /** * ap_module_init(): The module initialization code. * * Initializes the module. */ -int __init ap_module_init(void) +static int __init ap_module_init(void) { int max_domain_id; int rc, i; @@ -1274,8 +1249,6 @@ int __init ap_module_init(void) ap_airq_flag = (rc == 0); } - register_reset_call(&ap_reset_call); - /* Create /sys/bus/ap. */ rc = bus_register(&ap_bus_type); if (rc) @@ -1331,7 +1304,6 @@ out_bus: bus_remove_file(&ap_bus_type, ap_bus_attrs[i]); bus_unregister(&ap_bus_type); out: - unregister_reset_call(&ap_reset_call); if (ap_using_interrupts()) unregister_adapter_interrupt(&ap_airq); kfree(ap_configuration); diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h index e0827eaa42f1..02184cf35834 100644 --- a/drivers/s390/crypto/ap_bus.h +++ b/drivers/s390/crypto/ap_bus.h @@ -17,7 +17,7 @@ #include <linux/types.h> #include <asm/ap.h> -#define AP_DEVICES 64 /* Number of AP devices. */ +#define AP_DEVICES 256 /* Number of AP devices. */ #define AP_DOMAINS 256 /* Number of AP domains. */ #define AP_RESET_TIMEOUT (HZ*0.7) /* Time in ticks for reset timeouts. */ #define AP_CONFIG_TIME 30 /* Time in seconds between AP bus rescans. */ @@ -240,7 +240,4 @@ void ap_queue_resume(struct ap_device *ap_dev); struct ap_card *ap_card_create(int id, int queue_depth, int raw_device_type, int comp_device_type, unsigned int functions); -int ap_module_init(void); -void ap_module_exit(void); - #endif /* _AP_BUS_H_ */ diff --git a/drivers/s390/crypto/ap_debug.h b/drivers/s390/crypto/ap_debug.h index 6a9d77c75ec3..dc675eb5aef6 100644 --- a/drivers/s390/crypto/ap_debug.h +++ b/drivers/s390/crypto/ap_debug.h @@ -23,7 +23,4 @@ extern debug_info_t *ap_dbf_info; -int ap_debug_init(void); -void ap_debug_exit(void); - #endif /* AP_DEBUG_H */ diff --git a/drivers/s390/crypto/pkey_api.c b/drivers/s390/crypto/pkey_api.c index e7c2e4f9529a..ed80d00cdb6f 100644 --- a/drivers/s390/crypto/pkey_api.c +++ b/drivers/s390/crypto/pkey_api.c @@ -889,7 +889,7 @@ int pkey_findcard(const struct pkey_seckey *seckey, u16 *pcardnr, u16 *pdomain, int verify) { struct secaeskeytoken *t = (struct secaeskeytoken *) seckey; - struct zcrypt_device_matrix *device_matrix; + struct zcrypt_device_status_ext *device_status; u16 card, dom; u64 mkvp[2]; int i, rc, oi = -1; @@ -899,18 +899,19 @@ int pkey_findcard(const struct pkey_seckey *seckey, return -EINVAL; /* fetch status of all crypto cards */ - device_matrix = kmalloc(sizeof(struct zcrypt_device_matrix), + device_status = kmalloc(MAX_ZDEV_ENTRIES_EXT + * sizeof(struct zcrypt_device_status_ext), GFP_KERNEL); - if (!device_matrix) + if (!device_status) return -ENOMEM; - zcrypt_device_status_mask(device_matrix); + zcrypt_device_status_mask_ext(device_status); /* walk through all crypto cards */ - for (i = 0; i < MAX_ZDEV_ENTRIES; i++) { - card = AP_QID_CARD(device_matrix->device[i].qid); - dom = AP_QID_QUEUE(device_matrix->device[i].qid); - if (device_matrix->device[i].online && - device_matrix->device[i].functions & 0x04) { + for (i = 0; i < MAX_ZDEV_ENTRIES_EXT; i++) { + card = AP_QID_CARD(device_status[i].qid); + dom = AP_QID_QUEUE(device_status[i].qid); + if (device_status[i].online && + device_status[i].functions & 0x04) { /* an enabled CCA Coprocessor card */ /* try cached mkvp */ if (mkvp_cache_fetch(card, dom, mkvp) == 0 && @@ -930,14 +931,14 @@ int pkey_findcard(const struct pkey_seckey *seckey, mkvp_cache_scrub(card, dom); } } - if (i >= MAX_ZDEV_ENTRIES) { + if (i >= MAX_ZDEV_ENTRIES_EXT) { /* nothing found, so this time without cache */ - for (i = 0; i < MAX_ZDEV_ENTRIES; i++) { - if (!(device_matrix->device[i].online && - device_matrix->device[i].functions & 0x04)) + for (i = 0; i < MAX_ZDEV_ENTRIES_EXT; i++) { + if (!(device_status[i].online && + device_status[i].functions & 0x04)) continue; - card = AP_QID_CARD(device_matrix->device[i].qid); - dom = AP_QID_QUEUE(device_matrix->device[i].qid); + card = AP_QID_CARD(device_status[i].qid); + dom = AP_QID_QUEUE(device_status[i].qid); /* fresh fetch mkvp from adapter */ if (fetch_mkvp(card, dom, mkvp) == 0) { mkvp_cache_update(card, dom, mkvp); @@ -947,13 +948,13 @@ int pkey_findcard(const struct pkey_seckey *seckey, oi = i; } } - if (i >= MAX_ZDEV_ENTRIES && oi >= 0) { + if (i >= MAX_ZDEV_ENTRIES_EXT && oi >= 0) { /* old mkvp matched, use this card then */ - card = AP_QID_CARD(device_matrix->device[oi].qid); - dom = AP_QID_QUEUE(device_matrix->device[oi].qid); + card = AP_QID_CARD(device_status[oi].qid); + dom = AP_QID_QUEUE(device_status[oi].qid); } } - if (i < MAX_ZDEV_ENTRIES || oi >= 0) { + if (i < MAX_ZDEV_ENTRIES_EXT || oi >= 0) { if (pcardnr) *pcardnr = card; if (pdomain) @@ -962,7 +963,7 @@ int pkey_findcard(const struct pkey_seckey *seckey, } else rc = -ENODEV; - kfree(device_matrix); + kfree(device_status); return rc; } EXPORT_SYMBOL(pkey_findcard); diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index ce15f101ee28..5efd84862ccb 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c @@ -18,8 +18,6 @@ #include <linux/interrupt.h> #include <linux/miscdevice.h> #include <linux/fs.h> -#include <linux/proc_fs.h> -#include <linux/seq_file.h> #include <linux/compat.h> #include <linux/slab.h> #include <linux/atomic.h> @@ -607,19 +605,24 @@ out: return rc; } -void zcrypt_device_status_mask(struct zcrypt_device_matrix *matrix) +static void zcrypt_device_status_mask(struct zcrypt_device_status *devstatus) { struct zcrypt_card *zc; struct zcrypt_queue *zq; struct zcrypt_device_status *stat; + int card, queue; + + memset(devstatus, 0, MAX_ZDEV_ENTRIES + * sizeof(struct zcrypt_device_status)); - memset(matrix, 0, sizeof(*matrix)); spin_lock(&zcrypt_list_lock); for_each_zcrypt_card(zc) { for_each_zcrypt_queue(zq, zc) { - stat = matrix->device; - stat += AP_QID_CARD(zq->queue->qid) * MAX_ZDEV_DOMAINS; - stat += AP_QID_QUEUE(zq->queue->qid); + card = AP_QID_CARD(zq->queue->qid); + if (card >= MAX_ZDEV_CARDIDS) + continue; + queue = AP_QID_QUEUE(zq->queue->qid); + stat = &devstatus[card * AP_DOMAINS + queue]; stat->hwtype = zc->card->ap_dev.device_type; stat->functions = zc->card->functions >> 26; stat->qid = zq->queue->qid; @@ -628,40 +631,70 @@ void zcrypt_device_status_mask(struct zcrypt_device_matrix *matrix) } spin_unlock(&zcrypt_list_lock); } -EXPORT_SYMBOL(zcrypt_device_status_mask); -static void zcrypt_status_mask(char status[AP_DEVICES]) +void zcrypt_device_status_mask_ext(struct zcrypt_device_status_ext *devstatus) { struct zcrypt_card *zc; struct zcrypt_queue *zq; + struct zcrypt_device_status_ext *stat; + int card, queue; + + memset(devstatus, 0, MAX_ZDEV_ENTRIES_EXT + * sizeof(struct zcrypt_device_status_ext)); - memset(status, 0, sizeof(char) * AP_DEVICES); spin_lock(&zcrypt_list_lock); for_each_zcrypt_card(zc) { for_each_zcrypt_queue(zq, zc) { - if (AP_QID_QUEUE(zq->queue->qid) != ap_domain_index) + card = AP_QID_CARD(zq->queue->qid); + queue = AP_QID_QUEUE(zq->queue->qid); + stat = &devstatus[card * AP_DOMAINS + queue]; + stat->hwtype = zc->card->ap_dev.device_type; + stat->functions = zc->card->functions >> 26; + stat->qid = zq->queue->qid; + stat->online = zq->online ? 0x01 : 0x00; + } + } + spin_unlock(&zcrypt_list_lock); +} +EXPORT_SYMBOL(zcrypt_device_status_mask_ext); + +static void zcrypt_status_mask(char status[], size_t max_adapters) +{ + struct zcrypt_card *zc; + struct zcrypt_queue *zq; + int card; + + memset(status, 0, max_adapters); + spin_lock(&zcrypt_list_lock); + for_each_zcrypt_card(zc) { + for_each_zcrypt_queue(zq, zc) { + card = AP_QID_CARD(zq->queue->qid); + if (AP_QID_QUEUE(zq->queue->qid) != ap_domain_index + || card >= max_adapters) continue; - status[AP_QID_CARD(zq->queue->qid)] = - zc->online ? zc->user_space_type : 0x0d; + status[card] = zc->online ? zc->user_space_type : 0x0d; } } spin_unlock(&zcrypt_list_lock); } -static void zcrypt_qdepth_mask(char qdepth[AP_DEVICES]) +static void zcrypt_qdepth_mask(char qdepth[], size_t max_adapters) { struct zcrypt_card *zc; struct zcrypt_queue *zq; + int card; - memset(qdepth, 0, sizeof(char) * AP_DEVICES); + memset(qdepth, 0, max_adapters); spin_lock(&zcrypt_list_lock); local_bh_disable(); for_each_zcrypt_card(zc) { for_each_zcrypt_queue(zq, zc) { - if (AP_QID_QUEUE(zq->queue->qid) != ap_domain_index) + card = AP_QID_CARD(zq->queue->qid); + if (AP_QID_QUEUE(zq->queue->qid) != ap_domain_index + || card >= max_adapters) continue; spin_lock(&zq->queue->lock); - qdepth[AP_QID_CARD(zq->queue->qid)] = + qdepth[card] = zq->queue->pendingq_count + zq->queue->requestq_count; spin_unlock(&zq->queue->lock); @@ -671,21 +704,23 @@ static void zcrypt_qdepth_mask(char qdepth[AP_DEVICES]) spin_unlock(&zcrypt_list_lock); } -static void zcrypt_perdev_reqcnt(int reqcnt[AP_DEVICES]) +static void zcrypt_perdev_reqcnt(int reqcnt[], size_t max_adapters) { struct zcrypt_card *zc; struct zcrypt_queue *zq; + int card; - memset(reqcnt, 0, sizeof(int) * AP_DEVICES); + memset(reqcnt, 0, sizeof(int) * max_adapters); spin_lock(&zcrypt_list_lock); local_bh_disable(); for_each_zcrypt_card(zc) { for_each_zcrypt_queue(zq, zc) { - if (AP_QID_QUEUE(zq->queue->qid) != ap_domain_index) + card = AP_QID_CARD(zq->queue->qid); + if (AP_QID_QUEUE(zq->queue->qid) != ap_domain_index + || card >= max_adapters) continue; spin_lock(&zq->queue->lock); - reqcnt[AP_QID_CARD(zq->queue->qid)] = - zq->queue->total_request_count; + reqcnt[card] = zq->queue->total_request_count; spin_unlock(&zq->queue->lock); } } @@ -739,60 +774,10 @@ static int zcrypt_requestq_count(void) return requestq_count; } -static int zcrypt_count_type(int type) -{ - struct zcrypt_card *zc; - struct zcrypt_queue *zq; - int device_count; - - device_count = 0; - spin_lock(&zcrypt_list_lock); - for_each_zcrypt_card(zc) { - if (zc->card->id != type) - continue; - for_each_zcrypt_queue(zq, zc) { - if (AP_QID_QUEUE(zq->queue->qid) != ap_domain_index) - continue; - device_count++; - } - } - spin_unlock(&zcrypt_list_lock); - return device_count; -} - -/** - * zcrypt_ica_status(): Old, depracted combi status call. - * - * Old, deprecated combi status call. - */ -static long zcrypt_ica_status(struct file *filp, unsigned long arg) -{ - struct ica_z90_status *pstat; - int ret; - - pstat = kzalloc(sizeof(*pstat), GFP_KERNEL); - if (!pstat) - return -ENOMEM; - pstat->totalcount = zcrypt_device_count; - pstat->leedslitecount = zcrypt_count_type(ZCRYPT_PCICA); - pstat->leeds2count = zcrypt_count_type(ZCRYPT_PCICC); - pstat->requestqWaitCount = zcrypt_requestq_count(); - pstat->pendingqWaitCount = zcrypt_pendingq_count(); - pstat->totalOpenCount = atomic_read(&zcrypt_open_count); - pstat->cryptoDomain = ap_domain_index; - zcrypt_status_mask(pstat->status); - zcrypt_qdepth_mask(pstat->qdepth); - ret = 0; - if (copy_to_user((void __user *) arg, pstat, sizeof(*pstat))) - ret = -EFAULT; - kfree(pstat); - return ret; -} - static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { - int rc; + int rc = 0; switch (cmd) { case ICARSAMODEXPO: { @@ -871,48 +856,48 @@ static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd, return -EFAULT; return rc; } - case ZDEVICESTATUS: { - struct zcrypt_device_matrix *device_status; + case ZCRYPT_DEVICE_STATUS: { + struct zcrypt_device_status_ext *device_status; + size_t total_size = MAX_ZDEV_ENTRIES_EXT + * sizeof(struct zcrypt_device_status_ext); - device_status = kzalloc(sizeof(struct zcrypt_device_matrix), - GFP_KERNEL); + device_status = kzalloc(total_size, GFP_KERNEL); if (!device_status) return -ENOMEM; - - zcrypt_device_status_mask(device_status); - + zcrypt_device_status_mask_ext(device_status); if (copy_to_user((char __user *) arg, device_status, - sizeof(struct zcrypt_device_matrix))) { - kfree(device_status); - return -EFAULT; - } - + total_size)) + rc = -EFAULT; kfree(device_status); - return 0; + return rc; } - case Z90STAT_STATUS_MASK: { + case ZCRYPT_STATUS_MASK: { char status[AP_DEVICES]; - zcrypt_status_mask(status); - if (copy_to_user((char __user *) arg, status, - sizeof(char) * AP_DEVICES)) + + zcrypt_status_mask(status, AP_DEVICES); + if (copy_to_user((char __user *) arg, status, sizeof(status))) return -EFAULT; return 0; } - case Z90STAT_QDEPTH_MASK: { + case ZCRYPT_QDEPTH_MASK: { char qdepth[AP_DEVICES]; - zcrypt_qdepth_mask(qdepth); - if (copy_to_user((char __user *) arg, qdepth, - sizeof(char) * AP_DEVICES)) + + zcrypt_qdepth_mask(qdepth, AP_DEVICES); + if (copy_to_user((char __user *) arg, qdepth, sizeof(qdepth))) return -EFAULT; return 0; } - case Z90STAT_PERDEV_REQCNT: { - int reqcnt[AP_DEVICES]; - zcrypt_perdev_reqcnt(reqcnt); - if (copy_to_user((int __user *) arg, reqcnt, - sizeof(int) * AP_DEVICES)) - return -EFAULT; - return 0; + case ZCRYPT_PERDEV_REQCNT: { + int *reqcnt; + + reqcnt = kcalloc(AP_DEVICES, sizeof(int), GFP_KERNEL); + if (!reqcnt) + return -ENOMEM; + zcrypt_perdev_reqcnt(reqcnt, AP_DEVICES); + if (copy_to_user((int __user *) arg, reqcnt, sizeof(reqcnt))) + rc = -EFAULT; + kfree(reqcnt); + return rc; } case Z90STAT_REQUESTQ_COUNT: return put_user(zcrypt_requestq_count(), (int __user *) arg); @@ -924,38 +909,54 @@ static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd, case Z90STAT_DOMAIN_INDEX: return put_user(ap_domain_index, (int __user *) arg); /* - * Deprecated ioctls. Don't add another device count ioctl, - * you can count them yourself in the user space with the - * output of the Z90STAT_STATUS_MASK ioctl. + * Deprecated ioctls */ - case ICAZ90STATUS: - return zcrypt_ica_status(filp, arg); - case Z90STAT_TOTALCOUNT: - return put_user(zcrypt_device_count, (int __user *) arg); - case Z90STAT_PCICACOUNT: - return put_user(zcrypt_count_type(ZCRYPT_PCICA), - (int __user *) arg); - case Z90STAT_PCICCCOUNT: - return put_user(zcrypt_count_type(ZCRYPT_PCICC), - (int __user *) arg); - case Z90STAT_PCIXCCMCL2COUNT: - return put_user(zcrypt_count_type(ZCRYPT_PCIXCC_MCL2), - (int __user *) arg); - case Z90STAT_PCIXCCMCL3COUNT: - return put_user(zcrypt_count_type(ZCRYPT_PCIXCC_MCL3), - (int __user *) arg); - case Z90STAT_PCIXCCCOUNT: - return put_user(zcrypt_count_type(ZCRYPT_PCIXCC_MCL2) + - zcrypt_count_type(ZCRYPT_PCIXCC_MCL3), - (int __user *) arg); - case Z90STAT_CEX2CCOUNT: - return put_user(zcrypt_count_type(ZCRYPT_CEX2C), - (int __user *) arg); - case Z90STAT_CEX2ACOUNT: - return put_user(zcrypt_count_type(ZCRYPT_CEX2A), - (int __user *) arg); + case ZDEVICESTATUS: { + /* the old ioctl supports only 64 adapters */ + struct zcrypt_device_status *device_status; + size_t total_size = MAX_ZDEV_ENTRIES + * sizeof(struct zcrypt_device_status); + + device_status = kzalloc(total_size, GFP_KERNEL); + if (!device_status) + return -ENOMEM; + zcrypt_device_status_mask(device_status); + if (copy_to_user((char __user *) arg, device_status, + total_size)) + rc = -EFAULT; + kfree(device_status); + return rc; + } + case Z90STAT_STATUS_MASK: { + /* the old ioctl supports only 64 adapters */ + char status[MAX_ZDEV_CARDIDS]; + + zcrypt_status_mask(status, MAX_ZDEV_CARDIDS); + if (copy_to_user((char __user *) arg, status, sizeof(status))) + return -EFAULT; + return 0; + } + case Z90STAT_QDEPTH_MASK: { + /* the old ioctl supports only 64 adapters */ + char qdepth[MAX_ZDEV_CARDIDS]; + + zcrypt_qdepth_mask(qdepth, MAX_ZDEV_CARDIDS); + if (copy_to_user((char __user *) arg, qdepth, sizeof(qdepth))) + return -EFAULT; + return 0; + } + case Z90STAT_PERDEV_REQCNT: { + /* the old ioctl supports only 64 adapters */ + int reqcnt[MAX_ZDEV_CARDIDS]; + + zcrypt_perdev_reqcnt(reqcnt, MAX_ZDEV_CARDIDS); + if (copy_to_user((int __user *) arg, reqcnt, sizeof(reqcnt))) + return -EFAULT; + return 0; + } + /* unknown ioctl number */ default: - /* unknown ioctl number */ + ZCRYPT_DBF(DBF_DEBUG, "unknown ioctl 0x%08x\n", cmd); return -ENOIOCTLCMD; } } @@ -1152,201 +1153,6 @@ static struct miscdevice zcrypt_misc_device = { .fops = &zcrypt_fops, }; -/* - * Deprecated /proc entry support. - */ -static struct proc_dir_entry *zcrypt_entry; - -static void sprintcl(struct seq_file *m, unsigned char *addr, unsigned int len) -{ - int i; - - for (i = 0; i < len; i++) - seq_printf(m, "%01x", (unsigned int) addr[i]); - seq_putc(m, ' '); -} - -static void sprintrw(struct seq_file *m, unsigned char *addr, unsigned int len) -{ - int inl, c, cx; - - seq_printf(m, " "); - inl = 0; - for (c = 0; c < (len / 16); c++) { - sprintcl(m, addr+inl, 16); - inl += 16; - } - cx = len%16; - if (cx) { - sprintcl(m, addr+inl, cx); - inl += cx; - } - seq_putc(m, '\n'); -} - -static void sprinthx(unsigned char *title, struct seq_file *m, - unsigned char *addr, unsigned int len) -{ - int inl, r, rx; - - seq_printf(m, "\n%s\n", title); - inl = 0; - for (r = 0; r < (len / 64); r++) { - sprintrw(m, addr+inl, 64); - inl += 64; - } - rx = len % 64; - if (rx) { - sprintrw(m, addr+inl, rx); - inl += rx; - } - seq_putc(m, '\n'); -} - -static void sprinthx4(unsigned char *title, struct seq_file *m, - unsigned int *array, unsigned int len) -{ - seq_printf(m, "\n%s\n", title); - seq_hex_dump(m, " ", DUMP_PREFIX_NONE, 32, 4, array, len, false); - seq_putc(m, '\n'); -} - -static int zcrypt_proc_show(struct seq_file *m, void *v) -{ - char workarea[sizeof(int) * AP_DEVICES]; - - seq_printf(m, "\nzcrypt version: %d.%d.%d\n", - ZCRYPT_VERSION, ZCRYPT_RELEASE, ZCRYPT_VARIANT); - seq_printf(m, "Cryptographic domain: %d\n", ap_domain_index); - seq_printf(m, "Total device count: %d\n", zcrypt_device_count); - seq_printf(m, "PCICA count: %d\n", zcrypt_count_type(ZCRYPT_PCICA)); - seq_printf(m, "PCICC count: %d\n", zcrypt_count_type(ZCRYPT_PCICC)); - seq_printf(m, "PCIXCC MCL2 count: %d\n", - zcrypt_count_type(ZCRYPT_PCIXCC_MCL2)); - seq_printf(m, "PCIXCC MCL3 count: %d\n", - zcrypt_count_type(ZCRYPT_PCIXCC_MCL3)); - seq_printf(m, "CEX2C count: %d\n", zcrypt_count_type(ZCRYPT_CEX2C)); - seq_printf(m, "CEX2A count: %d\n", zcrypt_count_type(ZCRYPT_CEX2A)); - seq_printf(m, "CEX3C count: %d\n", zcrypt_count_type(ZCRYPT_CEX3C)); - seq_printf(m, "CEX3A count: %d\n", zcrypt_count_type(ZCRYPT_CEX3A)); - seq_printf(m, "requestq count: %d\n", zcrypt_requestq_count()); - seq_printf(m, "pendingq count: %d\n", zcrypt_pendingq_count()); - seq_printf(m, "Total open handles: %d\n\n", - atomic_read(&zcrypt_open_count)); - zcrypt_status_mask(workarea); - sprinthx("Online devices: 1=PCICA 2=PCICC 3=PCIXCC(MCL2) " - "4=PCIXCC(MCL3) 5=CEX2C 6=CEX2A 7=CEX3C 8=CEX3A", - m, workarea, AP_DEVICES); - zcrypt_qdepth_mask(workarea); - sprinthx("Waiting work element counts", m, workarea, AP_DEVICES); - zcrypt_perdev_reqcnt((int *) workarea); - sprinthx4("Per-device successfully completed request counts", - m, (unsigned int *) workarea, AP_DEVICES); - return 0; -} - -static int zcrypt_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, zcrypt_proc_show, NULL); -} - -static void zcrypt_disable_card(int index) -{ - struct zcrypt_card *zc; - struct zcrypt_queue *zq; - - spin_lock(&zcrypt_list_lock); - for_each_zcrypt_card(zc) { - for_each_zcrypt_queue(zq, zc) { - if (AP_QID_QUEUE(zq->queue->qid) != ap_domain_index) - continue; - zq->online = 0; - ap_flush_queue(zq->queue); - } - } - spin_unlock(&zcrypt_list_lock); -} - -static void zcrypt_enable_card(int index) -{ - struct zcrypt_card *zc; - struct zcrypt_queue *zq; - - spin_lock(&zcrypt_list_lock); - for_each_zcrypt_card(zc) { - for_each_zcrypt_queue(zq, zc) { - if (AP_QID_QUEUE(zq->queue->qid) != ap_domain_index) - continue; - zq->online = 1; - ap_flush_queue(zq->queue); - } - } - spin_unlock(&zcrypt_list_lock); -} - -static ssize_t zcrypt_proc_write(struct file *file, const char __user *buffer, - size_t count, loff_t *pos) -{ - unsigned char *lbuf, *ptr; - size_t local_count; - int j; - - if (count <= 0) - return 0; - -#define LBUFSIZE 1200UL - lbuf = kmalloc(LBUFSIZE, GFP_KERNEL); - if (!lbuf) - return 0; - - local_count = min(LBUFSIZE - 1, count); - if (copy_from_user(lbuf, buffer, local_count) != 0) { - kfree(lbuf); - return -EFAULT; - } - lbuf[local_count] = '\0'; - - ptr = strstr(lbuf, "Online devices"); - if (!ptr) - goto out; - ptr = strstr(ptr, "\n"); - if (!ptr) - goto out; - ptr++; - - if (strstr(ptr, "Waiting work element counts") == NULL) - goto out; - - for (j = 0; j < 64 && *ptr; ptr++) { - /* - * '0' for no device, '1' for PCICA, '2' for PCICC, - * '3' for PCIXCC_MCL2, '4' for PCIXCC_MCL3, - * '5' for CEX2C and '6' for CEX2A' - * '7' for CEX3C and '8' for CEX3A - */ - if (*ptr >= '0' && *ptr <= '8') - j++; - else if (*ptr == 'd' || *ptr == 'D') - zcrypt_disable_card(j++); - else if (*ptr == 'e' || *ptr == 'E') - zcrypt_enable_card(j++); - else if (*ptr != ' ' && *ptr != '\t') - break; - } -out: - kfree(lbuf); - return count; -} - -static const struct file_operations zcrypt_proc_fops = { - .owner = THIS_MODULE, - .open = zcrypt_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = zcrypt_proc_write, -}; - static int zcrypt_rng_device_count; static u32 *zcrypt_rng_buffer; static int zcrypt_rng_buffer_index; @@ -1448,27 +1254,15 @@ int __init zcrypt_api_init(void) if (rc) goto out; - atomic_set(&zcrypt_rescan_req, 0); - /* Register the request sprayer. */ rc = misc_register(&zcrypt_misc_device); if (rc < 0) goto out; - /* Set up the proc file system */ - zcrypt_entry = proc_create("driver/z90crypt", 0644, NULL, - &zcrypt_proc_fops); - if (!zcrypt_entry) { - rc = -ENOMEM; - goto out_misc; - } - zcrypt_msgtype6_init(); zcrypt_msgtype50_init(); return 0; -out_misc: - misc_deregister(&zcrypt_misc_device); out: return rc; } @@ -1480,7 +1274,6 @@ out: */ void __exit zcrypt_api_exit(void) { - remove_proc_entry("driver/z90crypt", NULL); misc_deregister(&zcrypt_misc_device); zcrypt_msgtype6_exit(); zcrypt_msgtype50_exit(); diff --git a/drivers/s390/crypto/zcrypt_api.h b/drivers/s390/crypto/zcrypt_api.h index 9fff8912f6e3..f149a8fee60d 100644 --- a/drivers/s390/crypto/zcrypt_api.h +++ b/drivers/s390/crypto/zcrypt_api.h @@ -21,30 +21,6 @@ #include <asm/zcrypt.h> #include "ap_bus.h" -/* deprecated status calls */ -#define ICAZ90STATUS _IOR(ZCRYPT_IOCTL_MAGIC, 0x10, struct ica_z90_status) -#define Z90STAT_PCIXCCCOUNT _IOR(ZCRYPT_IOCTL_MAGIC, 0x43, int) - -/** - * This structure is deprecated and the corresponding ioctl() has been - * replaced with individual ioctl()s for each piece of data! - */ -struct ica_z90_status { - int totalcount; - int leedslitecount; // PCICA - int leeds2count; // PCICC - // int PCIXCCCount; is not in struct for backward compatibility - int requestqWaitCount; - int pendingqWaitCount; - int totalOpenCount; - int cryptoDomain; - // status: 0=not there, 1=PCICA, 2=PCICC, 3=PCIXCC_MCL2, 4=PCIXCC_MCL3, - // 5=CEX2C - unsigned char status[64]; - // qdepth: # work elements waiting for each device - unsigned char qdepth[64]; -}; - /** * device type for an actual device is either PCICA, PCICC, PCIXCC_MCL2, * PCIXCC_MCL3, CEX2C, or CEX2A @@ -179,6 +155,6 @@ struct zcrypt_ops *zcrypt_msgtype(unsigned char *, int); int zcrypt_api_init(void); void zcrypt_api_exit(void); long zcrypt_send_cprb(struct ica_xcRB *xcRB); -void zcrypt_device_status_mask(struct zcrypt_device_matrix *devstatus); +void zcrypt_device_status_mask_ext(struct zcrypt_device_status_ext *devstatus); #endif /* _ZCRYPT_API_H_ */ diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 4326715dc13e..78b98b3e7efa 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -557,7 +557,6 @@ enum qeth_prot_versions { enum qeth_cmd_buffer_state { BUF_STATE_FREE, BUF_STATE_LOCKED, - BUF_STATE_PROCESSED, }; enum qeth_cq { @@ -601,7 +600,6 @@ struct qeth_channel { struct qeth_cmd_buffer iob[QETH_CMD_BUFFER_NO]; atomic_t irq_pending; int io_buf_no; - int buf_no; }; /** diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 04fefa5bb08d..dffd820731f2 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -706,7 +706,6 @@ void qeth_clear_ipacmd_list(struct qeth_card *card) qeth_put_reply(reply); } spin_unlock_irqrestore(&card->lock, flags); - atomic_set(&card->write.irq_pending, 0); } EXPORT_SYMBOL_GPL(qeth_clear_ipacmd_list); @@ -818,7 +817,6 @@ void qeth_clear_cmd_buffers(struct qeth_channel *channel) for (cnt = 0; cnt < QETH_CMD_BUFFER_NO; cnt++) qeth_release_buffer(channel, &channel->iob[cnt]); - channel->buf_no = 0; channel->io_buf_no = 0; } EXPORT_SYMBOL_GPL(qeth_clear_cmd_buffers); @@ -924,7 +922,6 @@ static int qeth_setup_channel(struct qeth_channel *channel) kfree(channel->iob[cnt].data); return -ENOMEM; } - channel->buf_no = 0; channel->io_buf_no = 0; atomic_set(&channel->irq_pending, 0); spin_lock_init(&channel->iob_lock); @@ -1100,16 +1097,9 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm, { int rc; int cstat, dstat; - struct qeth_cmd_buffer *buffer; + struct qeth_cmd_buffer *iob = NULL; struct qeth_channel *channel; struct qeth_card *card; - struct qeth_cmd_buffer *iob; - __u8 index; - - if (__qeth_check_irb_error(cdev, intparm, irb)) - return; - cstat = irb->scsw.cmd.cstat; - dstat = irb->scsw.cmd.dstat; card = CARD_FROM_CDEV(cdev); if (!card) @@ -1127,6 +1117,19 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm, channel = &card->data; QETH_CARD_TEXT(card, 5, "data"); } + + if (qeth_intparm_is_iob(intparm)) + iob = (struct qeth_cmd_buffer *) __va((addr_t)intparm); + + if (__qeth_check_irb_error(cdev, intparm, irb)) { + /* IO was terminated, free its resources. */ + if (iob) + qeth_release_buffer(iob->channel, iob); + atomic_set(&channel->irq_pending, 0); + wake_up(&card->wait_q); + return; + } + atomic_set(&channel->irq_pending, 0); if (irb->scsw.cmd.fctl & (SCSW_FCTL_CLEAR_FUNC)) @@ -1150,6 +1153,10 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm, /* we don't have to handle this further */ intparm = 0; } + + cstat = irb->scsw.cmd.cstat; + dstat = irb->scsw.cmd.dstat; + if ((dstat & DEV_STAT_UNIT_EXCEP) || (dstat & DEV_STAT_UNIT_CHECK) || (cstat)) { @@ -1182,25 +1189,15 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm, channel->state = CH_STATE_RCD_DONE; goto out; } - if (intparm) { - buffer = (struct qeth_cmd_buffer *) __va((addr_t)intparm); - buffer->state = BUF_STATE_PROCESSED; - } if (channel == &card->data) return; if (channel == &card->read && channel->state == CH_STATE_UP) __qeth_issue_next_read(card); - iob = channel->iob; - index = channel->buf_no; - while (iob[index].state == BUF_STATE_PROCESSED) { - if (iob[index].callback != NULL) - iob[index].callback(channel, iob + index); + if (iob && iob->callback) + iob->callback(iob->channel, iob); - index = (index + 1) % QETH_CMD_BUFFER_NO; - } - channel->buf_no = index; out: wake_up(&card->wait_q); return; @@ -1870,8 +1867,8 @@ static int qeth_idx_activate_get_answer(struct qeth_channel *channel, atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0); QETH_DBF_TEXT(SETUP, 6, "noirqpnd"); spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags); - rc = ccw_device_start(channel->ccwdev, - &channel->ccw, (addr_t) iob, 0, 0); + rc = ccw_device_start_timeout(channel->ccwdev, &channel->ccw, + (addr_t) iob, 0, 0, QETH_TIMEOUT); spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags); if (rc) { @@ -1888,7 +1885,6 @@ static int qeth_idx_activate_get_answer(struct qeth_channel *channel, if (channel->state != CH_STATE_UP) { rc = -ETIME; QETH_DBF_TEXT_(SETUP, 2, "3err%d", rc); - qeth_clear_cmd_buffers(channel); } else rc = 0; return rc; @@ -1942,8 +1938,8 @@ static int qeth_idx_activate_channel(struct qeth_channel *channel, atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0); QETH_DBF_TEXT(SETUP, 6, "noirqpnd"); spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags); - rc = ccw_device_start(channel->ccwdev, - &channel->ccw, (addr_t) iob, 0, 0); + rc = ccw_device_start_timeout(channel->ccwdev, &channel->ccw, + (addr_t) iob, 0, 0, QETH_TIMEOUT); spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags); if (rc) { @@ -1964,7 +1960,6 @@ static int qeth_idx_activate_channel(struct qeth_channel *channel, QETH_DBF_MESSAGE(2, "%s IDX activate timed out\n", dev_name(&channel->ccwdev->dev)); QETH_DBF_TEXT_(SETUP, 2, "2err%d", -ETIME); - qeth_clear_cmd_buffers(channel); return -ETIME; } return qeth_idx_activate_get_answer(channel, idx_reply_cb); @@ -2166,8 +2161,8 @@ int qeth_send_control_data(struct qeth_card *card, int len, QETH_CARD_TEXT(card, 6, "noirqpnd"); spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags); - rc = ccw_device_start(card->write.ccwdev, &card->write.ccw, - (addr_t) iob, 0, 0); + rc = ccw_device_start_timeout(CARD_WDEV(card), &card->write.ccw, + (addr_t) iob, 0, 0, event_timeout); spin_unlock_irqrestore(get_ccwdev_lock(card->write.ccwdev), flags); if (rc) { QETH_DBF_MESSAGE(2, "%s qeth_send_control_data: " @@ -2199,8 +2194,6 @@ int qeth_send_control_data(struct qeth_card *card, int len, } } - if (reply->rc == -EIO) - goto error; rc = reply->rc; qeth_put_reply(reply); return rc; @@ -2211,10 +2204,6 @@ time_err: list_del_init(&reply->list); spin_unlock_irqrestore(&reply->card->lock, flags); atomic_inc(&reply->received); -error: - atomic_set(&card->write.irq_pending, 0); - qeth_release_buffer(iob->channel, iob); - card->write.buf_no = (card->write.buf_no + 1) % QETH_CMD_BUFFER_NO; rc = reply->rc; qeth_put_reply(reply); return rc; @@ -3033,28 +3022,23 @@ static int qeth_send_startlan(struct qeth_card *card) return rc; } -static int qeth_default_setadapterparms_cb(struct qeth_card *card, - struct qeth_reply *reply, unsigned long data) +static int qeth_setadpparms_inspect_rc(struct qeth_ipa_cmd *cmd) { - struct qeth_ipa_cmd *cmd; - - QETH_CARD_TEXT(card, 4, "defadpcb"); - - cmd = (struct qeth_ipa_cmd *) data; - if (cmd->hdr.return_code == 0) + if (!cmd->hdr.return_code) cmd->hdr.return_code = cmd->data.setadapterparms.hdr.return_code; - return 0; + return cmd->hdr.return_code; } static int qeth_query_setadapterparms_cb(struct qeth_card *card, struct qeth_reply *reply, unsigned long data) { - struct qeth_ipa_cmd *cmd; + struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data; QETH_CARD_TEXT(card, 3, "quyadpcb"); + if (qeth_setadpparms_inspect_rc(cmd)) + return 0; - cmd = (struct qeth_ipa_cmd *) data; if (cmd->data.setadapterparms.data.query_cmds_supp.lan_type & 0x7f) { card->info.link_type = cmd->data.setadapterparms.data.query_cmds_supp.lan_type; @@ -3062,7 +3046,7 @@ static int qeth_query_setadapterparms_cb(struct qeth_card *card, } card->options.adp.supported_funcs = cmd->data.setadapterparms.data.query_cmds_supp.supported_cmds; - return qeth_default_setadapterparms_cb(card, reply, (unsigned long)cmd); + return 0; } static struct qeth_cmd_buffer *qeth_get_adapter_cmd(struct qeth_card *card, @@ -3154,22 +3138,20 @@ EXPORT_SYMBOL_GPL(qeth_query_ipassists); static int qeth_query_switch_attributes_cb(struct qeth_card *card, struct qeth_reply *reply, unsigned long data) { - struct qeth_ipa_cmd *cmd; - struct qeth_switch_info *sw_info; + struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data; struct qeth_query_switch_attributes *attrs; + struct qeth_switch_info *sw_info; QETH_CARD_TEXT(card, 2, "qswiatcb"); - cmd = (struct qeth_ipa_cmd *) data; - sw_info = (struct qeth_switch_info *)reply->param; - if (cmd->data.setadapterparms.hdr.return_code == 0) { - attrs = &cmd->data.setadapterparms.data.query_switch_attributes; - sw_info->capabilities = attrs->capabilities; - sw_info->settings = attrs->settings; - QETH_CARD_TEXT_(card, 2, "%04x%04x", sw_info->capabilities, - sw_info->settings); - } - qeth_default_setadapterparms_cb(card, reply, (unsigned long) cmd); + if (qeth_setadpparms_inspect_rc(cmd)) + return 0; + sw_info = (struct qeth_switch_info *)reply->param; + attrs = &cmd->data.setadapterparms.data.query_switch_attributes; + sw_info->capabilities = attrs->capabilities; + sw_info->settings = attrs->settings; + QETH_CARD_TEXT_(card, 2, "%04x%04x", sw_info->capabilities, + sw_info->settings); return 0; } @@ -4207,16 +4189,13 @@ EXPORT_SYMBOL_GPL(qeth_do_send_packet); static int qeth_setadp_promisc_mode_cb(struct qeth_card *card, struct qeth_reply *reply, unsigned long data) { - struct qeth_ipa_cmd *cmd; + struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data; struct qeth_ipacmd_setadpparms *setparms; QETH_CARD_TEXT(card, 4, "prmadpcb"); - cmd = (struct qeth_ipa_cmd *) data; setparms = &(cmd->data.setadapterparms); - - qeth_default_setadapterparms_cb(card, reply, (unsigned long)cmd); - if (cmd->hdr.return_code) { + if (qeth_setadpparms_inspect_rc(cmd)) { QETH_CARD_TEXT_(card, 4, "prmrc%x", cmd->hdr.return_code); setparms->data.mode = SET_PROMISC_MODE_OFF; } @@ -4286,18 +4265,18 @@ EXPORT_SYMBOL_GPL(qeth_get_stats); static int qeth_setadpparms_change_macaddr_cb(struct qeth_card *card, struct qeth_reply *reply, unsigned long data) { - struct qeth_ipa_cmd *cmd; + struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data; QETH_CARD_TEXT(card, 4, "chgmaccb"); + if (qeth_setadpparms_inspect_rc(cmd)) + return 0; - cmd = (struct qeth_ipa_cmd *) data; if (!card->options.layer2 || !(card->info.mac_bits & QETH_LAYER2_MAC_READ)) { ether_addr_copy(card->dev->dev_addr, cmd->data.setadapterparms.data.change_addr.addr); card->info.mac_bits |= QETH_LAYER2_MAC_READ; } - qeth_default_setadapterparms_cb(card, reply, (unsigned long) cmd); return 0; } @@ -4328,13 +4307,15 @@ EXPORT_SYMBOL_GPL(qeth_setadpparms_change_macaddr); static int qeth_setadpparms_set_access_ctrl_cb(struct qeth_card *card, struct qeth_reply *reply, unsigned long data) { - struct qeth_ipa_cmd *cmd; + struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data; struct qeth_set_access_ctrl *access_ctrl_req; int fallback = *(int *)reply->param; QETH_CARD_TEXT(card, 4, "setaccb"); + if (cmd->hdr.return_code) + return 0; + qeth_setadpparms_inspect_rc(cmd); - cmd = (struct qeth_ipa_cmd *) data; access_ctrl_req = &cmd->data.setadapterparms.data.set_access_ctrl; QETH_DBF_TEXT_(SETUP, 2, "setaccb"); QETH_DBF_TEXT_(SETUP, 2, "%s", card->gdev->dev.kobj.name); @@ -4407,7 +4388,6 @@ static int qeth_setadpparms_set_access_ctrl_cb(struct qeth_card *card, card->options.isolation = card->options.prev_isolation; break; } - qeth_default_setadapterparms_cb(card, reply, (unsigned long) cmd); return 0; } @@ -4695,14 +4675,15 @@ out: static int qeth_setadpparms_query_oat_cb(struct qeth_card *card, struct qeth_reply *reply, unsigned long data) { - struct qeth_ipa_cmd *cmd; + struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *)data; struct qeth_qoat_priv *priv; char *resdata; int resdatalen; QETH_CARD_TEXT(card, 3, "qoatcb"); + if (qeth_setadpparms_inspect_rc(cmd)) + return 0; - cmd = (struct qeth_ipa_cmd *)data; priv = (struct qeth_qoat_priv *)reply->param; resdatalen = cmd->data.setadapterparms.hdr.cmdlength; resdata = (char *)data + 28; @@ -4796,21 +4777,18 @@ out: static int qeth_query_card_info_cb(struct qeth_card *card, struct qeth_reply *reply, unsigned long data) { - struct qeth_ipa_cmd *cmd; + struct carrier_info *carrier_info = (struct carrier_info *)reply->param; + struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *)data; struct qeth_query_card_info *card_info; - struct carrier_info *carrier_info; QETH_CARD_TEXT(card, 2, "qcrdincb"); - carrier_info = (struct carrier_info *)reply->param; - cmd = (struct qeth_ipa_cmd *)data; - card_info = &cmd->data.setadapterparms.data.card_info; - if (cmd->data.setadapterparms.hdr.return_code == 0) { - carrier_info->card_type = card_info->card_type; - carrier_info->port_mode = card_info->port_mode; - carrier_info->port_speed = card_info->port_speed; - } + if (qeth_setadpparms_inspect_rc(cmd)) + return 0; - qeth_default_setadapterparms_cb(card, reply, (unsigned long) cmd); + card_info = &cmd->data.setadapterparms.data.card_info; + carrier_info->card_type = card_info->card_type; + carrier_info->port_mode = card_info->port_mode; + carrier_info->port_speed = card_info->port_speed; return 0; } @@ -4857,7 +4835,7 @@ int qeth_vm_request_mac(struct qeth_card *card) goto out; } - ccw_device_get_id(CARD_DDEV(card), &id); + ccw_device_get_id(CARD_RDEV(card), &id); request->resp_buf_len = sizeof(*response); request->resp_version = DIAG26C_VERSION2; request->op_code = DIAG26C_GET_MAC; @@ -6563,10 +6541,14 @@ static int __init qeth_core_init(void) mutex_init(&qeth_mod_mutex); qeth_wq = create_singlethread_workqueue("qeth_wq"); + if (!qeth_wq) { + rc = -ENOMEM; + goto out_err; + } rc = qeth_register_dbf_views(); if (rc) - goto out_err; + goto dbf_err; qeth_core_root_dev = root_device_register("qeth"); rc = PTR_ERR_OR_ZERO(qeth_core_root_dev); if (rc) @@ -6603,6 +6585,8 @@ slab_err: root_device_unregister(qeth_core_root_dev); register_err: qeth_unregister_dbf_views(); +dbf_err: + destroy_workqueue(qeth_wq); out_err: pr_err("Initializing the qeth device driver failed\n"); return rc; diff --git a/drivers/s390/net/qeth_core_mpc.h b/drivers/s390/net/qeth_core_mpc.h index 619f897b4bb0..f4d1ec0b8f5a 100644 --- a/drivers/s390/net/qeth_core_mpc.h +++ b/drivers/s390/net/qeth_core_mpc.h @@ -35,6 +35,18 @@ extern unsigned char IPA_PDU_HEADER[]; #define QETH_HALT_CHANNEL_PARM -11 #define QETH_RCD_PARM -12 +static inline bool qeth_intparm_is_iob(unsigned long intparm) +{ + switch (intparm) { + case QETH_CLEAR_CHANNEL_PARM: + case QETH_HALT_CHANNEL_PARM: + case QETH_RCD_PARM: + case 0: + return false; + } + return true; +} + /*****************************************************************************/ /* IP Assist related definitions */ /*****************************************************************************/ diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 50a313806dde..b8079f2a65b3 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -21,7 +21,6 @@ #include <linux/list.h> #include <linux/hash.h> #include <linux/hashtable.h> -#include <linux/string.h> #include <asm/setup.h> #include "qeth_core.h" #include "qeth_l2.h" @@ -122,13 +121,10 @@ static int qeth_l2_send_setmac(struct qeth_card *card, __u8 *mac) QETH_CARD_TEXT(card, 2, "L2Setmac"); rc = qeth_l2_send_setdelmac(card, mac, IPA_CMD_SETVMAC); if (rc == 0) { - card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED; - ether_addr_copy(card->dev->dev_addr, mac); dev_info(&card->gdev->dev, - "MAC address %pM successfully registered on device %s\n", - card->dev->dev_addr, card->dev->name); + "MAC address %pM successfully registered on device %s\n", + mac, card->dev->name); } else { - card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED; switch (rc) { case -EEXIST: dev_warn(&card->gdev->dev, @@ -143,19 +139,6 @@ static int qeth_l2_send_setmac(struct qeth_card *card, __u8 *mac) return rc; } -static int qeth_l2_send_delmac(struct qeth_card *card, __u8 *mac) -{ - int rc; - - QETH_CARD_TEXT(card, 2, "L2Delmac"); - if (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED)) - return 0; - rc = qeth_l2_send_setdelmac(card, mac, IPA_CMD_DELVMAC); - if (rc == 0) - card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED; - return rc; -} - static int qeth_l2_write_mac(struct qeth_card *card, u8 *mac) { enum qeth_ipa_cmds cmd = is_multicast_ether_addr_64bits(mac) ? @@ -520,6 +503,7 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p) { struct sockaddr *addr = p; struct qeth_card *card = dev->ml_priv; + u8 old_addr[ETH_ALEN]; int rc = 0; QETH_CARD_TEXT(card, 3, "setmac"); @@ -531,14 +515,35 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p) return -EOPNOTSUPP; } QETH_CARD_HEX(card, 3, addr->sa_data, ETH_ALEN); + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) { QETH_CARD_TEXT(card, 3, "setmcREC"); return -ERESTARTSYS; } - rc = qeth_l2_send_delmac(card, &card->dev->dev_addr[0]); - if (!rc || (rc == -ENOENT)) - rc = qeth_l2_send_setmac(card, addr->sa_data); - return rc ? -EINVAL : 0; + + if (!qeth_card_hw_is_reachable(card)) { + ether_addr_copy(dev->dev_addr, addr->sa_data); + return 0; + } + + /* don't register the same address twice */ + if (ether_addr_equal_64bits(dev->dev_addr, addr->sa_data) && + (card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED)) + return 0; + + /* add the new address, switch over, drop the old */ + rc = qeth_l2_send_setmac(card, addr->sa_data); + if (rc) + return rc; + ether_addr_copy(old_addr, dev->dev_addr); + ether_addr_copy(dev->dev_addr, addr->sa_data); + + if (card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED) + qeth_l2_remove_mac(card, old_addr); + card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED; + return 0; } static void qeth_promisc_to_bridge(struct qeth_card *card) @@ -1068,8 +1073,9 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) goto out_remove; } - if (card->info.type != QETH_CARD_TYPE_OSN) - qeth_l2_send_setmac(card, &card->dev->dev_addr[0]); + if (card->info.type != QETH_CARD_TYPE_OSN && + !qeth_l2_send_setmac(card, card->dev->dev_addr)) + card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED; if (qeth_is_diagass_supported(card, QETH_DIAGS_CMD_TRAP)) { if (card->info.hwtrap && @@ -1339,8 +1345,8 @@ static int qeth_osn_send_control_data(struct qeth_card *card, int len, qeth_prepare_control_data(card, len, iob); QETH_CARD_TEXT(card, 6, "osnoirqp"); spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags); - rc = ccw_device_start(card->write.ccwdev, &card->write.ccw, - (addr_t) iob, 0, 0); + rc = ccw_device_start_timeout(CARD_WDEV(card), &card->write.ccw, + (addr_t) iob, 0, 0, QETH_IPA_TIMEOUT); spin_unlock_irqrestore(get_ccwdev_lock(card->write.ccwdev), flags); if (rc) { QETH_DBF_MESSAGE(2, "qeth_osn_send_control_data: " diff --git a/drivers/s390/net/smsgiucv.c b/drivers/s390/net/smsgiucv.c index 3b0c8b8a7634..066b5c3aaae6 100644 --- a/drivers/s390/net/smsgiucv.c +++ b/drivers/s390/net/smsgiucv.c @@ -176,7 +176,7 @@ static struct device_driver smsg_driver = { static void __exit smsg_exit(void) { - cpcmd("SET SMSG IUCV", NULL, 0, NULL); + cpcmd("SET SMSG OFF", NULL, 0, NULL); device_unregister(smsg_dev); iucv_unregister(&smsg_handler, 1); driver_unregister(&smsg_driver); diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index a8b831000b2d..18c4f933e8b9 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -4,7 +4,7 @@ * * Debug traces for zfcp. * - * Copyright IBM Corp. 2002, 2017 + * Copyright IBM Corp. 2002, 2018 */ #define KMSG_COMPONENT "zfcp" @@ -308,6 +308,27 @@ void zfcp_dbf_rec_trig(char *tag, struct zfcp_adapter *adapter, spin_unlock_irqrestore(&dbf->rec_lock, flags); } +/** + * zfcp_dbf_rec_trig_lock - trace event related to triggered recovery with lock + * @tag: identifier for event + * @adapter: adapter on which the erp_action should run + * @port: remote port involved in the erp_action + * @sdev: scsi device involved in the erp_action + * @want: wanted erp_action + * @need: required erp_action + * + * The adapter->erp_lock must not be held. + */ +void zfcp_dbf_rec_trig_lock(char *tag, struct zfcp_adapter *adapter, + struct zfcp_port *port, struct scsi_device *sdev, + u8 want, u8 need) +{ + unsigned long flags; + + read_lock_irqsave(&adapter->erp_lock, flags); + zfcp_dbf_rec_trig(tag, adapter, port, sdev, want, need); + read_unlock_irqrestore(&adapter->erp_lock, flags); +} /** * zfcp_dbf_rec_run_lvl - trace event related to running recovery diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index bf8ea4df2bb8..e5eed8aac0ce 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -4,7 +4,7 @@ * * External function declarations. * - * Copyright IBM Corp. 2002, 2016 + * Copyright IBM Corp. 2002, 2018 */ #ifndef ZFCP_EXT_H @@ -35,6 +35,9 @@ extern int zfcp_dbf_adapter_register(struct zfcp_adapter *); extern void zfcp_dbf_adapter_unregister(struct zfcp_adapter *); extern void zfcp_dbf_rec_trig(char *, struct zfcp_adapter *, struct zfcp_port *, struct scsi_device *, u8, u8); +extern void zfcp_dbf_rec_trig_lock(char *tag, struct zfcp_adapter *adapter, + struct zfcp_port *port, + struct scsi_device *sdev, u8 want, u8 need); extern void zfcp_dbf_rec_run(char *, struct zfcp_erp_action *); extern void zfcp_dbf_rec_run_lvl(int level, char *tag, struct zfcp_erp_action *erp); diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 4d2ba5682493..22f9562f415c 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -4,7 +4,7 @@ * * Interface to Linux SCSI midlayer. * - * Copyright IBM Corp. 2002, 2017 + * Copyright IBM Corp. 2002, 2018 */ #define KMSG_COMPONENT "zfcp" @@ -618,9 +618,9 @@ static void zfcp_scsi_rport_register(struct zfcp_port *port) ids.port_id = port->d_id; ids.roles = FC_RPORT_ROLE_FCP_TARGET; - zfcp_dbf_rec_trig("scpaddy", port->adapter, port, NULL, - ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD, - ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD); + zfcp_dbf_rec_trig_lock("scpaddy", port->adapter, port, NULL, + ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD, + ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD); rport = fc_remote_port_add(port->adapter->scsi_host, 0, &ids); if (!rport) { dev_err(&port->adapter->ccw_device->dev, @@ -642,9 +642,9 @@ static void zfcp_scsi_rport_block(struct zfcp_port *port) struct fc_rport *rport = port->rport; if (rport) { - zfcp_dbf_rec_trig("scpdely", port->adapter, port, NULL, - ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL, - ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL); + zfcp_dbf_rec_trig_lock("scpdely", port->adapter, port, NULL, + ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL, + ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL); fc_remote_port_delete(rport); port->rport = NULL; } |