From patchwork Mon Jul 10 07:06:06 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: wangyijing X-Patchwork-Id: 107274 Delivered-To: patch@linaro.org Received: by 10.140.101.44 with SMTP id t41csp3037717qge; Mon, 10 Jul 2017 00:02:23 -0700 (PDT) X-Received: by 10.84.128.103 with SMTP id 94mr16345296pla.234.1499670143742; Mon, 10 Jul 2017 00:02:23 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1499670143; cv=none; d=google.com; s=arc-20160816; b=iY1LzDr94ZKAKLgpj2LMlOEjkuCYnGDCviMiqeMvvQgptGqDenWIcG/wZMtvugzXUs xeKSKV4eEvLoPH2bVpj5IVJlNM8djwZ9tnHdgOyUfWIzALbL+jDSCY2NQMtMxhhZ/nWx eC2h0PTmXtzZ9m1swT0zZ2hdbJOS/2c6CIXwVWJG29vD1p9+f4IaEaYs36uu6aa5s1bx RGNlWnhp5GWaqZsLQtbfFXUOsYEIuRllkUYQnrYSNor8zcq//30ctnmhLkzPg36BWDws u6W8cl9kb1Azk6mfpHu7esyM9ArfFUaQRY7nYbDIY4yWw7tNlRhQOcCdKd6QtWK1O81S V5RA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:arc-authentication-results; bh=VK/NgmoUgF3zmYFtRfuRM3Wkp5fHufqNEeII1X5Cqok=; b=BEefGeU8I6RQQN1spz0DW6rdPIMk9C14E+eKGTHQWJ/Zi3D3bfcHNj1t0JJu45+N4W qYjCKQrozVeY/h3+3twz4GNHP+5OQPs1uV+jmpw4LA9BjJh3zr2E8h6VZIYJwmdZEsNO LVmjycUwdh9nvMOhp+BncoPlrDObhpCIoohYuPdvKVnnZPvz/OMHbzvNVB1RYyahV9b6 tdlSVZRNRvqCNkykCF7uK1jbVejdVwiBKwMqiRVueGnx40FIxutyQhBA3/wnAiLZj2n1 FRXth4wy9OqwGfpG//S7hXKJQwGALADlrjnmn1zzi1U0Nx7rEk5XQkmlGWri2UJoM/lF THaA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-scsi-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-scsi-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id u1si7286725pfa.258.2017.07.10.00.02.23; Mon, 10 Jul 2017 00:02:23 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-scsi-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-scsi-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-scsi-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752618AbdGJHCW (ORCPT + 1 other); Mon, 10 Jul 2017 03:02:22 -0400 Received: from szxga01-in.huawei.com ([45.249.212.187]:9298 "EHLO szxga01-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751163AbdGJHCU (ORCPT ); Mon, 10 Jul 2017 03:02:20 -0400 Received: from 172.30.72.54 (EHLO dggeml406-hub.china.huawei.com) ([172.30.72.54]) by dggrg01-dlp.huawei.com (MOS 4.4.6-GA FastPath queued) with ESMTP id ARU37602; Mon, 10 Jul 2017 15:02:12 +0800 (CST) Received: from 138.huawei.com (10.175.124.28) by dggeml406-hub.china.huawei.com (10.3.17.50) with Microsoft SMTP Server id 14.3.301.0; Mon, 10 Jul 2017 15:02:05 +0800 From: Yijing Wang To: , CC: , , , , , , , , , , , , , , , , , , , Yijing Wang , "Johannes Thumshirn" Subject: [PATCH v3 4/7] libsas: add sas event wait-complete support Date: Mon, 10 Jul 2017 15:06:06 +0800 Message-ID: <1499670369-44143-5-git-send-email-wangyijing@huawei.com> X-Mailer: git-send-email 2.5.0 In-Reply-To: <1499670369-44143-1-git-send-email-wangyijing@huawei.com> References: <1499670369-44143-1-git-send-email-wangyijing@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.175.124.28] X-CFilter-Loop: Reflected X-Mirapoint-Virus-RAPID-Raw: score=unknown(0), refid=str=0001.0A020204.59632675.0017, ss=1, re=0.000, recu=0.000, reip=0.000, cl=1, cld=1, fgs=0, ip=0.0.0.0, so=2014-11-16 11:51:01, dmn=2013-03-21 17:37:32 X-Mirapoint-Loop-Id: 395af9df5221eef312253d515a5ff7a7 Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org Introduce wait-complete for libsas sas event processing, execute sas port create/destruct in sync. Signed-off-by: Yijing Wang CC: John Garry CC: Johannes Thumshirn CC: Ewan Milne CC: Christoph Hellwig CC: Tomas Henzl CC: Dan Williams --- drivers/scsi/libsas/sas_discover.c | 41 ++++++++++++++++++++++++++++---------- drivers/scsi/libsas/sas_internal.h | 34 +++++++++++++++++++++++++++++++ drivers/scsi/libsas/sas_port.c | 4 ++++ include/scsi/libsas.h | 5 ++++- 4 files changed, 72 insertions(+), 12 deletions(-) -- 2.5.0 diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c index 60de662..5d4a3a8 100644 --- a/drivers/scsi/libsas/sas_discover.c +++ b/drivers/scsi/libsas/sas_discover.c @@ -525,16 +525,43 @@ static void sas_revalidate_domain(struct work_struct *work) mutex_unlock(&ha->disco_mutex); } +static const work_func_t sas_event_fns[DISC_NUM_EVENTS] = { + [DISCE_DISCOVER_DOMAIN] = sas_discover_domain, + [DISCE_REVALIDATE_DOMAIN] = sas_revalidate_domain, + [DISCE_PROBE] = sas_probe_devices, + [DISCE_SUSPEND] = sas_suspend_devices, + [DISCE_RESUME] = sas_resume_devices, + [DISCE_DESTRUCT] = sas_destruct_devices, +}; + +/* a simple wrapper for sas discover event funtions */ +static void sas_discover_common_fn(struct work_struct *work) +{ + struct sas_discovery_event *ev = to_sas_discovery_event(work); + struct asd_sas_port *port = ev->port; + + sas_event_fns[ev->type](work); + sas_port_put(port); +} + + /* ---------- Events ---------- */ static void sas_chain_work(struct sas_ha_struct *ha, struct sas_work *sw) { + int ret; + struct sas_discovery_event *ev = to_sas_discovery_event(&sw->work); + struct asd_sas_port *port = ev->port; + /* chained work is not subject to SA_HA_DRAINING or * SAS_HA_REGISTERED, because it is either submitted in the * workqueue, or known to be submitted from a context that is * not racing against draining */ - scsi_queue_work(ha->core.shost, &sw->work); + sas_port_get(port); + ret = scsi_queue_work(ha->core.shost, &sw->work); + if (ret != 1) + sas_port_put(port); } static void sas_chain_event(int event, unsigned long *pending, @@ -575,18 +602,10 @@ void sas_init_disc(struct sas_discovery *disc, struct asd_sas_port *port) { int i; - static const work_func_t sas_event_fns[DISC_NUM_EVENTS] = { - [DISCE_DISCOVER_DOMAIN] = sas_discover_domain, - [DISCE_REVALIDATE_DOMAIN] = sas_revalidate_domain, - [DISCE_PROBE] = sas_probe_devices, - [DISCE_SUSPEND] = sas_suspend_devices, - [DISCE_RESUME] = sas_resume_devices, - [DISCE_DESTRUCT] = sas_destruct_devices, - }; - disc->pending = 0; for (i = 0; i < DISC_NUM_EVENTS; i++) { - INIT_SAS_WORK(&disc->disc_work[i].work, sas_event_fns[i]); + INIT_SAS_WORK(&disc->disc_work[i].work, sas_discover_common_fn); disc->disc_work[i].port = port; + disc->disc_work[i].type = i; } } diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h index f03ce64..890b5d26 100644 --- a/drivers/scsi/libsas/sas_internal.h +++ b/drivers/scsi/libsas/sas_internal.h @@ -100,6 +100,40 @@ void sas_free_device(struct kref *kref); extern const work_func_t sas_phy_event_fns[PHY_NUM_EVENTS]; extern const work_func_t sas_port_event_fns[PORT_NUM_EVENTS]; +static void sas_complete_event(struct kref *kref) +{ + struct asd_sas_port *port = container_of(kref, struct asd_sas_port, ref); + + complete_all(&port->completion); +} + +static inline void sas_port_put(struct asd_sas_port *port) +{ + if (port->is_sync) + kref_put(&port->ref, sas_complete_event); +} + +static inline void sas_port_wait_init(struct asd_sas_port *port) +{ + init_completion(&port->completion); + kref_init(&port->ref); + port->is_sync = true; +} + +static inline void sas_port_wait_completion( + struct asd_sas_port *port) +{ + sas_port_put(port); + wait_for_completion(&port->completion); + port->is_sync = false; +} + +static inline void sas_port_get(struct asd_sas_port *port) +{ + if (port && port->is_sync) + kref_get(&port->ref); +} + #ifdef CONFIG_SCSI_SAS_HOST_SMP extern int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req, struct request *rsp); diff --git a/drivers/scsi/libsas/sas_port.c b/drivers/scsi/libsas/sas_port.c index 9326628..d589adb 100644 --- a/drivers/scsi/libsas/sas_port.c +++ b/drivers/scsi/libsas/sas_port.c @@ -191,7 +191,9 @@ static void sas_form_port(struct asd_sas_phy *phy) if (si->dft->lldd_port_formed) si->dft->lldd_port_formed(phy); + sas_port_wait_init(port); sas_discover_event(phy->port, DISCE_DISCOVER_DOMAIN); + sas_port_wait_completion(port); } /** @@ -218,7 +220,9 @@ void sas_deform_port(struct asd_sas_phy *phy, int gone) dev->pathways--; if (port->num_phys == 1) { + sas_port_wait_init(port); sas_unregister_domain_devices(port, gone); + sas_port_wait_completion(port); sas_port_delete(port->port); port->port = NULL; } else { diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index a01ca42..c2ef05e 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -242,6 +242,7 @@ static inline void INIT_SAS_WORK(struct sas_work *sw, void (*fn)(struct work_str struct sas_discovery_event { struct sas_work work; struct asd_sas_port *port; + enum discover_event type; }; static inline struct sas_discovery_event *to_sas_discovery_event(struct work_struct *work) @@ -273,7 +274,9 @@ struct asd_sas_port { struct sas_work work; int suspended; - + struct kref ref; + struct completion completion; + bool is_sync; /* public: */ int id;