aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libsas/sas_expander.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/libsas/sas_expander.c')
-rw-r--r--drivers/scsi/libsas/sas_expander.c178
1 files changed, 99 insertions, 79 deletions
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index 4b2ecd35dc5a..7e2d3c4c6171 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -183,13 +183,27 @@ static char sas_route_char(struct domain_device *dev, struct ex_phy *phy)
183 } 183 }
184} 184}
185 185
186static void sas_set_ex_phy(struct domain_device *dev, int phy_id, 186static enum sas_dev_type to_dev_type(struct discover_resp *dr)
187 void *disc_resp)
188{ 187{
188 /* This is detecting a failure to transmit initial dev to host
189 * FIS as described in section J.5 of sas-2 r16
190 */
191 if (dr->attached_dev_type == NO_DEVICE && dr->attached_sata_dev &&
192 dr->linkrate >= SAS_LINK_RATE_1_5_GBPS)
193 return SATA_PENDING;
194 else
195 return dr->attached_dev_type;
196}
197
198static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
199{
200 enum sas_dev_type dev_type;
201 enum sas_linkrate linkrate;
202 u8 sas_addr[SAS_ADDR_SIZE];
203 struct smp_resp *resp = rsp;
204 struct discover_resp *dr = &resp->disc;
189 struct expander_device *ex = &dev->ex_dev; 205 struct expander_device *ex = &dev->ex_dev;
190 struct ex_phy *phy = &ex->ex_phy[phy_id]; 206 struct ex_phy *phy = &ex->ex_phy[phy_id];
191 struct smp_resp *resp = disc_resp;
192 struct discover_resp *dr = &resp->disc;
193 struct sas_rphy *rphy = dev->rphy; 207 struct sas_rphy *rphy = dev->rphy;
194 bool new_phy = !phy->phy; 208 bool new_phy = !phy->phy;
195 char *type; 209 char *type;
@@ -213,8 +227,13 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id,
213 break; 227 break;
214 } 228 }
215 229
230 /* check if anything important changed to squelch debug */
231 dev_type = phy->attached_dev_type;
232 linkrate = phy->linkrate;
233 memcpy(sas_addr, phy->attached_sas_addr, SAS_ADDR_SIZE);
234
235 phy->attached_dev_type = to_dev_type(dr);
216 phy->phy_id = phy_id; 236 phy->phy_id = phy_id;
217 phy->attached_dev_type = dr->attached_dev_type;
218 phy->linkrate = dr->linkrate; 237 phy->linkrate = dr->linkrate;
219 phy->attached_sata_host = dr->attached_sata_host; 238 phy->attached_sata_host = dr->attached_sata_host;
220 phy->attached_sata_dev = dr->attached_sata_dev; 239 phy->attached_sata_dev = dr->attached_sata_dev;
@@ -229,7 +248,7 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id,
229 phy->last_da_index = -1; 248 phy->last_da_index = -1;
230 249
231 phy->phy->identify.sas_address = SAS_ADDR(phy->attached_sas_addr); 250 phy->phy->identify.sas_address = SAS_ADDR(phy->attached_sas_addr);
232 phy->phy->identify.device_type = phy->attached_dev_type; 251 phy->phy->identify.device_type = dr->attached_dev_type;
233 phy->phy->identify.initiator_port_protocols = phy->attached_iproto; 252 phy->phy->identify.initiator_port_protocols = phy->attached_iproto;
234 phy->phy->identify.target_port_protocols = phy->attached_tproto; 253 phy->phy->identify.target_port_protocols = phy->attached_tproto;
235 phy->phy->identify.phy_identifier = phy_id; 254 phy->phy->identify.phy_identifier = phy_id;
@@ -246,6 +265,9 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id,
246 } 265 }
247 266
248 switch (phy->attached_dev_type) { 267 switch (phy->attached_dev_type) {
268 case SATA_PENDING:
269 type = "stp pending";
270 break;
249 case NO_DEVICE: 271 case NO_DEVICE:
250 type = "no device"; 272 type = "no device";
251 break; 273 break;
@@ -270,6 +292,16 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id,
270 type = "unknown"; 292 type = "unknown";
271 } 293 }
272 294
295 /* this routine is polled by libata error recovery so filter
296 * unimportant messages
297 */
298 if (new_phy || phy->attached_dev_type != dev_type ||
299 phy->linkrate != linkrate ||
300 SAS_ADDR(phy->attached_sas_addr) != SAS_ADDR(sas_addr))
301 /* pass */;
302 else
303 return;
304
273 SAS_DPRINTK("ex %016llx phy%02d:%c:%X attached: %016llx (%s)\n", 305 SAS_DPRINTK("ex %016llx phy%02d:%c:%X attached: %016llx (%s)\n",
274 SAS_ADDR(dev->sas_addr), phy->phy_id, 306 SAS_ADDR(dev->sas_addr), phy->phy_id,
275 sas_route_char(dev, phy), phy->linkrate, 307 sas_route_char(dev, phy), phy->linkrate,
@@ -304,50 +336,25 @@ struct domain_device *sas_ex_to_ata(struct domain_device *ex_dev, int phy_id)
304static int sas_ex_phy_discover_helper(struct domain_device *dev, u8 *disc_req, 336static int sas_ex_phy_discover_helper(struct domain_device *dev, u8 *disc_req,
305 u8 *disc_resp, int single) 337 u8 *disc_resp, int single)
306{ 338{
307 struct domain_device *ata_dev = sas_ex_to_ata(dev, single); 339 struct discover_resp *dr;
308 int i, res; 340 int res;
309 341
310 disc_req[9] = single; 342 disc_req[9] = single;
311 for (i = 1 ; i < 3; i++) {
312 struct discover_resp *dr;
313 343
314 res = smp_execute_task(dev, disc_req, DISCOVER_REQ_SIZE, 344 res = smp_execute_task(dev, disc_req, DISCOVER_REQ_SIZE,
315 disc_resp, DISCOVER_RESP_SIZE); 345 disc_resp, DISCOVER_RESP_SIZE);
316 if (res) 346 if (res)
317 return res; 347 return res;
318 dr = &((struct smp_resp *)disc_resp)->disc; 348 dr = &((struct smp_resp *)disc_resp)->disc;
319 if (memcmp(dev->sas_addr, dr->attached_sas_addr, 349 if (memcmp(dev->sas_addr, dr->attached_sas_addr, SAS_ADDR_SIZE) == 0) {
320 SAS_ADDR_SIZE) == 0) { 350 sas_printk("Found loopback topology, just ignore it!\n");
321 sas_printk("Found loopback topology, just ignore it!\n"); 351 return 0;
322 return 0;
323 }
324
325 /* This is detecting a failure to transmit initial
326 * dev to host FIS as described in section J.5 of
327 * sas-2 r16
328 */
329 if (!(dr->attached_dev_type == 0 &&
330 dr->attached_sata_dev))
331 break;
332
333 /* In order to generate the dev to host FIS, we send a
334 * link reset to the expander port. If a device was
335 * previously detected on this port we ask libata to
336 * manage the reset and link recovery.
337 */
338 if (ata_dev) {
339 sas_ata_schedule_reset(ata_dev);
340 break;
341 }
342 sas_smp_phy_control(dev, single, PHY_FUNC_LINK_RESET, NULL);
343 /* Wait for the reset to trigger the negotiation */
344 msleep(500);
345 } 352 }
346 sas_set_ex_phy(dev, single, disc_resp); 353 sas_set_ex_phy(dev, single, disc_resp);
347 return 0; 354 return 0;
348} 355}
349 356
350static int sas_ex_phy_discover(struct domain_device *dev, int single) 357int sas_ex_phy_discover(struct domain_device *dev, int single)
351{ 358{
352 struct expander_device *ex = &dev->ex_dev; 359 struct expander_device *ex = &dev->ex_dev;
353 int res = 0; 360 int res = 0;
@@ -652,9 +659,8 @@ int sas_smp_get_phy_events(struct sas_phy *phy)
652#define RPS_REQ_SIZE 16 659#define RPS_REQ_SIZE 16
653#define RPS_RESP_SIZE 60 660#define RPS_RESP_SIZE 60
654 661
655static int sas_get_report_phy_sata(struct domain_device *dev, 662int sas_get_report_phy_sata(struct domain_device *dev, int phy_id,
656 int phy_id, 663 struct smp_resp *rps_resp)
657 struct smp_resp *rps_resp)
658{ 664{
659 int res; 665 int res;
660 u8 *rps_req = alloc_smp_req(RPS_REQ_SIZE); 666 u8 *rps_req = alloc_smp_req(RPS_REQ_SIZE);
@@ -764,21 +770,9 @@ static struct domain_device *sas_ex_discover_end_dev(
764 770
765#ifdef CONFIG_SCSI_SAS_ATA 771#ifdef CONFIG_SCSI_SAS_ATA
766 if ((phy->attached_tproto & SAS_PROTOCOL_STP) || phy->attached_sata_dev) { 772 if ((phy->attached_tproto & SAS_PROTOCOL_STP) || phy->attached_sata_dev) {
767 child->dev_type = SATA_DEV; 773 res = sas_get_ata_info(child, phy);
768 if (phy->attached_tproto & SAS_PROTOCOL_STP) 774 if (res)
769 child->tproto = phy->attached_tproto;
770 if (phy->attached_sata_dev)
771 child->tproto |= SATA_DEV;
772 res = sas_get_report_phy_sata(parent, phy_id,
773 &child->sata_dev.rps_resp);
774 if (res) {
775 SAS_DPRINTK("report phy sata to %016llx:0x%x returned "
776 "0x%x\n", SAS_ADDR(parent->sas_addr),
777 phy_id, res);
778 goto out_free; 775 goto out_free;
779 }
780 memcpy(child->frame_rcvd, &child->sata_dev.rps_resp.rps.fis,
781 sizeof(struct dev_to_host_fis));
782 776
783 rphy = sas_end_device_alloc(phy->port); 777 rphy = sas_end_device_alloc(phy->port);
784 if (unlikely(!rphy)) 778 if (unlikely(!rphy))
@@ -993,7 +987,8 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id)
993 987
994 if (ex_phy->attached_dev_type != SAS_END_DEV && 988 if (ex_phy->attached_dev_type != SAS_END_DEV &&
995 ex_phy->attached_dev_type != FANOUT_DEV && 989 ex_phy->attached_dev_type != FANOUT_DEV &&
996 ex_phy->attached_dev_type != EDGE_DEV) { 990 ex_phy->attached_dev_type != EDGE_DEV &&
991 ex_phy->attached_dev_type != SATA_PENDING) {
997 SAS_DPRINTK("unknown device type(0x%x) attached to ex %016llx " 992 SAS_DPRINTK("unknown device type(0x%x) attached to ex %016llx "
998 "phy 0x%x\n", ex_phy->attached_dev_type, 993 "phy 0x%x\n", ex_phy->attached_dev_type,
999 SAS_ADDR(dev->sas_addr), 994 SAS_ADDR(dev->sas_addr),
@@ -1019,6 +1014,7 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id)
1019 1014
1020 switch (ex_phy->attached_dev_type) { 1015 switch (ex_phy->attached_dev_type) {
1021 case SAS_END_DEV: 1016 case SAS_END_DEV:
1017 case SATA_PENDING:
1022 child = sas_ex_discover_end_dev(dev, phy_id); 1018 child = sas_ex_discover_end_dev(dev, phy_id);
1023 break; 1019 break;
1024 case FANOUT_DEV: 1020 case FANOUT_DEV:
@@ -1688,8 +1684,8 @@ static int sas_get_phy_change_count(struct domain_device *dev,
1688 return res; 1684 return res;
1689} 1685}
1690 1686
1691int sas_get_phy_attached_sas_addr(struct domain_device *dev, int phy_id, 1687static int sas_get_phy_attached_dev(struct domain_device *dev, int phy_id,
1692 u8 *attached_sas_addr) 1688 u8 *sas_addr, enum sas_dev_type *type)
1693{ 1689{
1694 int res; 1690 int res;
1695 struct smp_resp *disc_resp; 1691 struct smp_resp *disc_resp;
@@ -1701,10 +1697,11 @@ int sas_get_phy_attached_sas_addr(struct domain_device *dev, int phy_id,
1701 dr = &disc_resp->disc; 1697 dr = &disc_resp->disc;
1702 1698
1703 res = sas_get_phy_discover(dev, phy_id, disc_resp); 1699 res = sas_get_phy_discover(dev, phy_id, disc_resp);
1704 if (!res) { 1700 if (res == 0) {
1705 memcpy(attached_sas_addr,disc_resp->disc.attached_sas_addr,8); 1701 memcpy(sas_addr, disc_resp->disc.attached_sas_addr, 8);
1706 if (dr->attached_dev_type == 0) 1702 *type = to_dev_type(dr);
1707 memset(attached_sas_addr, 0, 8); 1703 if (*type == 0)
1704 memset(sas_addr, 0, 8);
1708 } 1705 }
1709 kfree(disc_resp); 1706 kfree(disc_resp);
1710 return res; 1707 return res;
@@ -1953,39 +1950,62 @@ out:
1953 return res; 1950 return res;
1954} 1951}
1955 1952
1953static bool dev_type_flutter(enum sas_dev_type new, enum sas_dev_type old)
1954{
1955 if (old == new)
1956 return true;
1957
1958 /* treat device directed resets as flutter, if we went
1959 * SAS_END_DEV to SATA_PENDING the link needs recovery
1960 */
1961 if ((old == SATA_PENDING && new == SAS_END_DEV) ||
1962 (old == SAS_END_DEV && new == SATA_PENDING))
1963 return true;
1964
1965 return false;
1966}
1967
1956static int sas_rediscover_dev(struct domain_device *dev, int phy_id, bool last) 1968static int sas_rediscover_dev(struct domain_device *dev, int phy_id, bool last)
1957{ 1969{
1958 struct expander_device *ex = &dev->ex_dev; 1970 struct expander_device *ex = &dev->ex_dev;
1959 struct ex_phy *phy = &ex->ex_phy[phy_id]; 1971 struct ex_phy *phy = &ex->ex_phy[phy_id];
1960 u8 attached_sas_addr[8]; 1972 enum sas_dev_type type = NO_DEVICE;
1973 u8 sas_addr[8];
1961 int res; 1974 int res;
1962 1975
1963 res = sas_get_phy_attached_sas_addr(dev, phy_id, attached_sas_addr); 1976 res = sas_get_phy_attached_dev(dev, phy_id, sas_addr, &type);
1964 switch (res) { 1977 switch (res) {
1965 case SMP_RESP_NO_PHY: 1978 case SMP_RESP_NO_PHY:
1966 phy->phy_state = PHY_NOT_PRESENT; 1979 phy->phy_state = PHY_NOT_PRESENT;
1967 sas_unregister_devs_sas_addr(dev, phy_id, last); 1980 sas_unregister_devs_sas_addr(dev, phy_id, last);
1968 goto out; break; 1981 return res;
1969 case SMP_RESP_PHY_VACANT: 1982 case SMP_RESP_PHY_VACANT:
1970 phy->phy_state = PHY_VACANT; 1983 phy->phy_state = PHY_VACANT;
1971 sas_unregister_devs_sas_addr(dev, phy_id, last); 1984 sas_unregister_devs_sas_addr(dev, phy_id, last);
1972 goto out; break; 1985 return res;
1973 case SMP_RESP_FUNC_ACC: 1986 case SMP_RESP_FUNC_ACC:
1974 break; 1987 break;
1975 } 1988 }
1976 1989
1977 if (SAS_ADDR(attached_sas_addr) == 0) { 1990 if (SAS_ADDR(sas_addr) == 0) {
1978 phy->phy_state = PHY_EMPTY; 1991 phy->phy_state = PHY_EMPTY;
1979 sas_unregister_devs_sas_addr(dev, phy_id, last); 1992 sas_unregister_devs_sas_addr(dev, phy_id, last);
1980 } else if (SAS_ADDR(attached_sas_addr) == 1993 return res;
1981 SAS_ADDR(phy->attached_sas_addr)) { 1994 } else if (SAS_ADDR(sas_addr) == SAS_ADDR(phy->attached_sas_addr) &&
1982 SAS_DPRINTK("ex %016llx phy 0x%x broadcast flutter\n", 1995 dev_type_flutter(type, phy->attached_dev_type)) {
1983 SAS_ADDR(dev->sas_addr), phy_id); 1996 struct domain_device *ata_dev = sas_ex_to_ata(dev, phy_id);
1997 char *action = "";
1998
1984 sas_ex_phy_discover(dev, phy_id); 1999 sas_ex_phy_discover(dev, phy_id);
1985 } else 2000
1986 res = sas_discover_new(dev, phy_id); 2001 if (ata_dev && phy->attached_dev_type == SATA_PENDING)
1987out: 2002 action = ", needs recovery";
1988 return res; 2003 SAS_DPRINTK("ex %016llx phy 0x%x broadcast flutter%s\n",
2004 SAS_ADDR(dev->sas_addr), phy_id, action);
2005 return res;
2006 }
2007
2008 return sas_discover_new(dev, phy_id);
1989} 2009}
1990 2010
1991/** 2011/**