^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Serial Attached SCSI (SAS) Expander discovery and configuration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2005 Adaptec, Inc. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2005 Luben Tuikov <luben_tuikov@adaptec.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * This file is licensed under GPLv2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/scatterlist.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/blkdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <asm/unaligned.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "sas_internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <scsi/sas_ata.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <scsi/scsi_transport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <scsi/scsi_transport_sas.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "../scsi_sas_internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) static int sas_discover_expander(struct domain_device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) static int sas_configure_routing(struct domain_device *dev, u8 *sas_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) static int sas_configure_phy(struct domain_device *dev, int phy_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) u8 *sas_addr, int include);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) static int sas_disable_routing(struct domain_device *dev, u8 *sas_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) /* ---------- SMP task management ---------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static void smp_task_timedout(struct timer_list *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) struct sas_task_slow *slow = from_timer(slow, t, timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) struct sas_task *task = slow->task;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) spin_lock_irqsave(&task->task_state_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) task->task_state_flags |= SAS_TASK_STATE_ABORTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) complete(&task->slow_task->completion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) spin_unlock_irqrestore(&task->task_state_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static void smp_task_done(struct sas_task *task)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) del_timer(&task->slow_task->timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) complete(&task->slow_task->completion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* Give it some long enough timeout. In seconds. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define SMP_TIMEOUT 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static int smp_execute_task_sg(struct domain_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct scatterlist *req, struct scatterlist *resp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) int res, retry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct sas_task *task = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct sas_internal *i =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) to_sas_internal(dev->port->ha->core.shost->transportt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) mutex_lock(&dev->ex_dev.cmd_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) for (retry = 0; retry < 3; retry++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) if (test_bit(SAS_DEV_GONE, &dev->state)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) res = -ECOMM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) task = sas_alloc_slow_task(GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (!task) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) res = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) task->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) task->task_proto = dev->tproto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) task->smp_task.smp_req = *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) task->smp_task.smp_resp = *resp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) task->task_done = smp_task_done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) task->slow_task->timer.function = smp_task_timedout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) task->slow_task->timer.expires = jiffies + SMP_TIMEOUT*HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) add_timer(&task->slow_task->timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) res = i->dft->lldd_execute_task(task, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) del_timer(&task->slow_task->timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) pr_notice("executing SMP task failed:%d\n", res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) wait_for_completion(&task->slow_task->completion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) res = -ECOMM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) pr_notice("smp task timed out or aborted\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) i->dft->lldd_abort_task(task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) pr_notice("SMP task aborted and not done\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (task->task_status.resp == SAS_TASK_COMPLETE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) task->task_status.stat == SAM_STAT_GOOD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) res = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if (task->task_status.resp == SAS_TASK_COMPLETE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) task->task_status.stat == SAS_DATA_UNDERRUN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) /* no error, but return the number of bytes of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * underrun */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) res = task->task_status.residual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (task->task_status.resp == SAS_TASK_COMPLETE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) task->task_status.stat == SAS_DATA_OVERRUN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) res = -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if (task->task_status.resp == SAS_TASK_UNDELIVERED &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) task->task_status.stat == SAS_DEVICE_UNKNOWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) pr_notice("%s: task to dev %016llx response: 0x%x status 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) SAS_ADDR(dev->sas_addr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) task->task_status.resp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) task->task_status.stat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) sas_free_task(task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) task = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) mutex_unlock(&dev->ex_dev.cmd_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) BUG_ON(retry == 3 && task != NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) sas_free_task(task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) static int smp_execute_task(struct domain_device *dev, void *req, int req_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) void *resp, int resp_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) struct scatterlist req_sg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) struct scatterlist resp_sg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) sg_init_one(&req_sg, req, req_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) sg_init_one(&resp_sg, resp, resp_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return smp_execute_task_sg(dev, &req_sg, &resp_sg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /* ---------- Allocations ---------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) static inline void *alloc_smp_req(int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) u8 *p = kzalloc(size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) p[0] = SMP_REQUEST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) return p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) static inline void *alloc_smp_resp(int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) return kzalloc(size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) static char sas_route_char(struct domain_device *dev, struct ex_phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) switch (phy->routing_attr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) case TABLE_ROUTING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) if (dev->ex_dev.t2t_supp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return 'U';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return 'T';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) case DIRECT_ROUTING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) return 'D';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) case SUBTRACTIVE_ROUTING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) return 'S';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) return '?';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) static enum sas_device_type to_dev_type(struct discover_resp *dr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) /* This is detecting a failure to transmit initial dev to host
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * FIS as described in section J.5 of sas-2 r16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if (dr->attached_dev_type == SAS_PHY_UNUSED && dr->attached_sata_dev &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) dr->linkrate >= SAS_LINK_RATE_1_5_GBPS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) return SAS_SATA_PENDING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return dr->attached_dev_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) enum sas_device_type dev_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) enum sas_linkrate linkrate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) u8 sas_addr[SAS_ADDR_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) struct smp_resp *resp = rsp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) struct discover_resp *dr = &resp->disc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) struct sas_ha_struct *ha = dev->port->ha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) struct expander_device *ex = &dev->ex_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) struct ex_phy *phy = &ex->ex_phy[phy_id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) struct sas_rphy *rphy = dev->rphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) bool new_phy = !phy->phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) char *type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (new_phy) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (WARN_ON_ONCE(test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) phy->phy = sas_phy_alloc(&rphy->dev, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) /* FIXME: error_handling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) BUG_ON(!phy->phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) switch (resp->result) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) case SMP_RESP_PHY_VACANT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) phy->phy_state = PHY_VACANT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) phy->phy_state = PHY_NOT_PRESENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) case SMP_RESP_FUNC_ACC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) phy->phy_state = PHY_EMPTY; /* do not know yet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) /* check if anything important changed to squelch debug */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) dev_type = phy->attached_dev_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) linkrate = phy->linkrate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) memcpy(sas_addr, phy->attached_sas_addr, SAS_ADDR_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) /* Handle vacant phy - rest of dr data is not valid so skip it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (phy->phy_state == PHY_VACANT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) phy->attached_dev_type = SAS_PHY_UNUSED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (!test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) phy->phy_id = phy_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) goto skip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) phy->attached_dev_type = to_dev_type(dr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) phy->phy_id = phy_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) phy->linkrate = dr->linkrate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) phy->attached_sata_host = dr->attached_sata_host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) phy->attached_sata_dev = dr->attached_sata_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) phy->attached_sata_ps = dr->attached_sata_ps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) phy->attached_iproto = dr->iproto << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) phy->attached_tproto = dr->tproto << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) /* help some expanders that fail to zero sas_address in the 'no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * device' case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (phy->attached_dev_type == SAS_PHY_UNUSED ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) phy->linkrate < SAS_LINK_RATE_1_5_GBPS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) memcpy(phy->attached_sas_addr, dr->attached_sas_addr, SAS_ADDR_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) phy->attached_phy_id = dr->attached_phy_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) phy->phy_change_count = dr->change_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) phy->routing_attr = dr->routing_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) phy->virtual = dr->virtual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) phy->last_da_index = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) phy->phy->identify.sas_address = SAS_ADDR(phy->attached_sas_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) phy->phy->identify.device_type = dr->attached_dev_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) phy->phy->identify.initiator_port_protocols = phy->attached_iproto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) phy->phy->identify.target_port_protocols = phy->attached_tproto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (!phy->attached_tproto && dr->attached_sata_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) phy->phy->identify.target_port_protocols = SAS_PROTOCOL_SATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) phy->phy->identify.phy_identifier = phy_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) phy->phy->minimum_linkrate_hw = dr->hmin_linkrate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) phy->phy->maximum_linkrate_hw = dr->hmax_linkrate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) phy->phy->minimum_linkrate = dr->pmin_linkrate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) phy->phy->maximum_linkrate = dr->pmax_linkrate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) phy->phy->negotiated_linkrate = phy->linkrate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) phy->phy->enabled = (phy->linkrate != SAS_PHY_DISABLED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) skip:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (new_phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (sas_phy_add(phy->phy)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) sas_phy_free(phy->phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) switch (phy->attached_dev_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) case SAS_SATA_PENDING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) type = "stp pending";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) case SAS_PHY_UNUSED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) type = "no device";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) case SAS_END_DEVICE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (phy->attached_iproto) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (phy->attached_tproto)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) type = "host+target";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) type = "host";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (dr->attached_sata_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) type = "stp";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) type = "ssp";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) case SAS_EDGE_EXPANDER_DEVICE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) case SAS_FANOUT_EXPANDER_DEVICE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) type = "smp";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) type = "unknown";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) /* this routine is polled by libata error recovery so filter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) * unimportant messages
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (new_phy || phy->attached_dev_type != dev_type ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) phy->linkrate != linkrate ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) SAS_ADDR(phy->attached_sas_addr) != SAS_ADDR(sas_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) /* pass */;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) /* if the attached device type changed and ata_eh is active,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) * make sure we run revalidation when eh completes (see:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) * sas_enable_revalidation)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) set_bit(DISCE_REVALIDATE_DOMAIN, &dev->port->disc.pending);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) pr_debug("%sex %016llx phy%02d:%c:%X attached: %016llx (%s)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state) ? "ata: " : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) SAS_ADDR(dev->sas_addr), phy->phy_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) sas_route_char(dev, phy), phy->linkrate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) SAS_ADDR(phy->attached_sas_addr), type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) /* check if we have an existing attached ata device on this expander phy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) struct domain_device *sas_ex_to_ata(struct domain_device *ex_dev, int phy_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) struct ex_phy *ex_phy = &ex_dev->ex_dev.ex_phy[phy_id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) struct domain_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) struct sas_rphy *rphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) if (!ex_phy->port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) rphy = ex_phy->port->rphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (!rphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) dev = sas_find_dev_by_rphy(rphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (dev && dev_is_sata(dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) return dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) #define DISCOVER_REQ_SIZE 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) #define DISCOVER_RESP_SIZE 56
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) static int sas_ex_phy_discover_helper(struct domain_device *dev, u8 *disc_req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) u8 *disc_resp, int single)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) struct discover_resp *dr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) disc_req[9] = single;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) res = smp_execute_task(dev, disc_req, DISCOVER_REQ_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) disc_resp, DISCOVER_RESP_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) dr = &((struct smp_resp *)disc_resp)->disc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) if (memcmp(dev->sas_addr, dr->attached_sas_addr, SAS_ADDR_SIZE) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) pr_notice("Found loopback topology, just ignore it!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) sas_set_ex_phy(dev, single, disc_resp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) int sas_ex_phy_discover(struct domain_device *dev, int single)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) struct expander_device *ex = &dev->ex_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) int res = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) u8 *disc_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) u8 *disc_resp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) disc_req = alloc_smp_req(DISCOVER_REQ_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) if (!disc_req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) disc_resp = alloc_smp_resp(DISCOVER_RESP_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) if (!disc_resp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) kfree(disc_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) disc_req[1] = SMP_DISCOVER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) if (0 <= single && single < ex->num_phys) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) res = sas_ex_phy_discover_helper(dev, disc_req, disc_resp, single);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) for (i = 0; i < ex->num_phys; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) res = sas_ex_phy_discover_helper(dev, disc_req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) disc_resp, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) kfree(disc_resp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) kfree(disc_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) static int sas_expander_discover(struct domain_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) struct expander_device *ex = &dev->ex_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) ex->ex_phy = kcalloc(ex->num_phys, sizeof(*ex->ex_phy), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (!ex->ex_phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) res = sas_ex_phy_discover(dev, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) kfree(ex->ex_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) ex->ex_phy = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) #define MAX_EXPANDER_PHYS 128
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) static void ex_assign_report_general(struct domain_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) struct smp_resp *resp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) struct report_general_resp *rg = &resp->rg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) dev->ex_dev.ex_change_count = be16_to_cpu(rg->change_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) dev->ex_dev.max_route_indexes = be16_to_cpu(rg->route_indexes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) dev->ex_dev.num_phys = min(rg->num_phys, (u8)MAX_EXPANDER_PHYS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) dev->ex_dev.t2t_supp = rg->t2t_supp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) dev->ex_dev.conf_route_table = rg->conf_route_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) dev->ex_dev.configuring = rg->configuring;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) memcpy(dev->ex_dev.enclosure_logical_id, rg->enclosure_logical_id, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) #define RG_REQ_SIZE 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) #define RG_RESP_SIZE 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) static int sas_ex_general(struct domain_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) u8 *rg_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) struct smp_resp *rg_resp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) rg_req = alloc_smp_req(RG_REQ_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) if (!rg_req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) rg_resp = alloc_smp_resp(RG_RESP_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if (!rg_resp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) kfree(rg_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) rg_req[1] = SMP_REPORT_GENERAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) for (i = 0; i < 5; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) res = smp_execute_task(dev, rg_req, RG_REQ_SIZE, rg_resp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) RG_RESP_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) if (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) pr_notice("RG to ex %016llx failed:0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) SAS_ADDR(dev->sas_addr), res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) } else if (rg_resp->result != SMP_RESP_FUNC_ACC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) pr_debug("RG:ex %016llx returned SMP result:0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) SAS_ADDR(dev->sas_addr), rg_resp->result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) res = rg_resp->result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) ex_assign_report_general(dev, rg_resp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) if (dev->ex_dev.configuring) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) pr_debug("RG: ex %016llx self-configuring...\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) SAS_ADDR(dev->sas_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) schedule_timeout_interruptible(5*HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) kfree(rg_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) kfree(rg_resp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) static void ex_assign_manuf_info(struct domain_device *dev, void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) *_mi_resp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) u8 *mi_resp = _mi_resp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) struct sas_rphy *rphy = dev->rphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) struct sas_expander_device *edev = rphy_to_expander_device(rphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) memcpy(edev->vendor_id, mi_resp + 12, SAS_EXPANDER_VENDOR_ID_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) memcpy(edev->product_id, mi_resp + 20, SAS_EXPANDER_PRODUCT_ID_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) memcpy(edev->product_rev, mi_resp + 36,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) SAS_EXPANDER_PRODUCT_REV_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) if (mi_resp[8] & 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) memcpy(edev->component_vendor_id, mi_resp + 40,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) edev->component_id = mi_resp[48] << 8 | mi_resp[49];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) edev->component_revision_id = mi_resp[50];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) #define MI_REQ_SIZE 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) #define MI_RESP_SIZE 64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) static int sas_ex_manuf_info(struct domain_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) u8 *mi_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) u8 *mi_resp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) mi_req = alloc_smp_req(MI_REQ_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) if (!mi_req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) mi_resp = alloc_smp_resp(MI_RESP_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) if (!mi_resp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) kfree(mi_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) mi_req[1] = SMP_REPORT_MANUF_INFO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) res = smp_execute_task(dev, mi_req, MI_REQ_SIZE, mi_resp,MI_RESP_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) if (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) pr_notice("MI: ex %016llx failed:0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) SAS_ADDR(dev->sas_addr), res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) } else if (mi_resp[2] != SMP_RESP_FUNC_ACC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) pr_debug("MI ex %016llx returned SMP result:0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) SAS_ADDR(dev->sas_addr), mi_resp[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) ex_assign_manuf_info(dev, mi_resp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) kfree(mi_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) kfree(mi_resp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) #define PC_REQ_SIZE 44
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) #define PC_RESP_SIZE 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) int sas_smp_phy_control(struct domain_device *dev, int phy_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) enum phy_func phy_func,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) struct sas_phy_linkrates *rates)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) u8 *pc_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) u8 *pc_resp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) pc_req = alloc_smp_req(PC_REQ_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) if (!pc_req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) pc_resp = alloc_smp_resp(PC_RESP_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) if (!pc_resp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) kfree(pc_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) pc_req[1] = SMP_PHY_CONTROL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) pc_req[9] = phy_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) pc_req[10]= phy_func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) if (rates) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) pc_req[32] = rates->minimum_linkrate << 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) pc_req[33] = rates->maximum_linkrate << 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) res = smp_execute_task(dev, pc_req, PC_REQ_SIZE, pc_resp,PC_RESP_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) if (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) pr_err("ex %016llx phy%02d PHY control failed: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) SAS_ADDR(dev->sas_addr), phy_id, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) } else if (pc_resp[2] != SMP_RESP_FUNC_ACC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) pr_err("ex %016llx phy%02d PHY control failed: function result 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) SAS_ADDR(dev->sas_addr), phy_id, pc_resp[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) res = pc_resp[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) kfree(pc_resp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) kfree(pc_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) static void sas_ex_disable_phy(struct domain_device *dev, int phy_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) struct expander_device *ex = &dev->ex_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) struct ex_phy *phy = &ex->ex_phy[phy_id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) sas_smp_phy_control(dev, phy_id, PHY_FUNC_DISABLE, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) phy->linkrate = SAS_PHY_DISABLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) static void sas_ex_disable_port(struct domain_device *dev, u8 *sas_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) struct expander_device *ex = &dev->ex_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) for (i = 0; i < ex->num_phys; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) struct ex_phy *phy = &ex->ex_phy[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) if (phy->phy_state == PHY_VACANT ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) phy->phy_state == PHY_NOT_PRESENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) if (SAS_ADDR(phy->attached_sas_addr) == SAS_ADDR(sas_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) sas_ex_disable_phy(dev, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) static int sas_dev_present_in_domain(struct asd_sas_port *port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) u8 *sas_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) struct domain_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) if (SAS_ADDR(port->sas_addr) == SAS_ADDR(sas_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) list_for_each_entry(dev, &port->dev_list, dev_list_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) if (SAS_ADDR(dev->sas_addr) == SAS_ADDR(sas_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) #define RPEL_REQ_SIZE 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) #define RPEL_RESP_SIZE 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) int sas_smp_get_phy_events(struct sas_phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) u8 *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) u8 *resp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) struct sas_rphy *rphy = dev_to_rphy(phy->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) struct domain_device *dev = sas_find_dev_by_rphy(rphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) req = alloc_smp_req(RPEL_REQ_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) if (!req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) resp = alloc_smp_resp(RPEL_RESP_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) if (!resp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) kfree(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) req[1] = SMP_REPORT_PHY_ERR_LOG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) req[9] = phy->number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) res = smp_execute_task(dev, req, RPEL_REQ_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) resp, RPEL_RESP_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) phy->invalid_dword_count = get_unaligned_be32(&resp[12]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) phy->running_disparity_error_count = get_unaligned_be32(&resp[16]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) phy->loss_of_dword_sync_count = get_unaligned_be32(&resp[20]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) phy->phy_reset_problem_count = get_unaligned_be32(&resp[24]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) kfree(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) kfree(resp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) #ifdef CONFIG_SCSI_SAS_ATA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) #define RPS_REQ_SIZE 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) #define RPS_RESP_SIZE 60
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) int sas_get_report_phy_sata(struct domain_device *dev, int phy_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) struct smp_resp *rps_resp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) u8 *rps_req = alloc_smp_req(RPS_REQ_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) u8 *resp = (u8 *)rps_resp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) if (!rps_req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) rps_req[1] = SMP_REPORT_PHY_SATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) rps_req[9] = phy_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) res = smp_execute_task(dev, rps_req, RPS_REQ_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) rps_resp, RPS_RESP_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) /* 0x34 is the FIS type for the D2H fis. There's a potential
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) * standards cockup here. sas-2 explicitly specifies the FIS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) * should be encoded so that FIS type is in resp[24].
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) * However, some expanders endian reverse this. Undo the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) * reversal here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) if (!res && resp[27] == 0x34 && resp[24] != 0x34) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) for (i = 0; i < 5; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) int j = 24 + (i*4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) u8 a, b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) a = resp[j + 0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) b = resp[j + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) resp[j + 0] = resp[j + 3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) resp[j + 1] = resp[j + 2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) resp[j + 2] = b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) resp[j + 3] = a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) kfree(rps_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) static void sas_ex_get_linkrate(struct domain_device *parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) struct domain_device *child,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) struct ex_phy *parent_phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) struct expander_device *parent_ex = &parent->ex_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) struct sas_port *port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) child->pathways = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) port = parent_phy->port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) for (i = 0; i < parent_ex->num_phys; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) struct ex_phy *phy = &parent_ex->ex_phy[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) if (phy->phy_state == PHY_VACANT ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) phy->phy_state == PHY_NOT_PRESENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) if (SAS_ADDR(phy->attached_sas_addr) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) SAS_ADDR(child->sas_addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) child->min_linkrate = min(parent->min_linkrate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) phy->linkrate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) child->max_linkrate = max(parent->max_linkrate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) phy->linkrate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) child->pathways++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) sas_port_add_phy(port, phy->phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) child->linkrate = min(parent_phy->linkrate, child->max_linkrate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) child->pathways = min(child->pathways, parent->pathways);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) static struct domain_device *sas_ex_discover_end_dev(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) struct domain_device *parent, int phy_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) struct expander_device *parent_ex = &parent->ex_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) struct ex_phy *phy = &parent_ex->ex_phy[phy_id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) struct domain_device *child = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) struct sas_rphy *rphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) if (phy->attached_sata_host || phy->attached_sata_ps)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) child = sas_alloc_device();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) if (!child)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) kref_get(&parent->kref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) child->parent = parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) child->port = parent->port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) child->iproto = phy->attached_iproto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) memcpy(child->sas_addr, phy->attached_sas_addr, SAS_ADDR_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) sas_hash_addr(child->hashed_sas_addr, child->sas_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) if (!phy->port) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) phy->port = sas_port_alloc(&parent->rphy->dev, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) if (unlikely(!phy->port))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) if (unlikely(sas_port_add(phy->port) != 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) sas_port_free(phy->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) sas_ex_get_linkrate(parent, child, phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) sas_device_set_phy(child, phy->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) #ifdef CONFIG_SCSI_SAS_ATA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) if ((phy->attached_tproto & SAS_PROTOCOL_STP) || phy->attached_sata_dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) if (child->linkrate > parent->min_linkrate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) struct sas_phy *cphy = child->phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) enum sas_linkrate min_prate = cphy->minimum_linkrate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) parent_min_lrate = parent->min_linkrate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) min_linkrate = (min_prate > parent_min_lrate) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) parent_min_lrate : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) struct sas_phy_linkrates rates = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) .maximum_linkrate = parent->min_linkrate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) .minimum_linkrate = min_linkrate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) pr_notice("ex %016llx phy%02d SATA device linkrate > min pathway connection rate, attempting to lower device linkrate\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) SAS_ADDR(child->sas_addr), phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) ret = sas_smp_phy_control(parent, phy_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) PHY_FUNC_LINK_RESET, &rates);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) pr_err("ex %016llx phy%02d SATA device could not set linkrate (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) SAS_ADDR(child->sas_addr), phy_id, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) pr_notice("ex %016llx phy%02d SATA device set linkrate successfully\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) SAS_ADDR(child->sas_addr), phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) child->linkrate = child->min_linkrate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) res = sas_get_ata_info(child, phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) sas_init_dev(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) res = sas_ata_init(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) rphy = sas_end_device_alloc(phy->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) if (!rphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) rphy->identify.phy_identifier = phy_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) child->rphy = rphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) get_device(&rphy->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) list_add_tail(&child->disco_list_node, &parent->port->disco_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) res = sas_discover_sata(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) if (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) pr_notice("sas_discover_sata() for device %16llx at %016llx:%02d returned 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) SAS_ADDR(child->sas_addr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) SAS_ADDR(parent->sas_addr), phy_id, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) goto out_list_del;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) if (phy->attached_tproto & SAS_PROTOCOL_SSP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) child->dev_type = SAS_END_DEVICE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) rphy = sas_end_device_alloc(phy->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) /* FIXME: error handling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) if (unlikely(!rphy))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) child->tproto = phy->attached_tproto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) sas_init_dev(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) child->rphy = rphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) get_device(&rphy->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) rphy->identify.phy_identifier = phy_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) sas_fill_in_rphy(child, rphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) list_add_tail(&child->disco_list_node, &parent->port->disco_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) res = sas_discover_end_dev(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) if (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) pr_notice("sas_discover_end_dev() for device %016llx at %016llx:%02d returned 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) SAS_ADDR(child->sas_addr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) SAS_ADDR(parent->sas_addr), phy_id, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) goto out_list_del;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) pr_notice("target proto 0x%x at %016llx:0x%x not handled\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) phy->attached_tproto, SAS_ADDR(parent->sas_addr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) list_add_tail(&child->siblings, &parent_ex->children);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) return child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) out_list_del:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) sas_rphy_free(child->rphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) list_del(&child->disco_list_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) spin_lock_irq(&parent->port->dev_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) list_del(&child->dev_list_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) spin_unlock_irq(&parent->port->dev_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) sas_port_delete(phy->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) phy->port = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) sas_put_device(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) /* See if this phy is part of a wide port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) static bool sas_ex_join_wide_port(struct domain_device *parent, int phy_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) struct ex_phy *phy = &parent->ex_dev.ex_phy[phy_id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) for (i = 0; i < parent->ex_dev.num_phys; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) struct ex_phy *ephy = &parent->ex_dev.ex_phy[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) if (ephy == phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) if (!memcmp(phy->attached_sas_addr, ephy->attached_sas_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) SAS_ADDR_SIZE) && ephy->port) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) sas_port_add_phy(ephy->port, phy->phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) phy->port = ephy->port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) phy->phy_state = PHY_DEVICE_DISCOVERED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) static struct domain_device *sas_ex_discover_expander(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) struct domain_device *parent, int phy_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) struct sas_expander_device *parent_ex = rphy_to_expander_device(parent->rphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) struct ex_phy *phy = &parent->ex_dev.ex_phy[phy_id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) struct domain_device *child = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) struct sas_rphy *rphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) struct sas_expander_device *edev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) struct asd_sas_port *port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) if (phy->routing_attr == DIRECT_ROUTING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) pr_warn("ex %016llx:%02d:D <--> ex %016llx:0x%x is not allowed\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) SAS_ADDR(parent->sas_addr), phy_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) SAS_ADDR(phy->attached_sas_addr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) phy->attached_phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) child = sas_alloc_device();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) if (!child)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) phy->port = sas_port_alloc(&parent->rphy->dev, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) /* FIXME: better error handling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) BUG_ON(sas_port_add(phy->port) != 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) switch (phy->attached_dev_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) case SAS_EDGE_EXPANDER_DEVICE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) rphy = sas_expander_alloc(phy->port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) SAS_EDGE_EXPANDER_DEVICE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) case SAS_FANOUT_EXPANDER_DEVICE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) rphy = sas_expander_alloc(phy->port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) SAS_FANOUT_EXPANDER_DEVICE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) rphy = NULL; /* shut gcc up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) port = parent->port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) child->rphy = rphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) get_device(&rphy->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) edev = rphy_to_expander_device(rphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) child->dev_type = phy->attached_dev_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) kref_get(&parent->kref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) child->parent = parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) child->port = port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) child->iproto = phy->attached_iproto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) child->tproto = phy->attached_tproto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) memcpy(child->sas_addr, phy->attached_sas_addr, SAS_ADDR_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) sas_hash_addr(child->hashed_sas_addr, child->sas_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) sas_ex_get_linkrate(parent, child, phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) edev->level = parent_ex->level + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) parent->port->disc.max_level = max(parent->port->disc.max_level,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) edev->level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) sas_init_dev(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) sas_fill_in_rphy(child, rphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) sas_rphy_add(rphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) spin_lock_irq(&parent->port->dev_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) list_add_tail(&child->dev_list_node, &parent->port->dev_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) spin_unlock_irq(&parent->port->dev_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) res = sas_discover_expander(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) if (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) sas_rphy_delete(rphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) spin_lock_irq(&parent->port->dev_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) list_del(&child->dev_list_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) spin_unlock_irq(&parent->port->dev_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) sas_put_device(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) sas_port_delete(phy->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) phy->port = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) list_add_tail(&child->siblings, &parent->ex_dev.children);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) return child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) static int sas_ex_discover_dev(struct domain_device *dev, int phy_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) struct expander_device *ex = &dev->ex_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) struct ex_phy *ex_phy = &ex->ex_phy[phy_id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) struct domain_device *child = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) int res = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) /* Phy state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) if (ex_phy->linkrate == SAS_SATA_SPINUP_HOLD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) if (!sas_smp_phy_control(dev, phy_id, PHY_FUNC_LINK_RESET, NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) res = sas_ex_phy_discover(dev, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) /* Parent and domain coherency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) if (!dev->parent && (SAS_ADDR(ex_phy->attached_sas_addr) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) SAS_ADDR(dev->port->sas_addr))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) sas_add_parent_port(dev, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) if (dev->parent && (SAS_ADDR(ex_phy->attached_sas_addr) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) SAS_ADDR(dev->parent->sas_addr))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) sas_add_parent_port(dev, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) if (ex_phy->routing_attr == TABLE_ROUTING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) sas_configure_phy(dev, phy_id, dev->port->sas_addr, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) if (sas_dev_present_in_domain(dev->port, ex_phy->attached_sas_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) sas_ex_disable_port(dev, ex_phy->attached_sas_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) if (ex_phy->attached_dev_type == SAS_PHY_UNUSED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) if (ex_phy->routing_attr == DIRECT_ROUTING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) memset(ex_phy->attached_sas_addr, 0, SAS_ADDR_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) sas_configure_routing(dev, ex_phy->attached_sas_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) } else if (ex_phy->linkrate == SAS_LINK_RATE_UNKNOWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) if (ex_phy->attached_dev_type != SAS_END_DEVICE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) ex_phy->attached_dev_type != SAS_FANOUT_EXPANDER_DEVICE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) ex_phy->attached_dev_type != SAS_EDGE_EXPANDER_DEVICE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) ex_phy->attached_dev_type != SAS_SATA_PENDING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) pr_warn("unknown device type(0x%x) attached to ex %016llx phy%02d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) ex_phy->attached_dev_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) SAS_ADDR(dev->sas_addr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) res = sas_configure_routing(dev, ex_phy->attached_sas_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) if (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) pr_notice("configure routing for dev %016llx reported 0x%x. Forgotten\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) SAS_ADDR(ex_phy->attached_sas_addr), res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) sas_disable_routing(dev, ex_phy->attached_sas_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) if (sas_ex_join_wide_port(dev, phy_id)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) pr_debug("Attaching ex phy%02d to wide port %016llx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) phy_id, SAS_ADDR(ex_phy->attached_sas_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) switch (ex_phy->attached_dev_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) case SAS_END_DEVICE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) case SAS_SATA_PENDING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) child = sas_ex_discover_end_dev(dev, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) case SAS_FANOUT_EXPANDER_DEVICE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) if (SAS_ADDR(dev->port->disc.fanout_sas_addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) pr_debug("second fanout expander %016llx phy%02d attached to ex %016llx phy%02d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) SAS_ADDR(ex_phy->attached_sas_addr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) ex_phy->attached_phy_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) SAS_ADDR(dev->sas_addr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) sas_ex_disable_phy(dev, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) memcpy(dev->port->disc.fanout_sas_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) ex_phy->attached_sas_addr, SAS_ADDR_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) case SAS_EDGE_EXPANDER_DEVICE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) child = sas_ex_discover_expander(dev, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) if (!child)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) pr_notice("ex %016llx phy%02d failed to discover\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) SAS_ADDR(dev->sas_addr), phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) static int sas_find_sub_addr(struct domain_device *dev, u8 *sub_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) struct expander_device *ex = &dev->ex_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) for (i = 0; i < ex->num_phys; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) struct ex_phy *phy = &ex->ex_phy[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) if (phy->phy_state == PHY_VACANT ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) phy->phy_state == PHY_NOT_PRESENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) if (dev_is_expander(phy->attached_dev_type) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) phy->routing_attr == SUBTRACTIVE_ROUTING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) memcpy(sub_addr, phy->attached_sas_addr, SAS_ADDR_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) static int sas_check_level_subtractive_boundary(struct domain_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) struct expander_device *ex = &dev->ex_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) struct domain_device *child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) u8 sub_addr[SAS_ADDR_SIZE] = {0, };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) list_for_each_entry(child, &ex->children, siblings) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) if (!dev_is_expander(child->dev_type))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) if (sub_addr[0] == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) sas_find_sub_addr(child, sub_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) u8 s2[SAS_ADDR_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) if (sas_find_sub_addr(child, s2) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) (SAS_ADDR(sub_addr) != SAS_ADDR(s2))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) pr_notice("ex %016llx->%016llx-?->%016llx diverges from subtractive boundary %016llx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) SAS_ADDR(dev->sas_addr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) SAS_ADDR(child->sas_addr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) SAS_ADDR(s2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) SAS_ADDR(sub_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) sas_ex_disable_port(child, s2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) * sas_ex_discover_devices - discover devices attached to this expander
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) * @dev: pointer to the expander domain device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) * @single: if you want to do a single phy, else set to -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) * Configure this expander for use with its devices and register the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) * devices of this expander.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) static int sas_ex_discover_devices(struct domain_device *dev, int single)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) struct expander_device *ex = &dev->ex_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) int i = 0, end = ex->num_phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) int res = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) if (0 <= single && single < end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) i = single;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) end = i+1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) for ( ; i < end; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) struct ex_phy *ex_phy = &ex->ex_phy[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) if (ex_phy->phy_state == PHY_VACANT ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) ex_phy->phy_state == PHY_NOT_PRESENT ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) ex_phy->phy_state == PHY_DEVICE_DISCOVERED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) switch (ex_phy->linkrate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) case SAS_PHY_DISABLED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) case SAS_PHY_RESET_PROBLEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) case SAS_SATA_PORT_SELECTOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) res = sas_ex_discover_dev(dev, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) if (!res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) sas_check_level_subtractive_boundary(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) static int sas_check_ex_subtractive_boundary(struct domain_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) struct expander_device *ex = &dev->ex_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) u8 *sub_sas_addr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) if (dev->dev_type != SAS_EDGE_EXPANDER_DEVICE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) for (i = 0; i < ex->num_phys; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) struct ex_phy *phy = &ex->ex_phy[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) if (phy->phy_state == PHY_VACANT ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) phy->phy_state == PHY_NOT_PRESENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) if (dev_is_expander(phy->attached_dev_type) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) phy->routing_attr == SUBTRACTIVE_ROUTING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) if (!sub_sas_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) sub_sas_addr = &phy->attached_sas_addr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) else if (SAS_ADDR(sub_sas_addr) !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) SAS_ADDR(phy->attached_sas_addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) pr_notice("ex %016llx phy%02d diverges(%016llx) on subtractive boundary(%016llx). Disabled\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) SAS_ADDR(dev->sas_addr), i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) SAS_ADDR(phy->attached_sas_addr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) SAS_ADDR(sub_sas_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) sas_ex_disable_phy(dev, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) static void sas_print_parent_topology_bug(struct domain_device *child,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) struct ex_phy *parent_phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) struct ex_phy *child_phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) static const char *ex_type[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) [SAS_EDGE_EXPANDER_DEVICE] = "edge",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) [SAS_FANOUT_EXPANDER_DEVICE] = "fanout",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) struct domain_device *parent = child->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) pr_notice("%s ex %016llx phy%02d <--> %s ex %016llx phy%02d has %c:%c routing link!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) ex_type[parent->dev_type],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) SAS_ADDR(parent->sas_addr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) parent_phy->phy_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) ex_type[child->dev_type],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) SAS_ADDR(child->sas_addr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) child_phy->phy_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) sas_route_char(parent, parent_phy),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) sas_route_char(child, child_phy));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) static int sas_check_eeds(struct domain_device *child,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) struct ex_phy *parent_phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) struct ex_phy *child_phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) int res = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) struct domain_device *parent = child->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) if (SAS_ADDR(parent->port->disc.fanout_sas_addr) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) res = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) pr_warn("edge ex %016llx phy S:%02d <--> edge ex %016llx phy S:%02d, while there is a fanout ex %016llx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) SAS_ADDR(parent->sas_addr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) parent_phy->phy_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) SAS_ADDR(child->sas_addr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) child_phy->phy_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) SAS_ADDR(parent->port->disc.fanout_sas_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) } else if (SAS_ADDR(parent->port->disc.eeds_a) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) memcpy(parent->port->disc.eeds_a, parent->sas_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) SAS_ADDR_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) memcpy(parent->port->disc.eeds_b, child->sas_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) SAS_ADDR_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) } else if (((SAS_ADDR(parent->port->disc.eeds_a) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) SAS_ADDR(parent->sas_addr)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) (SAS_ADDR(parent->port->disc.eeds_a) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) SAS_ADDR(child->sas_addr)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) ((SAS_ADDR(parent->port->disc.eeds_b) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) SAS_ADDR(parent->sas_addr)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) (SAS_ADDR(parent->port->disc.eeds_b) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) SAS_ADDR(child->sas_addr))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) res = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) pr_warn("edge ex %016llx phy%02d <--> edge ex %016llx phy%02d link forms a third EEDS!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) SAS_ADDR(parent->sas_addr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) parent_phy->phy_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) SAS_ADDR(child->sas_addr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) child_phy->phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) /* Here we spill over 80 columns. It is intentional.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) static int sas_check_parent_topology(struct domain_device *child)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) struct expander_device *child_ex = &child->ex_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) struct expander_device *parent_ex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) int res = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) if (!child->parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) if (!dev_is_expander(child->parent->dev_type))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) parent_ex = &child->parent->ex_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) for (i = 0; i < parent_ex->num_phys; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) struct ex_phy *parent_phy = &parent_ex->ex_phy[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) struct ex_phy *child_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) if (parent_phy->phy_state == PHY_VACANT ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) parent_phy->phy_state == PHY_NOT_PRESENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) if (SAS_ADDR(parent_phy->attached_sas_addr) != SAS_ADDR(child->sas_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) child_phy = &child_ex->ex_phy[parent_phy->attached_phy_id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) switch (child->parent->dev_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) case SAS_EDGE_EXPANDER_DEVICE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) if (child->dev_type == SAS_FANOUT_EXPANDER_DEVICE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) if (parent_phy->routing_attr != SUBTRACTIVE_ROUTING ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) child_phy->routing_attr != TABLE_ROUTING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) sas_print_parent_topology_bug(child, parent_phy, child_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) res = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) } else if (parent_phy->routing_attr == SUBTRACTIVE_ROUTING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) if (child_phy->routing_attr == SUBTRACTIVE_ROUTING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) res = sas_check_eeds(child, parent_phy, child_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) } else if (child_phy->routing_attr != TABLE_ROUTING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) sas_print_parent_topology_bug(child, parent_phy, child_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) res = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) } else if (parent_phy->routing_attr == TABLE_ROUTING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) if (child_phy->routing_attr == SUBTRACTIVE_ROUTING ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) (child_phy->routing_attr == TABLE_ROUTING &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) child_ex->t2t_supp && parent_ex->t2t_supp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) /* All good */;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) sas_print_parent_topology_bug(child, parent_phy, child_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) res = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) case SAS_FANOUT_EXPANDER_DEVICE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) if (parent_phy->routing_attr != TABLE_ROUTING ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) child_phy->routing_attr != SUBTRACTIVE_ROUTING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) sas_print_parent_topology_bug(child, parent_phy, child_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) res = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) #define RRI_REQ_SIZE 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) #define RRI_RESP_SIZE 44
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) static int sas_configure_present(struct domain_device *dev, int phy_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) u8 *sas_addr, int *index, int *present)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) int i, res = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) struct expander_device *ex = &dev->ex_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) struct ex_phy *phy = &ex->ex_phy[phy_id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) u8 *rri_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) u8 *rri_resp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) *present = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) *index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) rri_req = alloc_smp_req(RRI_REQ_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) if (!rri_req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) rri_resp = alloc_smp_resp(RRI_RESP_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) if (!rri_resp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) kfree(rri_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) rri_req[1] = SMP_REPORT_ROUTE_INFO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) rri_req[9] = phy_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) for (i = 0; i < ex->max_route_indexes ; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) *(__be16 *)(rri_req+6) = cpu_to_be16(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) res = smp_execute_task(dev, rri_req, RRI_REQ_SIZE, rri_resp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) RRI_RESP_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) res = rri_resp[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) if (res == SMP_RESP_NO_INDEX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) pr_warn("overflow of indexes: dev %016llx phy%02d index 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) SAS_ADDR(dev->sas_addr), phy_id, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) } else if (res != SMP_RESP_FUNC_ACC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) pr_notice("%s: dev %016llx phy%02d index 0x%x result 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) __func__, SAS_ADDR(dev->sas_addr), phy_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) i, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) if (SAS_ADDR(sas_addr) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) if (SAS_ADDR(rri_resp+16) == SAS_ADDR(sas_addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) *index = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) if ((rri_resp[12] & 0x80) == 0x80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) *present = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) *present = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) } else if (SAS_ADDR(rri_resp+16) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) *index = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) *present = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) } else if (SAS_ADDR(rri_resp+16) == 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) phy->last_da_index < i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) phy->last_da_index = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) *index = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) *present = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) res = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) kfree(rri_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) kfree(rri_resp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) #define CRI_REQ_SIZE 44
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) #define CRI_RESP_SIZE 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) static int sas_configure_set(struct domain_device *dev, int phy_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) u8 *sas_addr, int index, int include)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) u8 *cri_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) u8 *cri_resp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) cri_req = alloc_smp_req(CRI_REQ_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) if (!cri_req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) cri_resp = alloc_smp_resp(CRI_RESP_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) if (!cri_resp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) kfree(cri_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) cri_req[1] = SMP_CONF_ROUTE_INFO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) *(__be16 *)(cri_req+6) = cpu_to_be16(index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) cri_req[9] = phy_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) if (SAS_ADDR(sas_addr) == 0 || !include)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) cri_req[12] |= 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) memcpy(cri_req+16, sas_addr, SAS_ADDR_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) res = smp_execute_task(dev, cri_req, CRI_REQ_SIZE, cri_resp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) CRI_RESP_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) res = cri_resp[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) if (res == SMP_RESP_NO_INDEX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) pr_warn("overflow of indexes: dev %016llx phy%02d index 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) SAS_ADDR(dev->sas_addr), phy_id, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) kfree(cri_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) kfree(cri_resp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) static int sas_configure_phy(struct domain_device *dev, int phy_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) u8 *sas_addr, int include)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) int present;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) res = sas_configure_present(dev, phy_id, sas_addr, &index, &present);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) if (include ^ present)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) return sas_configure_set(dev, phy_id, sas_addr, index,include);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) * sas_configure_parent - configure routing table of parent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) * @parent: parent expander
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) * @child: child expander
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) * @sas_addr: SAS port identifier of device directly attached to child
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) * @include: whether or not to include @child in the expander routing table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) static int sas_configure_parent(struct domain_device *parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) struct domain_device *child,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) u8 *sas_addr, int include)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) struct expander_device *ex_parent = &parent->ex_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) int res = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) if (parent->parent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) res = sas_configure_parent(parent->parent, parent, sas_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) include);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) if (ex_parent->conf_route_table == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) pr_debug("ex %016llx has self-configuring routing table\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) SAS_ADDR(parent->sas_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) for (i = 0; i < ex_parent->num_phys; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) struct ex_phy *phy = &ex_parent->ex_phy[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) if ((phy->routing_attr == TABLE_ROUTING) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) (SAS_ADDR(phy->attached_sas_addr) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) SAS_ADDR(child->sas_addr))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) res = sas_configure_phy(parent, i, sas_addr, include);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) * sas_configure_routing - configure routing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) * @dev: expander device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) * @sas_addr: port identifier of device directly attached to the expander device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) static int sas_configure_routing(struct domain_device *dev, u8 *sas_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) if (dev->parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) return sas_configure_parent(dev->parent, dev, sas_addr, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) static int sas_disable_routing(struct domain_device *dev, u8 *sas_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) if (dev->parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) return sas_configure_parent(dev->parent, dev, sas_addr, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) * sas_discover_expander - expander discovery
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) * @dev: pointer to expander domain device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) * See comment in sas_discover_sata().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) static int sas_discover_expander(struct domain_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) res = sas_notify_lldd_dev_found(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) res = sas_ex_general(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) res = sas_ex_manuf_info(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) res = sas_expander_discover(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) if (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) pr_warn("expander %016llx discovery failed(0x%x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) SAS_ADDR(dev->sas_addr), res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) sas_check_ex_subtractive_boundary(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) res = sas_check_parent_topology(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) sas_notify_lldd_dev_gone(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) static int sas_ex_level_discovery(struct asd_sas_port *port, const int level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) int res = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) struct domain_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) list_for_each_entry(dev, &port->dev_list, dev_list_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) if (dev_is_expander(dev->dev_type)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) struct sas_expander_device *ex =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) rphy_to_expander_device(dev->rphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) if (level == ex->level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) res = sas_ex_discover_devices(dev, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) else if (level > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) res = sas_ex_discover_devices(port->port_dev, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) static int sas_ex_bfs_disc(struct asd_sas_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) int level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) level = port->disc.max_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) res = sas_ex_level_discovery(port, level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) } while (level < port->disc.max_level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) int sas_discover_root_expander(struct domain_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) struct sas_expander_device *ex = rphy_to_expander_device(dev->rphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) res = sas_rphy_add(dev->rphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) ex->level = dev->port->disc.max_level; /* 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) res = sas_discover_expander(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) goto out_err2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) sas_ex_bfs_disc(dev->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) out_err2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) sas_rphy_remove(dev->rphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) /* ---------- Domain revalidation ---------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) static int sas_get_phy_discover(struct domain_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) int phy_id, struct smp_resp *disc_resp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) u8 *disc_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) disc_req = alloc_smp_req(DISCOVER_REQ_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) if (!disc_req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) disc_req[1] = SMP_DISCOVER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) disc_req[9] = phy_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) res = smp_execute_task(dev, disc_req, DISCOVER_REQ_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) disc_resp, DISCOVER_RESP_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) else if (disc_resp->result != SMP_RESP_FUNC_ACC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) res = disc_resp->result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) kfree(disc_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) static int sas_get_phy_change_count(struct domain_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) int phy_id, int *pcc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) struct smp_resp *disc_resp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) disc_resp = alloc_smp_resp(DISCOVER_RESP_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) if (!disc_resp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) res = sas_get_phy_discover(dev, phy_id, disc_resp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) if (!res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) *pcc = disc_resp->disc.change_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) kfree(disc_resp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) static int sas_get_phy_attached_dev(struct domain_device *dev, int phy_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) u8 *sas_addr, enum sas_device_type *type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) struct smp_resp *disc_resp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) struct discover_resp *dr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) disc_resp = alloc_smp_resp(DISCOVER_RESP_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) if (!disc_resp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) dr = &disc_resp->disc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) res = sas_get_phy_discover(dev, phy_id, disc_resp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) if (res == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) memcpy(sas_addr, disc_resp->disc.attached_sas_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) SAS_ADDR_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) *type = to_dev_type(dr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) if (*type == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) memset(sas_addr, 0, SAS_ADDR_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) kfree(disc_resp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) static int sas_find_bcast_phy(struct domain_device *dev, int *phy_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) int from_phy, bool update)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) struct expander_device *ex = &dev->ex_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) int res = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) for (i = from_phy; i < ex->num_phys; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) int phy_change_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) res = sas_get_phy_change_count(dev, i, &phy_change_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) switch (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) case SMP_RESP_PHY_VACANT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) case SMP_RESP_NO_PHY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) case SMP_RESP_FUNC_ACC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) if (phy_change_count != ex->ex_phy[i].phy_change_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) if (update)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) ex->ex_phy[i].phy_change_count =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) phy_change_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) *phy_id = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) static int sas_get_ex_change_count(struct domain_device *dev, int *ecc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) u8 *rg_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) struct smp_resp *rg_resp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) rg_req = alloc_smp_req(RG_REQ_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) if (!rg_req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) rg_resp = alloc_smp_resp(RG_RESP_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) if (!rg_resp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) kfree(rg_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) rg_req[1] = SMP_REPORT_GENERAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) res = smp_execute_task(dev, rg_req, RG_REQ_SIZE, rg_resp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) RG_RESP_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) if (rg_resp->result != SMP_RESP_FUNC_ACC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) res = rg_resp->result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) *ecc = be16_to_cpu(rg_resp->rg.change_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) kfree(rg_resp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) kfree(rg_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) * sas_find_bcast_dev - find the device issue BROADCAST(CHANGE).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) * @dev:domain device to be detect.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) * @src_dev: the device which originated BROADCAST(CHANGE).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) * Add self-configuration expander support. Suppose two expander cascading,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) * when the first level expander is self-configuring, hotplug the disks in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) * second level expander, BROADCAST(CHANGE) will not only be originated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) * in the second level expander, but also be originated in the first level
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) * expander (see SAS protocol SAS 2r-14, 7.11 for detail), it is to say,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) * expander changed count in two level expanders will all increment at least
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) * once, but the phy which chang count has changed is the source device which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) * we concerned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) static int sas_find_bcast_dev(struct domain_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) struct domain_device **src_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) struct expander_device *ex = &dev->ex_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) int ex_change_count = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) int phy_id = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) struct domain_device *ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) res = sas_get_ex_change_count(dev, &ex_change_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) if (ex_change_count != -1 && ex_change_count != ex->ex_change_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) /* Just detect if this expander phys phy change count changed,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) * in order to determine if this expander originate BROADCAST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) * and do not update phy change count field in our structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) res = sas_find_bcast_phy(dev, &phy_id, 0, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) if (phy_id != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) *src_dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) ex->ex_change_count = ex_change_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) pr_info("ex %016llx phy%02d change count has changed\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) SAS_ADDR(dev->sas_addr), phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) pr_info("ex %016llx phys DID NOT change\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) SAS_ADDR(dev->sas_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) list_for_each_entry(ch, &ex->children, siblings) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) if (dev_is_expander(ch->dev_type)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) res = sas_find_bcast_dev(ch, src_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) if (*src_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) static void sas_unregister_ex_tree(struct asd_sas_port *port, struct domain_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) struct expander_device *ex = &dev->ex_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) struct domain_device *child, *n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) list_for_each_entry_safe(child, n, &ex->children, siblings) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) set_bit(SAS_DEV_GONE, &child->state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) if (dev_is_expander(child->dev_type))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) sas_unregister_ex_tree(port, child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) sas_unregister_dev(port, child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) sas_unregister_dev(port, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) static void sas_unregister_devs_sas_addr(struct domain_device *parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) int phy_id, bool last)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) struct expander_device *ex_dev = &parent->ex_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) struct ex_phy *phy = &ex_dev->ex_phy[phy_id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) struct domain_device *child, *n, *found = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) if (last) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) list_for_each_entry_safe(child, n,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) &ex_dev->children, siblings) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) if (SAS_ADDR(child->sas_addr) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) SAS_ADDR(phy->attached_sas_addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) set_bit(SAS_DEV_GONE, &child->state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) if (dev_is_expander(child->dev_type))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) sas_unregister_ex_tree(parent->port, child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) sas_unregister_dev(parent->port, child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) found = child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) sas_disable_routing(parent, phy->attached_sas_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) if (phy->port) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) sas_port_delete_phy(phy->port, phy->phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) sas_device_set_phy(found, phy->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) if (phy->port->num_phys == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) list_add_tail(&phy->port->del_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) &parent->port->sas_port_del_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) phy->port = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) static int sas_discover_bfs_by_root_level(struct domain_device *root,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) const int level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) struct expander_device *ex_root = &root->ex_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) struct domain_device *child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) int res = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) list_for_each_entry(child, &ex_root->children, siblings) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) if (dev_is_expander(child->dev_type)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) struct sas_expander_device *ex =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) rphy_to_expander_device(child->rphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) if (level > ex->level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) res = sas_discover_bfs_by_root_level(child,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) else if (level == ex->level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) res = sas_ex_discover_devices(child, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) static int sas_discover_bfs_by_root(struct domain_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) struct sas_expander_device *ex = rphy_to_expander_device(dev->rphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) int level = ex->level+1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) res = sas_ex_discover_devices(dev, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) res = sas_discover_bfs_by_root_level(dev, level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) level += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) } while (level <= dev->port->disc.max_level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) static int sas_discover_new(struct domain_device *dev, int phy_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) struct ex_phy *ex_phy = &dev->ex_dev.ex_phy[phy_id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) struct domain_device *child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) pr_debug("ex %016llx phy%02d new device attached\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) SAS_ADDR(dev->sas_addr), phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) res = sas_ex_phy_discover(dev, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) if (sas_ex_join_wide_port(dev, phy_id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) res = sas_ex_discover_devices(dev, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) list_for_each_entry(child, &dev->ex_dev.children, siblings) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) if (SAS_ADDR(child->sas_addr) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) SAS_ADDR(ex_phy->attached_sas_addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) if (dev_is_expander(child->dev_type))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) res = sas_discover_bfs_by_root(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) static bool dev_type_flutter(enum sas_device_type new, enum sas_device_type old)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) if (old == new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) /* treat device directed resets as flutter, if we went
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) * SAS_END_DEVICE to SAS_SATA_PENDING the link needs recovery
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) if ((old == SAS_SATA_PENDING && new == SAS_END_DEVICE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) (old == SAS_END_DEVICE && new == SAS_SATA_PENDING))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) static int sas_rediscover_dev(struct domain_device *dev, int phy_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) bool last, int sibling)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) struct expander_device *ex = &dev->ex_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) struct ex_phy *phy = &ex->ex_phy[phy_id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) enum sas_device_type type = SAS_PHY_UNUSED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) u8 sas_addr[SAS_ADDR_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) char msg[80] = "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) if (!last)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) sprintf(msg, ", part of a wide port with phy%02d", sibling);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) pr_debug("ex %016llx rediscovering phy%02d%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) SAS_ADDR(dev->sas_addr), phy_id, msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) memset(sas_addr, 0, SAS_ADDR_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) res = sas_get_phy_attached_dev(dev, phy_id, sas_addr, &type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) switch (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) case SMP_RESP_NO_PHY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) phy->phy_state = PHY_NOT_PRESENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) sas_unregister_devs_sas_addr(dev, phy_id, last);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) case SMP_RESP_PHY_VACANT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) phy->phy_state = PHY_VACANT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) sas_unregister_devs_sas_addr(dev, phy_id, last);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) case SMP_RESP_FUNC_ACC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) case -ECOMM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) if ((SAS_ADDR(sas_addr) == 0) || (res == -ECOMM)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) phy->phy_state = PHY_EMPTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) sas_unregister_devs_sas_addr(dev, phy_id, last);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) * Even though the PHY is empty, for convenience we discover
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) * the PHY to update the PHY info, like negotiated linkrate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) sas_ex_phy_discover(dev, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) } else if (SAS_ADDR(sas_addr) == SAS_ADDR(phy->attached_sas_addr) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) dev_type_flutter(type, phy->attached_dev_type)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) struct domain_device *ata_dev = sas_ex_to_ata(dev, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) char *action = "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) sas_ex_phy_discover(dev, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) if (ata_dev && phy->attached_dev_type == SAS_SATA_PENDING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) action = ", needs recovery";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) pr_debug("ex %016llx phy%02d broadcast flutter%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) SAS_ADDR(dev->sas_addr), phy_id, action);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) /* we always have to delete the old device when we went here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) pr_info("ex %016llx phy%02d replace %016llx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) SAS_ADDR(dev->sas_addr), phy_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) SAS_ADDR(phy->attached_sas_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) sas_unregister_devs_sas_addr(dev, phy_id, last);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) return sas_discover_new(dev, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) * sas_rediscover - revalidate the domain.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) * @dev:domain device to be detect.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) * @phy_id: the phy id will be detected.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) * NOTE: this process _must_ quit (return) as soon as any connection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) * errors are encountered. Connection recovery is done elsewhere.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) * Discover process only interrogates devices in order to discover the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) * domain.For plugging out, we un-register the device only when it is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) * the last phy in the port, for other phys in this port, we just delete it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) * from the port.For inserting, we do discovery when it is the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) * first phy,for other phys in this port, we add it to the port to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) * forming the wide-port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) static int sas_rediscover(struct domain_device *dev, const int phy_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) struct expander_device *ex = &dev->ex_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) struct ex_phy *changed_phy = &ex->ex_phy[phy_id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) int res = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) bool last = true; /* is this the last phy of the port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) pr_debug("ex %016llx phy%02d originated BROADCAST(CHANGE)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) SAS_ADDR(dev->sas_addr), phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) if (SAS_ADDR(changed_phy->attached_sas_addr) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) for (i = 0; i < ex->num_phys; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) struct ex_phy *phy = &ex->ex_phy[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) if (i == phy_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) if (SAS_ADDR(phy->attached_sas_addr) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) SAS_ADDR(changed_phy->attached_sas_addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) last = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) res = sas_rediscover_dev(dev, phy_id, last, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) res = sas_discover_new(dev, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) * sas_ex_revalidate_domain - revalidate the domain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) * @port_dev: port domain device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) * NOTE: this process _must_ quit (return) as soon as any connection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) * errors are encountered. Connection recovery is done elsewhere.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) * Discover process only interrogates devices in order to discover the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) * domain.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) int sas_ex_revalidate_domain(struct domain_device *port_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) struct domain_device *dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) res = sas_find_bcast_dev(port_dev, &dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) if (res == 0 && dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) struct expander_device *ex = &dev->ex_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) int i = 0, phy_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) phy_id = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) res = sas_find_bcast_phy(dev, &phy_id, i, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) if (phy_id == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) res = sas_rediscover(dev, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) i = phy_id + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) } while (i < ex->num_phys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) void sas_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) struct sas_rphy *rphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) struct domain_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) unsigned int rcvlen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) int ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) /* no rphy means no smp target support (ie aic94xx host) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) if (!rphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) return sas_smp_host_handler(job, shost);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) switch (rphy->identify.device_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) case SAS_EDGE_EXPANDER_DEVICE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) case SAS_FANOUT_EXPANDER_DEVICE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) pr_err("%s: can we send a smp request to a device?\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) dev = sas_find_dev_by_rphy(rphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) if (!dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) pr_err("%s: fail to find a domain_device?\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) /* do we need to support multiple segments? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) if (job->request_payload.sg_cnt > 1 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164) job->reply_payload.sg_cnt > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) pr_info("%s: multiple segments req %u, rsp %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) __func__, job->request_payload.payload_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) job->reply_payload.payload_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) ret = smp_execute_task_sg(dev, job->request_payload.sg_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) job->reply_payload.sg_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) if (ret >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) /* bsg_job_done() requires the length received */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) rcvlen = job->reply_payload.payload_len - ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) bsg_job_done(job, ret, rcvlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) }