aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libsas/sas_phy.c
diff options
context:
space:
mode:
authorJason Yan <yanaijie@huawei.com>2017-12-08 04:42:04 -0500
committerMartin K. Petersen <martin.petersen@oracle.com>2018-01-08 21:59:28 -0500
commit1c393b970e0f4070e4376d45f89a2d19a5c895d0 (patch)
tree41706d1df454c4d020a6beaf335b30c27f5f4e20 /drivers/scsi/libsas/sas_phy.c
parent6f5c592ce936b2a2f5d05d3112b550bb039050f2 (diff)
scsi: libsas: Use dynamic alloced work to avoid sas event lost
Now libsas hotplug work is static, every sas event type has its own static work, LLDD driver queues the hotplug work into shost->work_q. If LLDD driver burst posts lots hotplug events to libsas, the hotplug events may pending in the workqueue like shost->work_q new work[PORTE_BYTES_DMAED] --> |[PHYE_LOSS_OF_SIGNAL][PORTE_BYTES_DMAED] -> processing |<-------wait worker to process-------->| In this case, a new PORTE_BYTES_DMAED event coming, libsas try to queue it to shost->work_q, but this work is already pending, so it would be lost. Finally, libsas delete the related sas port and sas devices, but LLDD driver expect libsas add the sas port and devices(last sas event). This patch use dynamic allocated work to avoid this issue. Signed-off-by: Yijing Wang <wangyijing@huawei.com> CC: John Garry <john.garry@huawei.com> CC: Johannes Thumshirn <jthumshirn@suse.de> CC: Ewan Milne <emilne@redhat.com> CC: Christoph Hellwig <hch@lst.de> CC: Tomas Henzl <thenzl@redhat.com> CC: Dan Williams <dan.j.williams@intel.com> Reviewed-by: Hannes Reinecke <hare@suse.com> Signed-off-by: Jason Yan <yanaijie@huawei.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/libsas/sas_phy.c')
-rw-r--r--drivers/scsi/libsas/sas_phy.c44
1 files changed, 9 insertions, 35 deletions
diff --git a/drivers/scsi/libsas/sas_phy.c b/drivers/scsi/libsas/sas_phy.c
index cdee446c29e1..59f82929b0a3 100644
--- a/drivers/scsi/libsas/sas_phy.c
+++ b/drivers/scsi/libsas/sas_phy.c
@@ -35,7 +35,6 @@ static void sas_phye_loss_of_signal(struct work_struct *work)
35 struct asd_sas_event *ev = to_asd_sas_event(work); 35 struct asd_sas_event *ev = to_asd_sas_event(work);
36 struct asd_sas_phy *phy = ev->phy; 36 struct asd_sas_phy *phy = ev->phy;
37 37
38 clear_bit(PHYE_LOSS_OF_SIGNAL, &phy->phy_events_pending);
39 phy->error = 0; 38 phy->error = 0;
40 sas_deform_port(phy, 1); 39 sas_deform_port(phy, 1);
41} 40}
@@ -45,7 +44,6 @@ static void sas_phye_oob_done(struct work_struct *work)
45 struct asd_sas_event *ev = to_asd_sas_event(work); 44 struct asd_sas_event *ev = to_asd_sas_event(work);
46 struct asd_sas_phy *phy = ev->phy; 45 struct asd_sas_phy *phy = ev->phy;
47 46
48 clear_bit(PHYE_OOB_DONE, &phy->phy_events_pending);
49 phy->error = 0; 47 phy->error = 0;
50} 48}
51 49
@@ -58,8 +56,6 @@ static void sas_phye_oob_error(struct work_struct *work)
58 struct sas_internal *i = 56 struct sas_internal *i =
59 to_sas_internal(sas_ha->core.shost->transportt); 57 to_sas_internal(sas_ha->core.shost->transportt);
60 58
61 clear_bit(PHYE_OOB_ERROR, &phy->phy_events_pending);
62
63 sas_deform_port(phy, 1); 59 sas_deform_port(phy, 1);
64 60
65 if (!port && phy->enabled && i->dft->lldd_control_phy) { 61 if (!port && phy->enabled && i->dft->lldd_control_phy) {
@@ -88,8 +84,6 @@ static void sas_phye_spinup_hold(struct work_struct *work)
88 struct sas_internal *i = 84 struct sas_internal *i =
89 to_sas_internal(sas_ha->core.shost->transportt); 85 to_sas_internal(sas_ha->core.shost->transportt);
90 86
91 clear_bit(PHYE_SPINUP_HOLD, &phy->phy_events_pending);
92
93 phy->error = 0; 87 phy->error = 0;
94 i->dft->lldd_control_phy(phy, PHY_FUNC_RELEASE_SPINUP_HOLD, NULL); 88 i->dft->lldd_control_phy(phy, PHY_FUNC_RELEASE_SPINUP_HOLD, NULL);
95} 89}
@@ -99,8 +93,6 @@ static void sas_phye_resume_timeout(struct work_struct *work)
99 struct asd_sas_event *ev = to_asd_sas_event(work); 93 struct asd_sas_event *ev = to_asd_sas_event(work);
100 struct asd_sas_phy *phy = ev->phy; 94 struct asd_sas_phy *phy = ev->phy;
101 95
102 clear_bit(PHYE_RESUME_TIMEOUT, &phy->phy_events_pending);
103
104 /* phew, lldd got the phy back in the nick of time */ 96 /* phew, lldd got the phy back in the nick of time */
105 if (!phy->suspended) { 97 if (!phy->suspended) {
106 dev_info(&phy->phy->dev, "resume timeout cancelled\n"); 98 dev_info(&phy->phy->dev, "resume timeout cancelled\n");
@@ -119,39 +111,12 @@ int sas_register_phys(struct sas_ha_struct *sas_ha)
119{ 111{
120 int i; 112 int i;
121 113
122 static const work_func_t sas_phy_event_fns[PHY_NUM_EVENTS] = {
123 [PHYE_LOSS_OF_SIGNAL] = sas_phye_loss_of_signal,
124 [PHYE_OOB_DONE] = sas_phye_oob_done,
125 [PHYE_OOB_ERROR] = sas_phye_oob_error,
126 [PHYE_SPINUP_HOLD] = sas_phye_spinup_hold,
127 [PHYE_RESUME_TIMEOUT] = sas_phye_resume_timeout,
128
129 };
130
131 static const work_func_t sas_port_event_fns[PORT_NUM_EVENTS] = {
132 [PORTE_BYTES_DMAED] = sas_porte_bytes_dmaed,
133 [PORTE_BROADCAST_RCVD] = sas_porte_broadcast_rcvd,
134 [PORTE_LINK_RESET_ERR] = sas_porte_link_reset_err,
135 [PORTE_TIMER_EVENT] = sas_porte_timer_event,
136 [PORTE_HARD_RESET] = sas_porte_hard_reset,
137 };
138
139 /* Now register the phys. */ 114 /* Now register the phys. */
140 for (i = 0; i < sas_ha->num_phys; i++) { 115 for (i = 0; i < sas_ha->num_phys; i++) {
141 int k;
142 struct asd_sas_phy *phy = sas_ha->sas_phy[i]; 116 struct asd_sas_phy *phy = sas_ha->sas_phy[i];
143 117
144 phy->error = 0; 118 phy->error = 0;
145 INIT_LIST_HEAD(&phy->port_phy_el); 119 INIT_LIST_HEAD(&phy->port_phy_el);
146 for (k = 0; k < PORT_NUM_EVENTS; k++) {
147 INIT_SAS_WORK(&phy->port_events[k].work, sas_port_event_fns[k]);
148 phy->port_events[k].phy = phy;
149 }
150
151 for (k = 0; k < PHY_NUM_EVENTS; k++) {
152 INIT_SAS_WORK(&phy->phy_events[k].work, sas_phy_event_fns[k]);
153 phy->phy_events[k].phy = phy;
154 }
155 120
156 phy->port = NULL; 121 phy->port = NULL;
157 phy->ha = sas_ha; 122 phy->ha = sas_ha;
@@ -179,3 +144,12 @@ int sas_register_phys(struct sas_ha_struct *sas_ha)
179 144
180 return 0; 145 return 0;
181} 146}
147
148const work_func_t sas_phy_event_fns[PHY_NUM_EVENTS] = {
149 [PHYE_LOSS_OF_SIGNAL] = sas_phye_loss_of_signal,
150 [PHYE_OOB_DONE] = sas_phye_oob_done,
151 [PHYE_OOB_ERROR] = sas_phye_oob_error,
152 [PHYE_SPINUP_HOLD] = sas_phye_spinup_hold,
153 [PHYE_RESUME_TIMEOUT] = sas_phye_resume_timeout,
154
155};