diff options
author | Dan Williams <dan.j.williams@intel.com> | 2011-02-18 12:25:05 -0500 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2011-07-03 06:55:27 -0400 |
commit | c7ef4031f01301298bbaba2666740183cd399f8c (patch) | |
tree | 48f5508280b6a3032e52804dfde1c4b117d6bd3a | |
parent | 11c88986290712fc3ae6993af85a0f9a15886278 (diff) |
isci: bypass scic_controller_get_handler_methods()
The indirection is unecessary and broken in the current case that assigns the
handlers based on a not up-to-date pdev->msix_enabled value.
Route the handlers directly to the requisite core routines.
Todo: hook up error interrupt handling
Reported-by: Jeff Garzik <jeff@garzik.org>
Cc: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Edmund Nadolski <edmund.nadolski@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
-rw-r--r-- | drivers/scsi/isci/core/scic_sds_controller.c | 10 | ||||
-rw-r--r-- | drivers/scsi/isci/host.c | 158 | ||||
-rw-r--r-- | drivers/scsi/isci/host.h | 12 | ||||
-rw-r--r-- | drivers/scsi/isci/init.c | 4 | ||||
-rw-r--r-- | drivers/scsi/isci/isci.h | 7 |
5 files changed, 45 insertions, 146 deletions
diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index 6a32d91742b5..cd8017f048c1 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c | |||
@@ -1898,8 +1898,7 @@ static void scic_sds_controller_single_vector_completion_handler( | |||
1898 | * | 1898 | * |
1899 | * bool true if an interrupt is processed false if no interrupt was processed | 1899 | * bool true if an interrupt is processed false if no interrupt was processed |
1900 | */ | 1900 | */ |
1901 | static bool scic_sds_controller_normal_vector_interrupt_handler( | 1901 | bool scic_sds_controller_isr(struct scic_sds_controller *scic) |
1902 | struct scic_sds_controller *scic) | ||
1903 | { | 1902 | { |
1904 | if (scic_sds_controller_completion_queue_has_entries(scic)) { | 1903 | if (scic_sds_controller_completion_queue_has_entries(scic)) { |
1905 | return true; | 1904 | return true; |
@@ -1925,8 +1924,7 @@ static bool scic_sds_controller_normal_vector_interrupt_handler( | |||
1925 | * This is the method provided to handle the completions for a normal MSIX | 1924 | * This is the method provided to handle the completions for a normal MSIX |
1926 | * message. | 1925 | * message. |
1927 | */ | 1926 | */ |
1928 | static void scic_sds_controller_normal_vector_completion_handler( | 1927 | void scic_sds_controller_completion_handler(struct scic_sds_controller *scic) |
1929 | struct scic_sds_controller *scic) | ||
1930 | { | 1928 | { |
1931 | /* Empty out the completion queue */ | 1929 | /* Empty out the completion queue */ |
1932 | if (scic_sds_controller_completion_queue_has_entries(scic)) | 1930 | if (scic_sds_controller_completion_queue_has_entries(scic)) |
@@ -2582,9 +2580,9 @@ enum sci_status scic_controller_get_handler_methods( | |||
2582 | status = SCI_SUCCESS; | 2580 | status = SCI_SUCCESS; |
2583 | } else if (message_count == 2) { | 2581 | } else if (message_count == 2) { |
2584 | handler_methods[0].interrupt_handler | 2582 | handler_methods[0].interrupt_handler |
2585 | = scic_sds_controller_normal_vector_interrupt_handler; | 2583 | = scic_sds_controller_isr; |
2586 | handler_methods[0].completion_handler | 2584 | handler_methods[0].completion_handler |
2587 | = scic_sds_controller_normal_vector_completion_handler; | 2585 | = scic_sds_controller_completion_handler; |
2588 | 2586 | ||
2589 | handler_methods[1].interrupt_handler | 2587 | handler_methods[1].interrupt_handler |
2590 | = scic_sds_controller_error_vector_interrupt_handler; | 2588 | = scic_sds_controller_error_vector_interrupt_handler; |
diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 6f16f4d6c82b..b66e62027247 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c | |||
@@ -62,80 +62,49 @@ | |||
62 | #include "request.h" | 62 | #include "request.h" |
63 | #include "host.h" | 63 | #include "host.h" |
64 | 64 | ||
65 | /** | 65 | irqreturn_t isci_msix_isr(int vec, void *data) |
66 | * isci_isr() - This function is the interrupt service routine for the | ||
67 | * controller. It schedules the tasklet and returns. | ||
68 | * @vec: This parameter specifies the interrupt vector. | ||
69 | * @data: This parameter specifies the ISCI host object. | ||
70 | * | ||
71 | * IRQ_HANDLED if out interrupt otherwise, IRQ_NONE | ||
72 | */ | ||
73 | irqreturn_t isci_isr(int vec, void *data) | ||
74 | { | 66 | { |
75 | struct isci_host *isci_host | 67 | struct isci_host *ihost = data; |
76 | = (struct isci_host *)data; | 68 | struct scic_sds_controller *scic = ihost->core_controller; |
77 | struct scic_controller_handler_methods *handlers | 69 | |
78 | = &isci_host->scic_irq_handlers[SCI_MSIX_NORMAL_VECTOR]; | 70 | if (isci_host_get_state(ihost) != isci_starting) { |
79 | irqreturn_t ret = IRQ_NONE; | 71 | if (scic_sds_controller_isr(scic)) { |
80 | 72 | if (isci_host_get_state(ihost) != isci_stopped) | |
81 | if (isci_host_get_state(isci_host) != isci_starting | 73 | tasklet_schedule(&ihost->completion_tasklet); |
82 | && handlers->interrupt_handler) { | 74 | else |
83 | 75 | dev_dbg(&ihost->pdev->dev, | |
84 | if (handlers->interrupt_handler(isci_host->core_controller)) { | 76 | "%s: controller stopped\n", __func__); |
85 | if (isci_host_get_state(isci_host) != isci_stopped) { | ||
86 | tasklet_schedule( | ||
87 | &isci_host->completion_tasklet); | ||
88 | } else | ||
89 | dev_dbg(&isci_host->pdev->dev, | ||
90 | "%s: controller stopped\n", | ||
91 | __func__); | ||
92 | ret = IRQ_HANDLED; | ||
93 | } | 77 | } |
94 | } else | 78 | } |
95 | dev_warn(&isci_host->pdev->dev, | ||
96 | "%s: get_handler_methods failed, " | ||
97 | "isci_host->status = 0x%x\n", | ||
98 | __func__, | ||
99 | isci_host_get_state(isci_host)); | ||
100 | 79 | ||
101 | return ret; | 80 | return IRQ_HANDLED; |
102 | } | 81 | } |
103 | 82 | ||
104 | irqreturn_t isci_legacy_isr(int vec, void *data) | 83 | irqreturn_t isci_intx_isr(int vec, void *data) |
105 | { | 84 | { |
106 | struct pci_dev *pdev = data; | 85 | struct pci_dev *pdev = data; |
107 | struct isci_host *isci_host; | 86 | struct isci_host *ihost; |
108 | struct scic_controller_handler_methods *handlers; | ||
109 | irqreturn_t ret = IRQ_NONE; | 87 | irqreturn_t ret = IRQ_NONE; |
110 | 88 | ||
111 | /* | 89 | for_each_isci_host(ihost, pdev) { |
112 | * Since this is a legacy interrupt, either or both | 90 | struct scic_sds_controller *scic = ihost->core_controller; |
113 | * controllers could have triggered it. Thus, we have to call | 91 | |
114 | * the legacy interrupt handler for all controllers on the | 92 | if (isci_host_get_state(ihost) != isci_starting) { |
115 | * PCI function. | 93 | if (scic_sds_controller_isr(scic)) { |
116 | */ | 94 | if (isci_host_get_state(ihost) != isci_stopped) |
117 | for_each_isci_host(isci_host, pdev) { | 95 | tasklet_schedule(&ihost->completion_tasklet); |
118 | handlers = &isci_host->scic_irq_handlers[SCI_MSIX_NORMAL_VECTOR]; | 96 | else |
119 | 97 | dev_dbg(&ihost->pdev->dev, | |
120 | if (isci_host_get_state(isci_host) != isci_starting | ||
121 | && handlers->interrupt_handler) { | ||
122 | |||
123 | if (handlers->interrupt_handler(isci_host->core_controller)) { | ||
124 | if (isci_host_get_state(isci_host) != isci_stopped) { | ||
125 | tasklet_schedule( | ||
126 | &isci_host->completion_tasklet); | ||
127 | } else | ||
128 | dev_dbg(&isci_host->pdev->dev, | ||
129 | "%s: controller stopped\n", | 98 | "%s: controller stopped\n", |
130 | __func__); | 99 | __func__); |
131 | ret = IRQ_HANDLED; | 100 | ret = IRQ_HANDLED; |
132 | } | 101 | } |
133 | } else | 102 | } else |
134 | dev_warn(&isci_host->pdev->dev, | 103 | dev_warn(&ihost->pdev->dev, |
135 | "%s: get_handler_methods failed, " | 104 | "%s: get_handler_methods failed, " |
136 | "isci_host->status = 0x%x\n", | 105 | "ihost->status = 0x%x\n", |
137 | __func__, | 106 | __func__, |
138 | isci_host_get_state(isci_host)); | 107 | isci_host_get_state(ihost)); |
139 | } | 108 | } |
140 | return ret; | 109 | return ret; |
141 | } | 110 | } |
@@ -166,34 +135,9 @@ void isci_host_start_complete( | |||
166 | 135 | ||
167 | } | 136 | } |
168 | 137 | ||
169 | 138 | int isci_host_scan_finished(struct Scsi_Host *shost, unsigned long time) | |
170 | |||
171 | /** | ||
172 | * isci_host_scan_finished() - This function is one of the SCSI Host Template | ||
173 | * functions. The SCSI midlayer calls this function during a target scan, | ||
174 | * approx. once every 10 millisecs. | ||
175 | * @shost: This parameter specifies the SCSI host being scanned | ||
176 | * @time: This parameter specifies the number of ticks since the scan started. | ||
177 | * | ||
178 | * scan status, zero indicates the SCSI midlayer should continue to poll, | ||
179 | * otherwise assume controller is ready. | ||
180 | */ | ||
181 | int isci_host_scan_finished( | ||
182 | struct Scsi_Host *shost, | ||
183 | unsigned long time) | ||
184 | { | 139 | { |
185 | struct isci_host *isci_host | 140 | struct isci_host *isci_host = isci_host_from_sas_ha(SHOST_TO_SAS_HA(shost)); |
186 | = isci_host_from_sas_ha(SHOST_TO_SAS_HA(shost)); | ||
187 | |||
188 | struct scic_controller_handler_methods *handlers | ||
189 | = &isci_host->scic_irq_handlers[SCI_MSIX_NORMAL_VECTOR]; | ||
190 | |||
191 | if (handlers->interrupt_handler == NULL) { | ||
192 | dev_err(&isci_host->pdev->dev, | ||
193 | "%s: scic_controller_get_handler_methods failed\n", | ||
194 | __func__); | ||
195 | return 1; | ||
196 | } | ||
197 | 141 | ||
198 | /** | 142 | /** |
199 | * check interrupt_handler's status and call completion_handler if true, | 143 | * check interrupt_handler's status and call completion_handler if true, |
@@ -204,8 +148,8 @@ int isci_host_scan_finished( | |||
204 | * continue to return zero from thee scan_finished routine until | 148 | * continue to return zero from thee scan_finished routine until |
205 | * the scic_cb_controller_start_complete() call comes from the core. | 149 | * the scic_cb_controller_start_complete() call comes from the core. |
206 | **/ | 150 | **/ |
207 | if (handlers->interrupt_handler(isci_host->core_controller)) | 151 | if (scic_sds_controller_isr(isci_host->core_controller)) |
208 | handlers->completion_handler(isci_host->core_controller); | 152 | scic_sds_controller_completion_handler(isci_host->core_controller); |
209 | 153 | ||
210 | if (isci_starting == isci_host_get_state(isci_host) | 154 | if (isci_starting == isci_host_get_state(isci_host) |
211 | && time < (HZ * 10)) { | 155 | && time < (HZ * 10)) { |
@@ -363,8 +307,6 @@ static int isci_host_mdl_allocate_coherent( | |||
363 | static void isci_host_completion_routine(unsigned long data) | 307 | static void isci_host_completion_routine(unsigned long data) |
364 | { | 308 | { |
365 | struct isci_host *isci_host = (struct isci_host *)data; | 309 | struct isci_host *isci_host = (struct isci_host *)data; |
366 | struct scic_controller_handler_methods *handlers | ||
367 | = &isci_host->scic_irq_handlers[SCI_MSIX_NORMAL_VECTOR]; | ||
368 | struct list_head completed_request_list; | 310 | struct list_head completed_request_list; |
369 | struct list_head aborted_request_list; | 311 | struct list_head aborted_request_list; |
370 | struct list_head *current_position; | 312 | struct list_head *current_position; |
@@ -378,11 +320,8 @@ static void isci_host_completion_routine(unsigned long data) | |||
378 | 320 | ||
379 | spin_lock_irq(&isci_host->scic_lock); | 321 | spin_lock_irq(&isci_host->scic_lock); |
380 | 322 | ||
381 | if (handlers->completion_handler) { | 323 | scic_sds_controller_completion_handler(isci_host->core_controller); |
382 | handlers->completion_handler( | 324 | |
383 | isci_host->core_controller | ||
384 | ); | ||
385 | } | ||
386 | /* Take the lists of completed I/Os from the host. */ | 325 | /* Take the lists of completed I/Os from the host. */ |
387 | list_splice_init(&isci_host->requests_to_complete, | 326 | list_splice_init(&isci_host->requests_to_complete, |
388 | &completed_request_list); | 327 | &completed_request_list); |
@@ -544,8 +483,6 @@ int isci_host_init(struct isci_host *isci_host) | |||
544 | enum sci_status status; | 483 | enum sci_status status; |
545 | struct scic_sds_controller *controller; | 484 | struct scic_sds_controller *controller; |
546 | struct scic_sds_port *scic_port; | 485 | struct scic_sds_port *scic_port; |
547 | struct scic_controller_handler_methods *handlers | ||
548 | = &isci_host->scic_irq_handlers[0]; | ||
549 | union scic_oem_parameters scic_oem_params; | 486 | union scic_oem_parameters scic_oem_params; |
550 | union scic_user_parameters scic_user_params; | 487 | union scic_user_parameters scic_user_params; |
551 | const struct firmware *fw = NULL; | 488 | const struct firmware *fw = NULL; |
@@ -691,35 +628,8 @@ int isci_host_init(struct isci_host *isci_host) | |||
691 | goto out; | 628 | goto out; |
692 | } | 629 | } |
693 | 630 | ||
694 | /* @todo: use both MSI-X interrupts, and don't do indirect | ||
695 | * calls to the handlers just register direct calls | ||
696 | */ | ||
697 | if (isci_host->pdev->msix_enabled) { | ||
698 | status = scic_controller_get_handler_methods( | ||
699 | SCIC_MSIX_INTERRUPT_TYPE, | ||
700 | SCI_MSIX_DOUBLE_VECTOR, | ||
701 | handlers | ||
702 | ); | ||
703 | } else { | ||
704 | status = scic_controller_get_handler_methods( | ||
705 | SCIC_LEGACY_LINE_INTERRUPT_TYPE, | ||
706 | 0, | ||
707 | handlers | ||
708 | ); | ||
709 | } | ||
710 | |||
711 | if (status != SCI_SUCCESS) { | ||
712 | handlers->interrupt_handler = NULL; | ||
713 | handlers->completion_handler = NULL; | ||
714 | dev_err(&isci_host->pdev->dev, | ||
715 | "%s: scic_controller_get_handler_methods failed\n", | ||
716 | __func__); | ||
717 | } | ||
718 | |||
719 | tasklet_init(&isci_host->completion_tasklet, | 631 | tasklet_init(&isci_host->completion_tasklet, |
720 | isci_host_completion_routine, | 632 | isci_host_completion_routine, (unsigned long)isci_host); |
721 | (unsigned long)isci_host | ||
722 | ); | ||
723 | 633 | ||
724 | INIT_LIST_HEAD(&(isci_host->mdl_struct_list)); | 634 | INIT_LIST_HEAD(&(isci_host->mdl_struct_list)); |
725 | 635 | ||
diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 4f4b99d29589..421d3debdaed 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h | |||
@@ -53,13 +53,6 @@ | |||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
54 | */ | 54 | */ |
55 | 55 | ||
56 | /** | ||
57 | * This file contains the isci_module initialization routines. | ||
58 | * | ||
59 | * host.h | ||
60 | */ | ||
61 | |||
62 | |||
63 | 56 | ||
64 | #if !defined(_SCI_HOST_H_) | 57 | #if !defined(_SCI_HOST_H_) |
65 | #define _SCI_HOST_H_ | 58 | #define _SCI_HOST_H_ |
@@ -79,10 +72,6 @@ | |||
79 | #define SCI_SCU_BAR_SIZE (4*1024*1024) | 72 | #define SCI_SCU_BAR_SIZE (4*1024*1024) |
80 | #define SCI_IO_SPACE_BAR0 2 | 73 | #define SCI_IO_SPACE_BAR0 2 |
81 | #define SCI_IO_SPACE_BAR1 3 | 74 | #define SCI_IO_SPACE_BAR1 3 |
82 | #define SCI_MSIX_NORMAL_VECTOR 0 | ||
83 | #define SCI_MSIX_ERROR_VECTOR 1 | ||
84 | #define SCI_MSIX_SINGLE_VECTOR 1 | ||
85 | #define SCI_MSIX_DOUBLE_VECTOR 2 | ||
86 | #define ISCI_CAN_QUEUE_VAL 250 /* < SCI_MAX_IO_REQUESTS ? */ | 75 | #define ISCI_CAN_QUEUE_VAL 250 /* < SCI_MAX_IO_REQUESTS ? */ |
87 | #define SCIC_CONTROLLER_STOP_TIMEOUT 5000 | 76 | #define SCIC_CONTROLLER_STOP_TIMEOUT 5000 |
88 | 77 | ||
@@ -96,7 +85,6 @@ struct coherent_memory_info { | |||
96 | 85 | ||
97 | struct isci_host { | 86 | struct isci_host { |
98 | struct scic_sds_controller *core_controller; | 87 | struct scic_sds_controller *core_controller; |
99 | struct scic_controller_handler_methods scic_irq_handlers[SCI_NUM_MSI_X_INT]; | ||
100 | union scic_oem_parameters oem_parameters; | 88 | union scic_oem_parameters oem_parameters; |
101 | 89 | ||
102 | int id; /* unique within a given pci device */ | 90 | int id; /* unique within a given pci device */ |
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index e3d9b15d0cbf..f2bd92b81136 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c | |||
@@ -334,7 +334,7 @@ static int isci_setup_interrupts(struct pci_dev *pdev) | |||
334 | BUG_ON(!isci_host); | 334 | BUG_ON(!isci_host); |
335 | 335 | ||
336 | /* @todo: need to handle error case. */ | 336 | /* @todo: need to handle error case. */ |
337 | err = devm_request_irq(&pdev->dev, msix->vector, isci_isr, 0, | 337 | err = devm_request_irq(&pdev->dev, msix->vector, isci_msix_isr, 0, |
338 | DRV_NAME"-msix", isci_host); | 338 | DRV_NAME"-msix", isci_host); |
339 | if (!err) | 339 | if (!err) |
340 | continue; | 340 | continue; |
@@ -353,7 +353,7 @@ static int isci_setup_interrupts(struct pci_dev *pdev) | |||
353 | return 0; | 353 | return 0; |
354 | 354 | ||
355 | intx: | 355 | intx: |
356 | err = devm_request_irq(&pdev->dev, pdev->irq, isci_legacy_isr, | 356 | err = devm_request_irq(&pdev->dev, pdev->irq, isci_intx_isr, |
357 | IRQF_SHARED, DRV_NAME"-intx", pdev); | 357 | IRQF_SHARED, DRV_NAME"-intx", pdev); |
358 | 358 | ||
359 | return err; | 359 | return err; |
diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h index 6aee3c9c8827..3dc0f6c21174 100644 --- a/drivers/scsi/isci/isci.h +++ b/drivers/scsi/isci/isci.h | |||
@@ -113,8 +113,11 @@ struct isci_firmware { | |||
113 | u8 sas_addrs_size; | 113 | u8 sas_addrs_size; |
114 | }; | 114 | }; |
115 | 115 | ||
116 | irqreturn_t isci_isr(int vec, void *data); | 116 | irqreturn_t isci_msix_isr(int vec, void *data); |
117 | irqreturn_t isci_legacy_isr(int vec, void *data); | 117 | irqreturn_t isci_intx_isr(int vec, void *data); |
118 | |||
119 | bool scic_sds_controller_isr(struct scic_sds_controller *scic); | ||
120 | void scic_sds_controller_completion_handler(struct scic_sds_controller *scic); | ||
118 | 121 | ||
119 | enum sci_status isci_parse_oem_parameters( | 122 | enum sci_status isci_parse_oem_parameters( |
120 | union scic_oem_parameters *oem_params, | 123 | union scic_oem_parameters *oem_params, |