@@ -38,8 +38,13 @@ static irqreturn_t fnic_isr_legacy(int irq, void *data)
3838 fnic_log_q_error (fnic );
3939 }
4040
41+ if (pba & (1 << FNIC_INTX_DUMMY )) {
42+ atomic64_inc (& fnic -> fnic_stats .misc_stats .intx_dummy );
43+ vnic_intr_return_all_credits (& fnic -> intr [FNIC_INTX_DUMMY ]);
44+ }
45+
4146 if (pba & (1 << FNIC_INTX_WQ_RQ_COPYWQ )) {
42- work_done += fnic_wq_copy_cmpl_handler (fnic , io_completions );
47+ work_done += fnic_wq_copy_cmpl_handler (fnic , io_completions , FNIC_MQ_CQ_INDEX );
4348 work_done += fnic_wq_cmpl_handler (fnic , -1 );
4449 work_done += fnic_rq_cmpl_handler (fnic , -1 );
4550
@@ -60,7 +65,7 @@ static irqreturn_t fnic_isr_msi(int irq, void *data)
6065 fnic -> fnic_stats .misc_stats .last_isr_time = jiffies ;
6166 atomic64_inc (& fnic -> fnic_stats .misc_stats .isr_count );
6267
63- work_done += fnic_wq_copy_cmpl_handler (fnic , io_completions );
68+ work_done += fnic_wq_copy_cmpl_handler (fnic , io_completions , FNIC_MQ_CQ_INDEX );
6469 work_done += fnic_wq_cmpl_handler (fnic , -1 );
6570 work_done += fnic_rq_cmpl_handler (fnic , -1 );
6671
@@ -109,12 +114,22 @@ static irqreturn_t fnic_isr_msix_wq_copy(int irq, void *data)
109114{
110115 struct fnic * fnic = data ;
111116 unsigned long wq_copy_work_done = 0 ;
117+ int i ;
112118
113119 fnic -> fnic_stats .misc_stats .last_isr_time = jiffies ;
114120 atomic64_inc (& fnic -> fnic_stats .misc_stats .isr_count );
115121
116- wq_copy_work_done = fnic_wq_copy_cmpl_handler (fnic , io_completions );
117- vnic_intr_return_credits (& fnic -> intr [FNIC_MSIX_WQ_COPY ],
122+ i = irq - fnic -> msix [0 ].irq_num ;
123+ if (i >= fnic -> wq_copy_count + fnic -> copy_wq_base ||
124+ i < 0 || fnic -> msix [i ].irq_num != irq ) {
125+ for (i = fnic -> copy_wq_base ; i < fnic -> wq_copy_count + fnic -> copy_wq_base ; i ++ ) {
126+ if (fnic -> msix [i ].irq_num == irq )
127+ break ;
128+ }
129+ }
130+
131+ wq_copy_work_done = fnic_wq_copy_cmpl_handler (fnic , io_completions , i );
132+ vnic_intr_return_credits (& fnic -> intr [i ],
118133 wq_copy_work_done ,
119134 1 /* unmask intr */ ,
120135 1 /* reset intr timer */ );
@@ -128,7 +143,7 @@ static irqreturn_t fnic_isr_msix_err_notify(int irq, void *data)
128143 fnic -> fnic_stats .misc_stats .last_isr_time = jiffies ;
129144 atomic64_inc (& fnic -> fnic_stats .misc_stats .isr_count );
130145
131- vnic_intr_return_all_credits (& fnic -> intr [FNIC_MSIX_ERR_NOTIFY ]);
146+ vnic_intr_return_all_credits (& fnic -> intr [fnic -> err_intr_offset ]);
132147 fnic_log_q_error (fnic );
133148 fnic_handle_link_event (fnic );
134149
@@ -186,26 +201,30 @@ int fnic_request_intr(struct fnic *fnic)
186201 fnic -> msix [FNIC_MSIX_WQ ].isr = fnic_isr_msix_wq ;
187202 fnic -> msix [FNIC_MSIX_WQ ].devid = fnic ;
188203
189- sprintf (fnic -> msix [FNIC_MSIX_WQ_COPY ].devname ,
190- "%.11s-scsi-wq" , fnic -> name );
191- fnic -> msix [FNIC_MSIX_WQ_COPY ].isr = fnic_isr_msix_wq_copy ;
192- fnic -> msix [FNIC_MSIX_WQ_COPY ].devid = fnic ;
204+ for (i = fnic -> copy_wq_base ; i < fnic -> wq_copy_count + fnic -> copy_wq_base ; i ++ ) {
205+ sprintf (fnic -> msix [i ].devname ,
206+ "%.11s-scsi-wq-%d" , fnic -> name , i - FNIC_MSIX_WQ_COPY );
207+ fnic -> msix [i ].isr = fnic_isr_msix_wq_copy ;
208+ fnic -> msix [i ].devid = fnic ;
209+ }
193210
194- sprintf (fnic -> msix [FNIC_MSIX_ERR_NOTIFY ].devname ,
211+ sprintf (fnic -> msix [fnic -> err_intr_offset ].devname ,
195212 "%.11s-err-notify" , fnic -> name );
196- fnic -> msix [FNIC_MSIX_ERR_NOTIFY ].isr =
213+ fnic -> msix [fnic -> err_intr_offset ].isr =
197214 fnic_isr_msix_err_notify ;
198- fnic -> msix [FNIC_MSIX_ERR_NOTIFY ].devid = fnic ;
215+ fnic -> msix [fnic -> err_intr_offset ].devid = fnic ;
199216
200- for (i = 0 ; i < ARRAY_SIZE (fnic -> msix ); i ++ ) {
201- err = request_irq (pci_irq_vector (fnic -> pdev , i ),
202- fnic -> msix [i ].isr , 0 ,
203- fnic -> msix [i ].devname ,
204- fnic -> msix [i ].devid );
217+ for (i = 0 ; i < fnic -> intr_count ; i ++ ) {
218+ fnic -> msix [i ].irq_num = pci_irq_vector (fnic -> pdev , i );
219+
220+ err = request_irq (fnic -> msix [i ].irq_num ,
221+ fnic -> msix [i ].isr , 0 ,
222+ fnic -> msix [i ].devname ,
223+ fnic -> msix [i ].devid );
205224 if (err ) {
206- shost_printk (KERN_ERR , fnic -> lport -> host ,
207- "MSIX: request_irq"
208- " failed %d\n" , err );
225+ FNIC_ISR_DBG (KERN_ERR , fnic -> lport -> host , fnic -> fnic_num ,
226+ "request_irq failed with error: %d\n" ,
227+ err );
209228 fnic_free_intr (fnic );
210229 break ;
211230 }
@@ -220,44 +239,99 @@ int fnic_request_intr(struct fnic *fnic)
220239 return err ;
221240}
222241
223- int fnic_set_intr_mode (struct fnic * fnic )
242+ int fnic_set_intr_mode_msix (struct fnic * fnic )
224243{
225244 unsigned int n = ARRAY_SIZE (fnic -> rq );
226245 unsigned int m = ARRAY_SIZE (fnic -> wq );
227246 unsigned int o = ARRAY_SIZE (fnic -> hw_copy_wq );
247+ unsigned int min_irqs = n + m + 1 + 1 ; /*rq, raw wq, wq, err*/
228248
229249 /*
230- * Set interrupt mode (INTx, MSI, MSI-X) depending
231- * system capabilities.
232- *
233- * Try MSI-X first
234- *
235250 * We need n RQs, m WQs, o Copy WQs, n+m+o CQs, and n+m+o+1 INTRs
236251 * (last INTR is used for WQ/RQ errors and notification area)
237252 */
238- if (fnic -> rq_count >= n &&
239- fnic -> raw_wq_count >= m &&
240- fnic -> wq_copy_count >= o &&
241- fnic -> cq_count >= n + m + o ) {
242- int vecs = n + m + o + 1 ;
243-
244- if (pci_alloc_irq_vectors (fnic -> pdev , vecs , vecs ,
245- PCI_IRQ_MSIX ) == vecs ) {
253+ FNIC_ISR_DBG (KERN_INFO , fnic -> lport -> host , fnic -> fnic_num ,
254+ "rq-array size: %d wq-array size: %d copy-wq array size: %d\n" ,
255+ n , m , o );
256+ FNIC_ISR_DBG (KERN_INFO , fnic -> lport -> host , fnic -> fnic_num ,
257+ "rq_count: %d raw_wq_count: %d wq_copy_count: %d cq_count: %d\n" ,
258+ fnic -> rq_count , fnic -> raw_wq_count ,
259+ fnic -> wq_copy_count , fnic -> cq_count );
260+
261+ if (fnic -> rq_count <= n && fnic -> raw_wq_count <= m &&
262+ fnic -> wq_copy_count <= o ) {
263+ int vec_count = 0 ;
264+ int vecs = fnic -> rq_count + fnic -> raw_wq_count + fnic -> wq_copy_count + 1 ;
265+
266+ vec_count = pci_alloc_irq_vectors (fnic -> pdev , min_irqs , vecs ,
267+ PCI_IRQ_MSIX | PCI_IRQ_AFFINITY );
268+ FNIC_ISR_DBG (KERN_INFO , fnic -> lport -> host , fnic -> fnic_num ,
269+ "allocated %d MSI-X vectors\n" ,
270+ vec_count );
271+
272+ if (vec_count > 0 ) {
273+ if (vec_count < vecs ) {
274+ FNIC_ISR_DBG (KERN_ERR , fnic -> lport -> host , fnic -> fnic_num ,
275+ "interrupts number mismatch: vec_count: %d vecs: %d\n" ,
276+ vec_count , vecs );
277+ if (vec_count < min_irqs ) {
278+ FNIC_ISR_DBG (KERN_ERR , fnic -> lport -> host , fnic -> fnic_num ,
279+ "no interrupts for copy wq\n" );
280+ return 1 ;
281+ }
282+ }
283+
246284 fnic -> rq_count = n ;
247285 fnic -> raw_wq_count = m ;
248- fnic -> wq_copy_count = o ;
249- fnic -> wq_count = m + o ;
250- fnic -> cq_count = n + m + o ;
251- fnic -> intr_count = vecs ;
252- fnic -> err_intr_offset = FNIC_MSIX_ERR_NOTIFY ;
253-
254- FNIC_ISR_DBG (KERN_DEBUG , fnic -> lport -> host ,
255- "Using MSI-X Interrupts\n" );
256- vnic_dev_set_intr_mode (fnic -> vdev ,
257- VNIC_DEV_INTR_MODE_MSIX );
286+ fnic -> copy_wq_base = fnic -> rq_count + fnic -> raw_wq_count ;
287+ fnic -> wq_copy_count = vec_count - n - m - 1 ;
288+ fnic -> wq_count = fnic -> raw_wq_count + fnic -> wq_copy_count ;
289+ if (fnic -> cq_count != vec_count - 1 ) {
290+ FNIC_ISR_DBG (KERN_ERR , fnic -> lport -> host , fnic -> fnic_num ,
291+ "CQ count: %d does not match MSI-X vector count: %d\n" ,
292+ fnic -> cq_count , vec_count );
293+ fnic -> cq_count = vec_count - 1 ;
294+ }
295+ fnic -> intr_count = vec_count ;
296+ fnic -> err_intr_offset = fnic -> rq_count + fnic -> wq_count ;
297+
298+ FNIC_ISR_DBG (KERN_INFO , fnic -> lport -> host , fnic -> fnic_num ,
299+ "rq_count: %d raw_wq_count: %d copy_wq_base: %d\n" ,
300+ fnic -> rq_count ,
301+ fnic -> raw_wq_count , fnic -> copy_wq_base );
302+
303+ FNIC_ISR_DBG (KERN_INFO , fnic -> lport -> host , fnic -> fnic_num ,
304+ "wq_copy_count: %d wq_count: %d cq_count: %d\n" ,
305+ fnic -> wq_copy_count ,
306+ fnic -> wq_count , fnic -> cq_count );
307+
308+ FNIC_ISR_DBG (KERN_INFO , fnic -> lport -> host , fnic -> fnic_num ,
309+ "intr_count: %d err_intr_offset: %u" ,
310+ fnic -> intr_count ,
311+ fnic -> err_intr_offset );
312+
313+ vnic_dev_set_intr_mode (fnic -> vdev , VNIC_DEV_INTR_MODE_MSIX );
314+ FNIC_ISR_DBG (KERN_INFO , fnic -> lport -> host , fnic -> fnic_num ,
315+ "fnic using MSI-X\n" );
258316 return 0 ;
259317 }
260318 }
319+ return 1 ;
320+ }
321+
322+ int fnic_set_intr_mode (struct fnic * fnic )
323+ {
324+ int ret_status = 0 ;
325+
326+ /*
327+ * Set interrupt mode (INTx, MSI, MSI-X) depending
328+ * system capabilities.
329+ *
330+ * Try MSI-X first
331+ */
332+ ret_status = fnic_set_intr_mode_msix (fnic );
333+ if (ret_status == 0 )
334+ return ret_status ;
261335
262336 /*
263337 * Next try MSI
@@ -277,7 +351,7 @@ int fnic_set_intr_mode(struct fnic *fnic)
277351 fnic -> intr_count = 1 ;
278352 fnic -> err_intr_offset = 0 ;
279353
280- FNIC_ISR_DBG (KERN_DEBUG , fnic -> lport -> host ,
354+ FNIC_ISR_DBG (KERN_DEBUG , fnic -> lport -> host , fnic -> fnic_num ,
281355 "Using MSI Interrupts\n" );
282356 vnic_dev_set_intr_mode (fnic -> vdev , VNIC_DEV_INTR_MODE_MSI );
283357
@@ -303,7 +377,7 @@ int fnic_set_intr_mode(struct fnic *fnic)
303377 fnic -> cq_count = 3 ;
304378 fnic -> intr_count = 3 ;
305379
306- FNIC_ISR_DBG (KERN_DEBUG , fnic -> lport -> host ,
380+ FNIC_ISR_DBG (KERN_DEBUG , fnic -> lport -> host , fnic -> fnic_num ,
307381 "Using Legacy Interrupts\n" );
308382 vnic_dev_set_intr_mode (fnic -> vdev , VNIC_DEV_INTR_MODE_INTX );
309383
0 commit comments