aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/isci/host.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/isci/host.c')
-rw-r--r--drivers/scsi/isci/host.c145
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 */
121void isci_host_start_complete( 102void 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
138int isci_host_scan_finished(struct Scsi_Host *shost, unsigned long time) 112int 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 */
181void isci_host_scan_start(struct Scsi_Host *shost) 146void 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
197void isci_host_stop_complete( 157void 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
208static struct coherent_memory_info *isci_host_alloc_mdl_struct( 165static 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
373void isci_host_deinit( 330void 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
400static int isci_verify_firmware(const struct firmware *fw, 352static 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;