diff options
Diffstat (limited to 'drivers/scsi/isci/host.c')
-rw-r--r-- | drivers/scsi/isci/host.c | 145 |
1 files changed, 49 insertions, 96 deletions
diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index b66e62027247..dbdc3bab9ca3 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c | |||
@@ -67,15 +67,8 @@ irqreturn_t isci_msix_isr(int vec, void *data) | |||
67 | struct isci_host *ihost = data; | 67 | struct isci_host *ihost = data; |
68 | struct scic_sds_controller *scic = ihost->core_controller; | 68 | struct scic_sds_controller *scic = ihost->core_controller; |
69 | 69 | ||
70 | if (isci_host_get_state(ihost) != isci_starting) { | 70 | if (scic_sds_controller_isr(scic)) |
71 | if (scic_sds_controller_isr(scic)) { | 71 | tasklet_schedule(&ihost->completion_tasklet); |
72 | if (isci_host_get_state(ihost) != isci_stopped) | ||
73 | tasklet_schedule(&ihost->completion_tasklet); | ||
74 | else | ||
75 | dev_dbg(&ihost->pdev->dev, | ||
76 | "%s: controller stopped\n", __func__); | ||
77 | } | ||
78 | } | ||
79 | 72 | ||
80 | return IRQ_HANDLED; | 73 | return IRQ_HANDLED; |
81 | } | 74 | } |
@@ -89,22 +82,10 @@ irqreturn_t isci_intx_isr(int vec, void *data) | |||
89 | for_each_isci_host(ihost, pdev) { | 82 | for_each_isci_host(ihost, pdev) { |
90 | struct scic_sds_controller *scic = ihost->core_controller; | 83 | struct scic_sds_controller *scic = ihost->core_controller; |
91 | 84 | ||
92 | if (isci_host_get_state(ihost) != isci_starting) { | 85 | if (scic_sds_controller_isr(scic)) { |
93 | if (scic_sds_controller_isr(scic)) { | 86 | tasklet_schedule(&ihost->completion_tasklet); |
94 | if (isci_host_get_state(ihost) != isci_stopped) | 87 | ret = IRQ_HANDLED; |
95 | tasklet_schedule(&ihost->completion_tasklet); | 88 | } |
96 | else | ||
97 | dev_dbg(&ihost->pdev->dev, | ||
98 | "%s: controller stopped\n", | ||
99 | __func__); | ||
100 | ret = IRQ_HANDLED; | ||
101 | } | ||
102 | } else | ||
103 | dev_warn(&ihost->pdev->dev, | ||
104 | "%s: get_handler_methods failed, " | ||
105 | "ihost->status = 0x%x\n", | ||
106 | __func__, | ||
107 | isci_host_get_state(ihost)); | ||
108 | } | 89 | } |
109 | return ret; | 90 | return ret; |
110 | } | 91 | } |
@@ -118,26 +99,19 @@ irqreturn_t isci_intx_isr(int vec, void *data) | |||
118 | * core library. | 99 | * core library. |
119 | * | 100 | * |
120 | */ | 101 | */ |
121 | void isci_host_start_complete( | 102 | void isci_host_start_complete(struct isci_host *ihost, enum sci_status completion_status) |
122 | struct isci_host *isci_host, | ||
123 | enum sci_status completion_status) | ||
124 | { | 103 | { |
125 | if (completion_status == SCI_SUCCESS) { | 104 | if (completion_status != SCI_SUCCESS) |
126 | dev_dbg(&isci_host->pdev->dev, | 105 | dev_info(&ihost->pdev->dev, |
127 | "%s: completion_status: SCI_SUCCESS\n", __func__); | 106 | "controller start timed out, continuing...\n"); |
128 | isci_host_change_state(isci_host, isci_ready); | 107 | isci_host_change_state(ihost, isci_ready); |
129 | complete_all(&isci_host->start_complete); | 108 | clear_bit(IHOST_START_PENDING, &ihost->flags); |
130 | } else | 109 | wake_up(&ihost->eventq); |
131 | dev_err(&isci_host->pdev->dev, | ||
132 | "controller start failed with " | ||
133 | "completion_status = 0x%x;", | ||
134 | completion_status); | ||
135 | |||
136 | } | 110 | } |
137 | 111 | ||
138 | int isci_host_scan_finished(struct Scsi_Host *shost, unsigned long time) | 112 | int isci_host_scan_finished(struct Scsi_Host *shost, unsigned long time) |
139 | { | 113 | { |
140 | struct isci_host *isci_host = isci_host_from_sas_ha(SHOST_TO_SAS_HA(shost)); | 114 | struct isci_host *ihost = isci_host_from_sas_ha(SHOST_TO_SAS_HA(shost)); |
141 | 115 | ||
142 | /** | 116 | /** |
143 | * check interrupt_handler's status and call completion_handler if true, | 117 | * check interrupt_handler's status and call completion_handler if true, |
@@ -148,61 +122,44 @@ int isci_host_scan_finished(struct Scsi_Host *shost, unsigned long time) | |||
148 | * continue to return zero from thee scan_finished routine until | 122 | * continue to return zero from thee scan_finished routine until |
149 | * the scic_cb_controller_start_complete() call comes from the core. | 123 | * the scic_cb_controller_start_complete() call comes from the core. |
150 | **/ | 124 | **/ |
151 | if (scic_sds_controller_isr(isci_host->core_controller)) | 125 | if (scic_sds_controller_isr(ihost->core_controller)) |
152 | scic_sds_controller_completion_handler(isci_host->core_controller); | 126 | scic_sds_controller_completion_handler(ihost->core_controller); |
153 | 127 | ||
154 | if (isci_starting == isci_host_get_state(isci_host) | 128 | if (test_bit(IHOST_START_PENDING, &ihost->flags) && time < HZ*10) { |
155 | && time < (HZ * 10)) { | 129 | dev_dbg(&ihost->pdev->dev, |
156 | dev_dbg(&isci_host->pdev->dev, | 130 | "%s: ihost->status = %d, time = %ld\n", |
157 | "%s: isci_host->status = %d, time = %ld\n", | 131 | __func__, isci_host_get_state(ihost), time); |
158 | __func__, isci_host_get_state(isci_host), time); | ||
159 | return 0; | 132 | return 0; |
160 | } | 133 | } |
161 | 134 | ||
162 | 135 | ||
163 | dev_dbg(&isci_host->pdev->dev, | 136 | dev_dbg(&ihost->pdev->dev, |
164 | "%s: isci_host->status = %d, time = %ld\n", | 137 | "%s: ihost->status = %d, time = %ld\n", |
165 | __func__, isci_host_get_state(isci_host), time); | 138 | __func__, isci_host_get_state(ihost), time); |
166 | 139 | ||
167 | scic_controller_enable_interrupts(isci_host->core_controller); | 140 | scic_controller_enable_interrupts(ihost->core_controller); |
168 | 141 | ||
169 | return 1; | 142 | return 1; |
170 | 143 | ||
171 | } | 144 | } |
172 | 145 | ||
173 | |||
174 | /** | ||
175 | * isci_host_scan_start() - This function is one of the SCSI Host Template | ||
176 | * function, called by the SCSI mid layer berfore a target scan begins. The | ||
177 | * core library controller start routine is called from here. | ||
178 | * @shost: This parameter specifies the SCSI host to be scanned | ||
179 | * | ||
180 | */ | ||
181 | void isci_host_scan_start(struct Scsi_Host *shost) | 146 | void isci_host_scan_start(struct Scsi_Host *shost) |
182 | { | 147 | { |
183 | struct isci_host *isci_host; | 148 | struct isci_host *ihost = isci_host_from_sas_ha(SHOST_TO_SAS_HA(shost)); |
184 | 149 | struct scic_sds_controller *scic = ihost->core_controller; | |
185 | isci_host = isci_host_from_sas_ha(SHOST_TO_SAS_HA(shost)); | 150 | unsigned long tmo = scic_controller_get_suggested_start_timeout(scic); |
186 | isci_host_change_state(isci_host, isci_starting); | ||
187 | 151 | ||
188 | scic_controller_disable_interrupts(isci_host->core_controller); | 152 | set_bit(IHOST_START_PENDING, &ihost->flags); |
189 | init_completion(&isci_host->start_complete); | 153 | scic_controller_disable_interrupts(ihost->core_controller); |
190 | scic_controller_start( | 154 | scic_controller_start(scic, tmo); |
191 | isci_host->core_controller, | ||
192 | scic_controller_get_suggested_start_timeout( | ||
193 | isci_host->core_controller) | ||
194 | ); | ||
195 | } | 155 | } |
196 | 156 | ||
197 | void isci_host_stop_complete( | 157 | void isci_host_stop_complete(struct isci_host *ihost, enum sci_status completion_status) |
198 | struct isci_host *isci_host, | ||
199 | enum sci_status completion_status) | ||
200 | { | 158 | { |
201 | isci_host_change_state(isci_host, isci_stopped); | 159 | isci_host_change_state(ihost, isci_stopped); |
202 | scic_controller_disable_interrupts( | 160 | scic_controller_disable_interrupts(ihost->core_controller); |
203 | isci_host->core_controller | 161 | clear_bit(IHOST_STOP_PENDING, &ihost->flags); |
204 | ); | 162 | wake_up(&ihost->eventq); |
205 | complete(&isci_host->stop_complete); | ||
206 | } | 163 | } |
207 | 164 | ||
208 | static struct coherent_memory_info *isci_host_alloc_mdl_struct( | 165 | static struct coherent_memory_info *isci_host_alloc_mdl_struct( |
@@ -370,31 +327,26 @@ static void isci_host_completion_routine(unsigned long data) | |||
370 | 327 | ||
371 | } | 328 | } |
372 | 329 | ||
373 | void isci_host_deinit( | 330 | void isci_host_deinit(struct isci_host *ihost) |
374 | struct isci_host *isci_host) | ||
375 | { | 331 | { |
332 | struct scic_sds_controller *scic = ihost->core_controller; | ||
376 | int i; | 333 | int i; |
377 | 334 | ||
378 | isci_host_change_state(isci_host, isci_stopping); | 335 | isci_host_change_state(ihost, isci_stopping); |
379 | for (i = 0; i < SCI_MAX_PORTS; i++) { | 336 | for (i = 0; i < SCI_MAX_PORTS; i++) { |
380 | struct isci_port *port = &isci_host->isci_ports[i]; | 337 | struct isci_port *port = &ihost->isci_ports[i]; |
381 | struct isci_remote_device *device, *tmpdev; | 338 | struct isci_remote_device *idev, *d; |
382 | list_for_each_entry_safe(device, tmpdev, | 339 | |
383 | &port->remote_dev_list, node) { | 340 | list_for_each_entry_safe(idev, d, &port->remote_dev_list, node) { |
384 | isci_remote_device_change_state(device, isci_stopping); | 341 | isci_remote_device_change_state(idev, isci_stopping); |
385 | isci_remote_device_stop(device); | 342 | isci_remote_device_stop(idev); |
386 | } | 343 | } |
387 | } | 344 | } |
388 | 345 | ||
389 | /* stop the comtroller and wait for completion. */ | 346 | set_bit(IHOST_STOP_PENDING, &ihost->flags); |
390 | init_completion(&isci_host->stop_complete); | 347 | scic_controller_stop(scic, SCIC_CONTROLLER_STOP_TIMEOUT); |
391 | scic_controller_stop( | 348 | wait_for_stop(ihost); |
392 | isci_host->core_controller, | 349 | scic_controller_reset(scic); |
393 | SCIC_CONTROLLER_STOP_TIMEOUT | ||
394 | ); | ||
395 | wait_for_completion(&isci_host->stop_complete); | ||
396 | /* next, reset the controller. */ | ||
397 | scic_controller_reset(isci_host->core_controller); | ||
398 | } | 350 | } |
399 | 351 | ||
400 | static int isci_verify_firmware(const struct firmware *fw, | 352 | static int isci_verify_firmware(const struct firmware *fw, |
@@ -506,6 +458,7 @@ int isci_host_init(struct isci_host *isci_host) | |||
506 | spin_lock_init(&isci_host->state_lock); | 458 | spin_lock_init(&isci_host->state_lock); |
507 | spin_lock_init(&isci_host->scic_lock); | 459 | spin_lock_init(&isci_host->scic_lock); |
508 | spin_lock_init(&isci_host->queue_lock); | 460 | spin_lock_init(&isci_host->queue_lock); |
461 | init_waitqueue_head(&isci_host->eventq); | ||
509 | 462 | ||
510 | isci_host_change_state(isci_host, isci_starting); | 463 | isci_host_change_state(isci_host, isci_starting); |
511 | isci_host->can_queue = ISCI_CAN_QUEUE_VAL; | 464 | isci_host->can_queue = ISCI_CAN_QUEUE_VAL; |