diff options
Diffstat (limited to 'drivers/scsi/libsas/sas_port.c')
-rw-r--r-- | drivers/scsi/libsas/sas_port.c | 52 |
1 files changed, 51 insertions, 1 deletions
diff --git a/drivers/scsi/libsas/sas_port.c b/drivers/scsi/libsas/sas_port.c index e884a8c58a0..1398b714c01 100644 --- a/drivers/scsi/libsas/sas_port.c +++ b/drivers/scsi/libsas/sas_port.c | |||
@@ -39,6 +39,49 @@ static bool phy_is_wideport_member(struct asd_sas_port *port, struct asd_sas_phy | |||
39 | return true; | 39 | return true; |
40 | } | 40 | } |
41 | 41 | ||
42 | static void sas_resume_port(struct asd_sas_phy *phy) | ||
43 | { | ||
44 | struct domain_device *dev; | ||
45 | struct asd_sas_port *port = phy->port; | ||
46 | struct sas_ha_struct *sas_ha = phy->ha; | ||
47 | struct sas_internal *si = to_sas_internal(sas_ha->core.shost->transportt); | ||
48 | |||
49 | if (si->dft->lldd_port_formed) | ||
50 | si->dft->lldd_port_formed(phy); | ||
51 | |||
52 | if (port->suspended) | ||
53 | port->suspended = 0; | ||
54 | else { | ||
55 | /* we only need to handle "link returned" actions once */ | ||
56 | return; | ||
57 | } | ||
58 | |||
59 | /* if the port came back: | ||
60 | * 1/ presume every device came back | ||
61 | * 2/ force the next revalidation to check all expander phys | ||
62 | */ | ||
63 | list_for_each_entry(dev, &port->dev_list, dev_list_node) { | ||
64 | int i, rc; | ||
65 | |||
66 | rc = sas_notify_lldd_dev_found(dev); | ||
67 | if (rc) { | ||
68 | sas_unregister_dev(port, dev); | ||
69 | continue; | ||
70 | } | ||
71 | |||
72 | if (dev->dev_type == EDGE_DEV || dev->dev_type == FANOUT_DEV) { | ||
73 | dev->ex_dev.ex_change_count = -1; | ||
74 | for (i = 0; i < dev->ex_dev.num_phys; i++) { | ||
75 | struct ex_phy *phy = &dev->ex_dev.ex_phy[i]; | ||
76 | |||
77 | phy->phy_change_count = -1; | ||
78 | } | ||
79 | } | ||
80 | } | ||
81 | |||
82 | sas_discover_event(port, DISCE_RESUME); | ||
83 | } | ||
84 | |||
42 | /** | 85 | /** |
43 | * sas_form_port -- add this phy to a port | 86 | * sas_form_port -- add this phy to a port |
44 | * @phy: the phy of interest | 87 | * @phy: the phy of interest |
@@ -58,7 +101,14 @@ static void sas_form_port(struct asd_sas_phy *phy) | |||
58 | if (port) { | 101 | if (port) { |
59 | if (!phy_is_wideport_member(port, phy)) | 102 | if (!phy_is_wideport_member(port, phy)) |
60 | sas_deform_port(phy, 0); | 103 | sas_deform_port(phy, 0); |
61 | else { | 104 | else if (phy->suspended) { |
105 | phy->suspended = 0; | ||
106 | sas_resume_port(phy); | ||
107 | |||
108 | /* phy came back, try to cancel the timeout */ | ||
109 | wake_up(&sas_ha->eh_wait_q); | ||
110 | return; | ||
111 | } else { | ||
62 | SAS_DPRINTK("%s: phy%d belongs to port%d already(%d)!\n", | 112 | SAS_DPRINTK("%s: phy%d belongs to port%d already(%d)!\n", |
63 | __func__, phy->id, phy->port->id, | 113 | __func__, phy->id, phy->port->id, |
64 | phy->port->num_phys); | 114 | phy->port->num_phys); |