aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2011-02-18 12:25:05 -0500
committerDan Williams <dan.j.williams@intel.com>2011-07-03 06:55:27 -0400
commitc7ef4031f01301298bbaba2666740183cd399f8c (patch)
tree48f5508280b6a3032e52804dfde1c4b117d6bd3a
parent11c88986290712fc3ae6993af85a0f9a15886278 (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.c10
-rw-r--r--drivers/scsi/isci/host.c158
-rw-r--r--drivers/scsi/isci/host.h12
-rw-r--r--drivers/scsi/isci/init.c4
-rw-r--r--drivers/scsi/isci/isci.h7
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 */
1901static bool scic_sds_controller_normal_vector_interrupt_handler( 1901bool 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 */
1928static void scic_sds_controller_normal_vector_completion_handler( 1927void 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/** 65irqreturn_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 */
73irqreturn_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
104irqreturn_t isci_legacy_isr(int vec, void *data) 83irqreturn_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 138int 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 */
181int 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(
363static void isci_host_completion_routine(unsigned long data) 307static 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
97struct isci_host { 86struct 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
116irqreturn_t isci_isr(int vec, void *data); 116irqreturn_t isci_msix_isr(int vec, void *data);
117irqreturn_t isci_legacy_isr(int vec, void *data); 117irqreturn_t isci_intx_isr(int vec, void *data);
118
119bool scic_sds_controller_isr(struct scic_sds_controller *scic);
120void scic_sds_controller_completion_handler(struct scic_sds_controller *scic);
118 121
119enum sci_status isci_parse_oem_parameters( 122enum sci_status isci_parse_oem_parameters(
120 union scic_oem_parameters *oem_params, 123 union scic_oem_parameters *oem_params,