From patchwork Fri Mar 18 14:21:27 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cornelia Huck X-Patchwork-Id: 8620231 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id A856AC0553 for ; Fri, 18 Mar 2016 14:29:08 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 88CCE20149 for ; Fri, 18 Mar 2016 14:29:07 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 3E95E20108 for ; Fri, 18 Mar 2016 14:29:06 +0000 (UTC) Received: from localhost ([::1]:43970 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1agvOj-0004en-KH for patchwork-qemu-devel@patchwork.kernel.org; Fri, 18 Mar 2016 10:29:05 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52476) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1agvHo-0000Il-7G for qemu-devel@nongnu.org; Fri, 18 Mar 2016 10:21:59 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1agvHk-000748-TZ for qemu-devel@nongnu.org; Fri, 18 Mar 2016 10:21:56 -0400 Received: from e06smtp08.uk.ibm.com ([195.75.94.104]:35470) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1agvHk-00073l-Km for qemu-devel@nongnu.org; Fri, 18 Mar 2016 10:21:52 -0400 Received: from localhost by e06smtp08.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Fri, 18 Mar 2016 14:21:51 -0000 Received: from d06dlp01.portsmouth.uk.ibm.com (9.149.20.13) by e06smtp08.uk.ibm.com (192.168.101.138) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Fri, 18 Mar 2016 14:21:41 -0000 X-IBM-Helo: d06dlp01.portsmouth.uk.ibm.com X-IBM-MailFrom: cornelia.huck@de.ibm.com X-IBM-RcptTo: qemu-devel@nongnu.org Received: from b06cxnps3074.portsmouth.uk.ibm.com (d06relay09.portsmouth.uk.ibm.com [9.149.109.194]) by d06dlp01.portsmouth.uk.ibm.com (Postfix) with ESMTP id 6D7D017D8066 for ; Fri, 18 Mar 2016 14:22:13 +0000 (GMT) Received: from d06av05.portsmouth.uk.ibm.com (d06av05.portsmouth.uk.ibm.com [9.149.37.229]) by b06cxnps3074.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id u2IELfJH51380286 for ; Fri, 18 Mar 2016 14:21:41 GMT Received: from d06av05.portsmouth.uk.ibm.com (localhost [127.0.0.1]) by d06av05.portsmouth.uk.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id u2IELeDE004115 for ; Fri, 18 Mar 2016 08:21:40 -0600 Received: from gondolin.boeblingen.de.ibm.com (dyn-9-152-224-197.boeblingen.de.ibm.com [9.152.224.197]) by d06av05.portsmouth.uk.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id u2IELbut003985 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Fri, 18 Mar 2016 08:21:40 -0600 From: Cornelia Huck To: qemu-devel@nongnu.org Date: Fri, 18 Mar 2016 15:21:27 +0100 Message-Id: <1458310895-29044-7-git-send-email-cornelia.huck@de.ibm.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1458310895-29044-1-git-send-email-cornelia.huck@de.ibm.com> References: <1458310895-29044-1-git-send-email-cornelia.huck@de.ibm.com> X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 16031814-0033-0000-0000-000006B61EC2 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 195.75.94.104 Cc: Cornelia Huck , borntraeger@de.ibm.com, jfrei@linux.vnet.ibm.com, agraf@suse.de, "Eugene \(jno\) Dvurechenski" Subject: [Qemu-devel] [PATCH for-2.6 06/14] pc-bios/s390-ccw: add vdev object to store all device details X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: "Eugene (jno) Dvurechenski" Add VDev "object" as a container for all device-related items. The default object is static. Leverage dependency on many different device-related globals. Make them syntactically visible. Signed-off-by: Eugene (jno) Dvurechenski Signed-off-by: Cornelia Huck --- pc-bios/s390-ccw/virtio.c | 181 +++++++++++++++++++++++++--------------------- pc-bios/s390-ccw/virtio.h | 18 +++++ 2 files changed, 116 insertions(+), 83 deletions(-) diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c index d366aa3..6bf0c38 100644 --- a/pc-bios/s390-ccw/virtio.c +++ b/pc-bios/s390-ccw/virtio.c @@ -11,13 +11,34 @@ #include "s390-ccw.h" #include "virtio.h" +#define VRING_WAIT_REPLY_TIMEOUT 3 + static VRing block[VIRTIO_MAX_VQS]; static char ring_area[VIRTIO_RING_SIZE * VIRTIO_MAX_VQS] __attribute__((__aligned__(PAGE_SIZE))); -static int nr_vqs = 1; static char chsc_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE))); +static VDev vdev = { + .nr_vqs = 1, + .vrings = block, + .cmd_vr_idx = 0, + .ring_area = ring_area, + .wait_reply_timeout = VRING_WAIT_REPLY_TIMEOUT, + .guessed_disk_nature = false, + .schid = { .one = 1 }, +}; + +VDev *virtio_get_device(void) +{ + return &vdev; +} + +VirtioDevType virtio_get_device_type(void) +{ + return vdev.senseid.cu_model; +} + /* virtio spec v1.0 para 4.3.3.2 */ static long kvm_hypercall(unsigned long nr, unsigned long param1, unsigned long param2, unsigned long param3) @@ -65,7 +86,7 @@ static int drain_irqs(SubChannelId schid) } } -static int run_ccw(SubChannelId schid, int cmd, void *ptr, int len) +static int run_ccw(VDev *vdev, int cmd, void *ptr, int len) { Ccw1 ccw = {}; CmdOrb orb = {}; @@ -73,9 +94,9 @@ static int run_ccw(SubChannelId schid, int cmd, void *ptr, int len) int r; /* start command processing */ - stsch_err(schid, &schib); + stsch_err(vdev->schid, &schib); schib.scsw.ctrl = SCSW_FCTL_START_FUNC; - msch(schid, &schib); + msch(vdev->schid, &schib); /* start subchannel command */ orb.fmt = 1; @@ -86,32 +107,18 @@ static int run_ccw(SubChannelId schid, int cmd, void *ptr, int len) ccw.cda = (long)ptr; ccw.count = len; - r = ssch(schid, &orb); + r = ssch(vdev->schid, &orb); /* * XXX Wait until device is done processing the CCW. For now we can * assume that a simple tsch will have finished the CCW processing, * but the architecture allows for asynchronous operation */ if (!r) { - r = drain_irqs(schid); + r = drain_irqs(vdev->schid); } return r; } -static void virtio_set_status(SubChannelId schid, - unsigned long dev_addr) -{ - unsigned char status = dev_addr; - if (run_ccw(schid, CCW_CMD_WRITE_STATUS, &status, sizeof(status))) { - panic("Could not write status to host!\n"); - } -} - -static void virtio_reset(SubChannelId schid) -{ - run_ccw(schid, CCW_CMD_VDEV_RESET, NULL, 0); -} - static void vring_init(VRing *vr, VqInfo *info) { void *p = (void *) info->queue; @@ -199,22 +206,22 @@ static int vr_poll(VRing *vr) * * Returns 0 on success, 1 on timeout. */ -static int vring_wait_reply(int timeout) +static int vring_wait_reply(void) { - ulong target_second = get_second() + timeout; + ulong target_second = get_second() + vdev.wait_reply_timeout; /* Wait for any queue to be updated by the host */ do { int i, r = 0; - for (i = 0; i < nr_vqs; i++) { - r += vr_poll(&block[i]); + for (i = 0; i < vdev.nr_vqs; i++) { + r += vr_poll(&vdev.vrings[i]); } yield(); if (r) { return 0; } - } while (!timeout || (get_second() < target_second)); + } while (!vdev.wait_reply_timeout || (get_second() < target_second)); return 1; } @@ -227,29 +234,28 @@ int virtio_read_many(ulong sector, void *load_addr, int sec_num) { VirtioBlkOuthdr out_hdr; u8 status; - int r; + VRing *vr = &vdev.vrings[vdev.cmd_vr_idx]; /* Tell the host we want to read */ out_hdr.type = VIRTIO_BLK_T_IN; out_hdr.ioprio = 99; out_hdr.sector = virtio_sector_adjust(sector); - vring_send_buf(&block[0], &out_hdr, sizeof(out_hdr), VRING_DESC_F_NEXT); + vring_send_buf(vr, &out_hdr, sizeof(out_hdr), VRING_DESC_F_NEXT); /* This is where we want to receive data */ - vring_send_buf(&block[0], load_addr, virtio_get_block_size() * sec_num, + vring_send_buf(vr, load_addr, virtio_get_block_size() * sec_num, VRING_DESC_F_WRITE | VRING_HIDDEN_IS_CHAIN | VRING_DESC_F_NEXT); /* status field */ - vring_send_buf(&block[0], &status, sizeof(u8), VRING_DESC_F_WRITE | - VRING_HIDDEN_IS_CHAIN); + vring_send_buf(vr, &status, sizeof(u8), + VRING_DESC_F_WRITE | VRING_HIDDEN_IS_CHAIN); /* Now we can tell the host to read */ - vring_wait_reply(0); + vring_wait_reply(); - r = drain_irqs(block[0].schid); - if (r) { + if (drain_irqs(vr->schid)) { /* Well, whatever status is supposed to contain... */ status = 1; } @@ -284,46 +290,43 @@ int virtio_read(ulong sector, void *load_addr) return virtio_read_many(sector, load_addr, 1); } -static VirtioBlkConfig blk_cfg = {}; -static bool guessed_disk_nature; - bool virtio_guessed_disk_nature(void) { - return guessed_disk_nature; + return vdev.guessed_disk_nature; } void virtio_assume_scsi(void) { - guessed_disk_nature = true; - blk_cfg.blk_size = 512; - blk_cfg.physical_block_exp = 0; + vdev.guessed_disk_nature = true; + vdev.config.blk.blk_size = 512; + vdev.config.blk.physical_block_exp = 0; } void virtio_assume_iso9660(void) { - guessed_disk_nature = true; - blk_cfg.blk_size = 2048; - blk_cfg.physical_block_exp = 0; + vdev.guessed_disk_nature = true; + vdev.config.blk.blk_size = 2048; + vdev.config.blk.physical_block_exp = 0; } void virtio_assume_eckd(void) { - guessed_disk_nature = true; - blk_cfg.blk_size = 4096; - blk_cfg.physical_block_exp = 0; + vdev.guessed_disk_nature = true; + vdev.config.blk.blk_size = 4096; + vdev.config.blk.physical_block_exp = 0; /* this must be here to calculate code segment position */ - blk_cfg.geometry.heads = 15; - blk_cfg.geometry.sectors = 12; + vdev.config.blk.geometry.heads = 15; + vdev.config.blk.geometry.sectors = 12; } bool virtio_disk_is_scsi(void) { - if (guessed_disk_nature) { + if (vdev.guessed_disk_nature) { return (virtio_get_block_size() == 512); } - return (blk_cfg.geometry.heads == 255) - && (blk_cfg.geometry.sectors == 63) + return (vdev.config.blk.geometry.heads == 255) + && (vdev.config.blk.geometry.sectors == 63) && (virtio_get_block_size() == 512); } @@ -350,11 +353,11 @@ bool virtio_disk_is_eckd(void) { const int block_size = virtio_get_block_size(); - if (guessed_disk_nature) { + if (vdev.guessed_disk_nature) { return (block_size == 4096); } - return (blk_cfg.geometry.heads == 15) - && (blk_cfg.geometry.sectors == + return (vdev.config.blk.geometry.heads == 15) + && (vdev.config.blk.geometry.sectors == virtio_eckd_sectors_for_block_size(block_size)); } @@ -365,36 +368,45 @@ bool virtio_ipl_disk_is_valid(void) int virtio_get_block_size(void) { - return blk_cfg.blk_size << blk_cfg.physical_block_exp; + return vdev.config.blk.blk_size << vdev.config.blk.physical_block_exp; } uint8_t virtio_get_heads(void) { - return blk_cfg.geometry.heads; + return vdev.config.blk.geometry.heads; } uint8_t virtio_get_sectors(void) { - return blk_cfg.geometry.sectors; + return vdev.config.blk.geometry.sectors; } uint64_t virtio_get_blocks(void) { - return blk_cfg.capacity / + return vdev.config.blk.capacity / (virtio_get_block_size() / VIRTIO_SECTOR_SIZE); } -static void virtio_setup_ccw(SubChannelId schid, - int nvr, void *cfg, int cfg_size) +static void virtio_setup_ccw(VDev *vdev) { - int i; + int i, cfg_size; + unsigned char status = VIRTIO_CONFIG_S_DRIVER_OK; + + vdev->config.blk.blk_size = 0; /* mark "illegal" - setup started... */ + vdev->guessed_disk_nature = false; - blk_cfg.blk_size = 0; /* mark "illegal" - setup started... */ - nr_vqs = nvr; - guessed_disk_nature = false; + run_ccw(vdev, CCW_CMD_VDEV_RESET, NULL, 0); - virtio_reset(schid); - IPL_assert(run_ccw(schid, CCW_CMD_READ_CONF, cfg, cfg_size) == 0, + switch (vdev->senseid.cu_model) { + case VIRTIO_ID_BLOCK: + vdev->nr_vqs = 1; + vdev->cmd_vr_idx = 0; + cfg_size = sizeof(vdev->config.blk); + break; + default: + panic("Unsupported virtio device\n"); + } + IPL_assert(run_ccw(vdev, CCW_CMD_READ_CONF, &vdev->config, cfg_size) == 0, "Could not get block device configuration"); /* @@ -403,7 +415,7 @@ static void virtio_setup_ccw(SubChannelId schid, * expect it. */ - for (i = 0; i < nr_vqs; i++) { + for (i = 0; i < vdev->nr_vqs; i++) { VqInfo info = { .queue = (unsigned long long) ring_area + (i * VIRTIO_RING_SIZE), .align = KVM_S390_VIRTIO_RING_ALIGN, @@ -416,43 +428,46 @@ static void virtio_setup_ccw(SubChannelId schid, }; IPL_assert( - run_ccw(schid, CCW_CMD_READ_VQ_CONF, &config, sizeof(config)) == 0, + run_ccw(vdev, CCW_CMD_READ_VQ_CONF, &config, sizeof(config)) == 0, "Could not get block device VQ configuration"); info.num = config.num; - vring_init(&block[i], &info); - block[i].schid = schid; - IPL_assert(run_ccw(schid, CCW_CMD_SET_VQ, &info, sizeof(info)) == 0, + vring_init(&vdev->vrings[i], &info); + vdev->vrings[i].schid = vdev->schid; + IPL_assert(run_ccw(vdev, CCW_CMD_SET_VQ, &info, sizeof(info)) == 0, "Cannot set VQ info"); } - virtio_set_status(schid, VIRTIO_CONFIG_S_DRIVER_OK); + IPL_assert( + run_ccw(vdev, CCW_CMD_WRITE_STATUS, &status, sizeof(status)) == 0, + "Could not write status to host"); } void virtio_setup_block(SubChannelId schid) { - virtio_setup_ccw(schid, 1, &blk_cfg, sizeof(blk_cfg)); + vdev.schid = schid; + virtio_setup_ccw(&vdev); if (!virtio_ipl_disk_is_valid()) { /* make sure all getters but blocksize return 0 for invalid IPL disk */ - memset(&blk_cfg, 0, sizeof(blk_cfg)); + memset(&vdev.config.blk, 0, sizeof(vdev.config.blk)); virtio_assume_scsi(); } } bool virtio_is_blk(SubChannelId schid) { - int r; - SenseId senseid = {}; - + vdev.schid = schid; + memset(&vdev.senseid, 0, sizeof(vdev.senseid)); /* run sense id command */ - r = run_ccw(schid, CCW_CMD_SENSE_ID, &senseid, sizeof(senseid)); - if (r) { + if (run_ccw(&vdev, CCW_CMD_SENSE_ID, &vdev.senseid, sizeof(vdev.senseid))) { return false; } - if ((senseid.cu_type != 0x3832) || (senseid.cu_model != VIRTIO_ID_BLOCK)) { - return false; + if (vdev.senseid.cu_type == 0x3832) { + switch (vdev.senseid.cu_model) { + case VIRTIO_ID_BLOCK: + return true; + } } - - return true; + return false; } int enable_mss_facility(void) diff --git a/pc-bios/s390-ccw/virtio.h b/pc-bios/s390-ccw/virtio.h index d17b135..b0034aa 100644 --- a/pc-bios/s390-ccw/virtio.h +++ b/pc-bios/s390-ccw/virtio.h @@ -222,4 +222,22 @@ static inline ulong virtio_sector_adjust(ulong sector) return sector * (virtio_get_block_size() / VIRTIO_SECTOR_SIZE); } +struct VDev { + int nr_vqs; + VRing *vrings; + int cmd_vr_idx; + void *ring_area; + long wait_reply_timeout; + bool guessed_disk_nature; + SubChannelId schid; + SenseId senseid; + union { + VirtioBlkConfig blk; + } config; +}; +typedef struct VDev VDev; + +VDev *virtio_get_device(void); +VirtioDevType virtio_get_device_type(void); + #endif /* VIRTIO_H */