From patchwork Mon Nov 9 16:32:29 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Garry X-Patchwork-Id: 56246 Delivered-To: patch@linaro.org Received: by 10.112.155.196 with SMTP id vy4csp269614lbb; Mon, 9 Nov 2015 08:21:06 -0800 (PST) X-Received: by 10.66.192.193 with SMTP id hi1mr10529512pac.110.1447086065282; Mon, 09 Nov 2015 08:21:05 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id lq8si23251843pab.72.2015.11.09.08.21.05 for ; Mon, 09 Nov 2015 08:21:05 -0800 (PST) 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 S1751648AbbKIQVD (ORCPT ); Mon, 9 Nov 2015 11:21:03 -0500 Received: from szxga02-in.huawei.com ([119.145.14.65]:13626 "EHLO szxga02-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752605AbbKIQTH (ORCPT ); Mon, 9 Nov 2015 11:19:07 -0500 Received: from 172.24.1.51 (EHLO szxeml434-hub.china.huawei.com) ([172.24.1.51]) by szxrg02-dlp.huawei.com (MOS 4.3.7-GA FastPath queued) with ESMTP id CVY12683; Tue, 10 Nov 2015 00:18:07 +0800 (CST) Received: from localhost.localdomain (10.67.212.75) by szxeml434-hub.china.huawei.com (10.82.67.225) with Microsoft SMTP Server id 14.3.235.1; Tue, 10 Nov 2015 00:17:57 +0800 From: John Garry To: , , , , , , CC: , , , , , , , , John Garry Subject: [PATCH v3 24/32] scsi: hisi_sas: add dev_found and dev_gone Date: Tue, 10 Nov 2015 00:32:29 +0800 Message-ID: <1447086757-147706-25-git-send-email-john.garry@huawei.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1447086757-147706-1-git-send-email-john.garry@huawei.com> References: <1447086757-147706-1-git-send-email-john.garry@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.67.212.75] X-CFilter-Loop: Reflected X-Mirapoint-Virus-RAPID-Raw: score=unknown(0), refid=str=0001.0A020202.5640C740.0210,ss=1,re=0.000,fgs=0, ip=0.0.0.0, so=2013-06-18 04:22:30, dmn=2011-05-27 18:58:46 X-Mirapoint-Loop-Id: bfd47555935bd32c6af4d4a9f7861390 Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org Add functions to deal with lldd_dev_found and lldd_dev_gone. Signed-off-by: John Garry --- drivers/scsi/hisi_sas/hisi_sas.h | 13 +++++ drivers/scsi/hisi_sas/hisi_sas_main.c | 88 ++++++++++++++++++++++++++++++++++ drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 41 ++++++++++++++++ 3 files changed, 142 insertions(+) -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index 2f927be..cf89f67 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -39,6 +39,7 @@ #define HISI_SAS_NAME_LEN 32 +struct hisi_hba; enum { PORT_TYPE_SAS = (1U << 1), @@ -49,6 +50,13 @@ enum dev_status { HISI_SAS_DEV_NORMAL, HISI_SAS_DEV_EH, }; + +enum hisi_sas_dev_type { + HISI_SAS_DEV_TYPE_STP = 0, + HISI_SAS_DEV_TYPE_SSP, + HISI_SAS_DEV_TYPE_SATA, +}; + struct hisi_sas_phy { struct hisi_hba *hisi_hba; struct hisi_sas_port *port; @@ -83,6 +91,9 @@ struct hisi_sas_cq { struct hisi_sas_device { enum sas_device_type dev_type; + struct hisi_hba *hisi_hba; + struct domain_device *sas_device; + u64 attached_phy; u64 device_id; u64 running_req; u8 dev_status; @@ -115,6 +126,8 @@ struct hisi_sas_tmf_task { struct hisi_sas_hw { int (*hw_init)(struct hisi_hba *hisi_hba); + void (*setup_itct)(struct hisi_hba *hisi_hba, + struct hisi_sas_device *device); void (*sl_notify)(struct hisi_hba *hisi_hba, int phy_no); int (*get_free_slot)(struct hisi_hba *hisi_hba, int *q, int *s); void (*start_delivery)(struct hisi_hba *hisi_hba); diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 9b55076..e6bb476 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -12,6 +12,9 @@ #include "hisi_sas.h" #define DRV_NAME "hisi_sas" +#define DEV_IS_EXPANDER(type) \ + ((type == SAS_EDGE_EXPANDER_DEVICE) || \ + (type == SAS_FANOUT_EXPANDER_DEVICE)) #define DEV_IS_GONE(dev) \ ((!dev) || (dev->dev_type == SAS_PHY_UNUSED)) @@ -325,6 +328,72 @@ static void hisi_sas_bytes_dmaed(struct hisi_hba *hisi_hba, int phy_no) sas_ha->notify_port_event(sas_phy, PORTE_BYTES_DMAED); } +static struct hisi_sas_device *hisi_sas_alloc_dev(struct domain_device *device) +{ + struct hisi_hba *hisi_hba = dev_to_hisi_hba(device); + struct hisi_sas_device *sas_dev = NULL; + int i; + + spin_lock(&hisi_hba->lock); + for (i = 0; i < HISI_SAS_MAX_DEVICES; i++) { + if (hisi_hba->devices[i].dev_type == SAS_PHY_UNUSED) { + hisi_hba->devices[i].device_id = i; + sas_dev = &hisi_hba->devices[i]; + sas_dev->dev_status = HISI_SAS_DEV_NORMAL; + sas_dev->dev_type = device->dev_type; + sas_dev->hisi_hba = hisi_hba; + sas_dev->sas_device = device; + break; + } + } + spin_unlock(&hisi_hba->lock); + + return sas_dev; +} + +static int hisi_sas_dev_found(struct domain_device *device) +{ + struct hisi_hba *hisi_hba = dev_to_hisi_hba(device); + struct domain_device *parent_dev = device->parent; + struct hisi_sas_device *sas_dev; + struct device *dev = &hisi_hba->pdev->dev; + + sas_dev = hisi_sas_alloc_dev(device); + if (!sas_dev) { + dev_err(dev, "fail alloc dev: max support %d devices\n", + HISI_SAS_MAX_DEVICES); + return -EINVAL; + } + + device->lldd_dev = sas_dev; + hisi_hba->hw->setup_itct(hisi_hba, sas_dev); + + if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type)) { + int phy_no; + u8 phy_num = parent_dev->ex_dev.num_phys; + struct ex_phy *phy; + + for (phy_no = 0; phy_no < phy_num; phy_no++) { + phy = &parent_dev->ex_dev.ex_phy[phy_no]; + if (SAS_ADDR(phy->attached_sas_addr) == + SAS_ADDR(device->sas_addr)) { + sas_dev->attached_phy = phy_no; + break; + } + } + + if (phy_no == phy_num) { + dev_info(dev, "dev found: no attached " + "dev:%016llx at ex:%016llx\n", + SAS_ADDR(device->sas_addr), + SAS_ADDR(parent_dev->sas_addr)); + return -EINVAL; + } + } + + return 0; +} + static void hisi_sas_phyup_work(struct work_struct *work) { struct hisi_sas_phy *phy = @@ -362,6 +431,23 @@ static void hisi_sas_phy_init(struct hisi_hba *hisi_hba, int phy_no) INIT_WORK(&phy->phyup_ws, hisi_sas_phyup_work); } +static void hisi_sas_dev_gone(struct domain_device *device) +{ + struct hisi_sas_device *sas_dev = device->lldd_dev; + struct hisi_hba *hisi_hba = dev_to_hisi_hba(device); + struct device *dev = &hisi_hba->pdev->dev; + u64 dev_id = sas_dev->device_id; + + dev_info(dev, "found dev[%lld:%x] is gone\n", + sas_dev->device_id, sas_dev->dev_type); + + hisi_hba->hw->free_device(hisi_hba, sas_dev); + device->lldd_dev = NULL; + memset(sas_dev, 0, sizeof(*sas_dev)); + sas_dev->device_id = dev_id; + sas_dev->dev_type = SAS_PHY_UNUSED; + sas_dev->dev_status = HISI_SAS_DEV_NORMAL; +} static int hisi_sas_queue_command(struct sas_task *task, gfp_t gfp_flags) { @@ -390,6 +476,8 @@ static struct scsi_host_template hisi_sas_sht = { }; static struct sas_domain_function_template hisi_sas_transport_ops = { + .lldd_dev_found = hisi_sas_dev_found, + .lldd_dev_gone = hisi_sas_dev_gone, .lldd_execute_task = hisi_sas_queue_command, }; diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c index 2806e48..45564fb 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c @@ -498,6 +498,46 @@ static void init_id_frame_v1_hw(struct hisi_hba *hisi_hba) config_id_frame_v1_hw(hisi_hba, i); } +static void setup_itct_v1_hw(struct hisi_hba *hisi_hba, + struct hisi_sas_device *sas_dev) +{ + struct domain_device *device = sas_dev->sas_device; + struct device *dev = &hisi_hba->pdev->dev; + u64 qw0, device_id = sas_dev->device_id; + struct hisi_sas_itct *itct = &hisi_hba->itct[device_id]; + + memset(itct, 0, sizeof(*itct)); + + /* qw0 */ + qw0 = 0; + switch (sas_dev->dev_type) { + case SAS_END_DEVICE: + case SAS_EDGE_EXPANDER_DEVICE: + case SAS_FANOUT_EXPANDER_DEVICE: + qw0 = HISI_SAS_DEV_TYPE_SSP << ITCT_HDR_DEV_TYPE_OFF; + break; + default: + dev_warn(dev, "setup itct: unsupported dev type (%d)\n", + sas_dev->dev_type); + } + + qw0 |= ((1 << ITCT_HDR_VALID_OFF) | + (1 << ITCT_HDR_AWT_CONTROL_OFF) | + (device->max_linkrate << ITCT_HDR_MAX_CONN_RATE_OFF) | + (1 << ITCT_HDR_VALID_LINK_NUM_OFF) | + (device->port->id << ITCT_HDR_PORT_ID_OFF)); + itct->qw0 = cpu_to_le64(qw0); + + /* qw1 */ + memcpy(&itct->sas_addr, device->sas_addr, SAS_ADDR_SIZE); + itct->sas_addr = __swab64(itct->sas_addr); + + /* qw2 */ + itct->qw2 = cpu_to_le64((500 < ITCT_HDR_IT_NEXUS_LOSS_TL_OFF) | + (0xff00 < ITCT_HDR_BUS_INACTIVE_TL_OFF) | + (0xff00 < ITCT_HDR_MAX_CONN_TL_OFF) | + (0xff00 < ITCT_HDR_REJ_OPEN_TL_OFF)); +} static void free_device_v1_hw(struct hisi_hba *hisi_hba, struct hisi_sas_device *sas_dev) @@ -1455,6 +1495,7 @@ static int hisi_sas_v1_init(struct hisi_hba *hisi_hba) static const struct hisi_sas_hw hisi_sas_v1_hw = { .hw_init = hisi_sas_v1_init, + .setup_itct = setup_itct_v1_hw, .sl_notify = sl_notify_v1_hw, .free_device = free_device_v1_hw, .prep_ssp = prep_ssp_v1_hw,