diff options
author | James Smart <James.Smart@Emulex.Com> | 2008-06-14 22:52:53 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-07-12 09:22:28 -0400 |
commit | 5e9d9b8276980fc5dfa88ce34f6ec88ce3026232 (patch) | |
tree | 30b495edab629068f929a32f88a66ad705687f34 /drivers/scsi/lpfc | |
parent | 0d2b6b83030d6a88cbf7db57f84f2daf0e0b251b (diff) |
[SCSI] lpfc 8.2.7 : Rework the worker thread
Rework of the worker thread to make it more efficient.
Make a finer-grain notfication of pending work so less time is
spent checking conditions. Also made other general cleanups.
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 20 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_ct.c | 16 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 33 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 93 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 13 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 26 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 36 |
7 files changed, 97 insertions, 140 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index ec0b0f6e5e1a..e3e5b540e36c 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
@@ -59,6 +59,9 @@ struct lpfc_sli2_slim; | |||
59 | 59 | ||
60 | #define MAX_HBAEVT 32 | 60 | #define MAX_HBAEVT 32 |
61 | 61 | ||
62 | /* lpfc wait event data ready flag */ | ||
63 | #define LPFC_DATA_READY (1<<0) | ||
64 | |||
62 | enum lpfc_polling_flags { | 65 | enum lpfc_polling_flags { |
63 | ENABLE_FCP_RING_POLLING = 0x1, | 66 | ENABLE_FCP_RING_POLLING = 0x1, |
64 | DISABLE_FCP_RING_INT = 0x2 | 67 | DISABLE_FCP_RING_INT = 0x2 |
@@ -425,9 +428,6 @@ struct lpfc_hba { | |||
425 | 428 | ||
426 | uint16_t pci_cfg_value; | 429 | uint16_t pci_cfg_value; |
427 | 430 | ||
428 | uint8_t work_found; | ||
429 | #define LPFC_MAX_WORKER_ITERATION 4 | ||
430 | |||
431 | uint8_t fc_linkspeed; /* Link speed after last READ_LA */ | 431 | uint8_t fc_linkspeed; /* Link speed after last READ_LA */ |
432 | 432 | ||
433 | uint32_t fc_eventTag; /* event tag for link attention */ | 433 | uint32_t fc_eventTag; /* event tag for link attention */ |
@@ -489,8 +489,9 @@ struct lpfc_hba { | |||
489 | uint32_t work_hs; /* HS stored in case of ERRAT */ | 489 | uint32_t work_hs; /* HS stored in case of ERRAT */ |
490 | uint32_t work_status[2]; /* Extra status from SLIM */ | 490 | uint32_t work_status[2]; /* Extra status from SLIM */ |
491 | 491 | ||
492 | wait_queue_head_t *work_wait; | 492 | wait_queue_head_t work_waitq; |
493 | struct task_struct *worker_thread; | 493 | struct task_struct *worker_thread; |
494 | long data_flags; | ||
494 | 495 | ||
495 | uint32_t hbq_in_use; /* HBQs in use flag */ | 496 | uint32_t hbq_in_use; /* HBQs in use flag */ |
496 | struct list_head hbqbuf_in_list; /* in-fly hbq buffer list */ | 497 | struct list_head hbqbuf_in_list; /* in-fly hbq buffer list */ |
@@ -637,6 +638,17 @@ lpfc_is_link_up(struct lpfc_hba *phba) | |||
637 | phba->link_state == LPFC_HBA_READY; | 638 | phba->link_state == LPFC_HBA_READY; |
638 | } | 639 | } |
639 | 640 | ||
641 | static inline void | ||
642 | lpfc_worker_wake_up(struct lpfc_hba *phba) | ||
643 | { | ||
644 | /* Set the lpfc data pending flag */ | ||
645 | set_bit(LPFC_DATA_READY, &phba->data_flags); | ||
646 | |||
647 | /* Wake up worker thread */ | ||
648 | wake_up(&phba->work_waitq); | ||
649 | return; | ||
650 | } | ||
651 | |||
640 | #define FC_REG_DUMP_EVENT 0x10 /* Register for Dump events */ | 652 | #define FC_REG_DUMP_EVENT 0x10 /* Register for Dump events */ |
641 | #define FC_REG_TEMPERATURE_EVENT 0x20 /* Register for temperature | 653 | #define FC_REG_TEMPERATURE_EVENT 0x20 /* Register for temperature |
642 | event */ | 654 | event */ |
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 153afae567b5..5442ce33615a 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c | |||
@@ -1679,20 +1679,18 @@ lpfc_fdmi_tmo(unsigned long ptr) | |||
1679 | { | 1679 | { |
1680 | struct lpfc_vport *vport = (struct lpfc_vport *)ptr; | 1680 | struct lpfc_vport *vport = (struct lpfc_vport *)ptr; |
1681 | struct lpfc_hba *phba = vport->phba; | 1681 | struct lpfc_hba *phba = vport->phba; |
1682 | uint32_t tmo_posted; | ||
1682 | unsigned long iflag; | 1683 | unsigned long iflag; |
1683 | 1684 | ||
1684 | spin_lock_irqsave(&vport->work_port_lock, iflag); | 1685 | spin_lock_irqsave(&vport->work_port_lock, iflag); |
1685 | if (!(vport->work_port_events & WORKER_FDMI_TMO)) { | 1686 | tmo_posted = vport->work_port_events & WORKER_FDMI_TMO; |
1687 | if (!tmo_posted) | ||
1686 | vport->work_port_events |= WORKER_FDMI_TMO; | 1688 | vport->work_port_events |= WORKER_FDMI_TMO; |
1687 | spin_unlock_irqrestore(&vport->work_port_lock, iflag); | 1689 | spin_unlock_irqrestore(&vport->work_port_lock, iflag); |
1688 | 1690 | ||
1689 | spin_lock_irqsave(&phba->hbalock, iflag); | 1691 | if (!tmo_posted) |
1690 | if (phba->work_wait) | 1692 | lpfc_worker_wake_up(phba); |
1691 | lpfc_worker_wake_up(phba); | 1693 | return; |
1692 | spin_unlock_irqrestore(&phba->hbalock, iflag); | ||
1693 | } | ||
1694 | else | ||
1695 | spin_unlock_irqrestore(&vport->work_port_lock, iflag); | ||
1696 | } | 1694 | } |
1697 | 1695 | ||
1698 | void | 1696 | void |
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index d418c7c1251e..5d69dee85a8d 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -1813,11 +1813,11 @@ lpfc_els_retry_delay(unsigned long ptr) | |||
1813 | * count until the queued work is done | 1813 | * count until the queued work is done |
1814 | */ | 1814 | */ |
1815 | evtp->evt_arg1 = lpfc_nlp_get(ndlp); | 1815 | evtp->evt_arg1 = lpfc_nlp_get(ndlp); |
1816 | evtp->evt = LPFC_EVT_ELS_RETRY; | 1816 | if (evtp->evt_arg1) { |
1817 | list_add_tail(&evtp->evt_listp, &phba->work_list); | 1817 | evtp->evt = LPFC_EVT_ELS_RETRY; |
1818 | if (phba->work_wait) | 1818 | list_add_tail(&evtp->evt_listp, &phba->work_list); |
1819 | lpfc_worker_wake_up(phba); | 1819 | lpfc_worker_wake_up(phba); |
1820 | 1820 | } | |
1821 | spin_unlock_irqrestore(&phba->hbalock, flags); | 1821 | spin_unlock_irqrestore(&phba->hbalock, flags); |
1822 | return; | 1822 | return; |
1823 | } | 1823 | } |
@@ -3802,20 +3802,17 @@ lpfc_els_timeout(unsigned long ptr) | |||
3802 | { | 3802 | { |
3803 | struct lpfc_vport *vport = (struct lpfc_vport *) ptr; | 3803 | struct lpfc_vport *vport = (struct lpfc_vport *) ptr; |
3804 | struct lpfc_hba *phba = vport->phba; | 3804 | struct lpfc_hba *phba = vport->phba; |
3805 | uint32_t tmo_posted; | ||
3805 | unsigned long iflag; | 3806 | unsigned long iflag; |
3806 | 3807 | ||
3807 | spin_lock_irqsave(&vport->work_port_lock, iflag); | 3808 | spin_lock_irqsave(&vport->work_port_lock, iflag); |
3808 | if ((vport->work_port_events & WORKER_ELS_TMO) == 0) { | 3809 | tmo_posted = vport->work_port_events & WORKER_ELS_TMO; |
3810 | if (!tmo_posted) | ||
3809 | vport->work_port_events |= WORKER_ELS_TMO; | 3811 | vport->work_port_events |= WORKER_ELS_TMO; |
3810 | spin_unlock_irqrestore(&vport->work_port_lock, iflag); | 3812 | spin_unlock_irqrestore(&vport->work_port_lock, iflag); |
3811 | 3813 | ||
3812 | spin_lock_irqsave(&phba->hbalock, iflag); | 3814 | if (!tmo_posted) |
3813 | if (phba->work_wait) | 3815 | lpfc_worker_wake_up(phba); |
3814 | lpfc_worker_wake_up(phba); | ||
3815 | spin_unlock_irqrestore(&phba->hbalock, iflag); | ||
3816 | } | ||
3817 | else | ||
3818 | spin_unlock_irqrestore(&vport->work_port_lock, iflag); | ||
3819 | return; | 3816 | return; |
3820 | } | 3817 | } |
3821 | 3818 | ||
@@ -4769,18 +4766,16 @@ lpfc_fabric_block_timeout(unsigned long ptr) | |||
4769 | struct lpfc_hba *phba = (struct lpfc_hba *) ptr; | 4766 | struct lpfc_hba *phba = (struct lpfc_hba *) ptr; |
4770 | unsigned long iflags; | 4767 | unsigned long iflags; |
4771 | uint32_t tmo_posted; | 4768 | uint32_t tmo_posted; |
4769 | |||
4772 | spin_lock_irqsave(&phba->pport->work_port_lock, iflags); | 4770 | spin_lock_irqsave(&phba->pport->work_port_lock, iflags); |
4773 | tmo_posted = phba->pport->work_port_events & WORKER_FABRIC_BLOCK_TMO; | 4771 | tmo_posted = phba->pport->work_port_events & WORKER_FABRIC_BLOCK_TMO; |
4774 | if (!tmo_posted) | 4772 | if (!tmo_posted) |
4775 | phba->pport->work_port_events |= WORKER_FABRIC_BLOCK_TMO; | 4773 | phba->pport->work_port_events |= WORKER_FABRIC_BLOCK_TMO; |
4776 | spin_unlock_irqrestore(&phba->pport->work_port_lock, iflags); | 4774 | spin_unlock_irqrestore(&phba->pport->work_port_lock, iflags); |
4777 | 4775 | ||
4778 | if (!tmo_posted) { | 4776 | if (!tmo_posted) |
4779 | spin_lock_irqsave(&phba->hbalock, iflags); | 4777 | lpfc_worker_wake_up(phba); |
4780 | if (phba->work_wait) | 4778 | return; |
4781 | lpfc_worker_wake_up(phba); | ||
4782 | spin_unlock_irqrestore(&phba->hbalock, iflags); | ||
4783 | } | ||
4784 | } | 4779 | } |
4785 | 4780 | ||
4786 | static void | 4781 | static void |
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index f3dc19dfac5b..ba4873c9e2c3 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -153,11 +153,11 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) | |||
153 | * count until this queued work is done | 153 | * count until this queued work is done |
154 | */ | 154 | */ |
155 | evtp->evt_arg1 = lpfc_nlp_get(ndlp); | 155 | evtp->evt_arg1 = lpfc_nlp_get(ndlp); |
156 | evtp->evt = LPFC_EVT_DEV_LOSS; | 156 | if (evtp->evt_arg1) { |
157 | list_add_tail(&evtp->evt_listp, &phba->work_list); | 157 | evtp->evt = LPFC_EVT_DEV_LOSS; |
158 | if (phba->work_wait) | 158 | list_add_tail(&evtp->evt_listp, &phba->work_list); |
159 | wake_up(phba->work_wait); | 159 | lpfc_worker_wake_up(phba); |
160 | 160 | } | |
161 | spin_unlock_irq(&phba->hbalock); | 161 | spin_unlock_irq(&phba->hbalock); |
162 | 162 | ||
163 | return; | 163 | return; |
@@ -276,14 +276,6 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) | |||
276 | lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM); | 276 | lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM); |
277 | } | 277 | } |
278 | 278 | ||
279 | |||
280 | void | ||
281 | lpfc_worker_wake_up(struct lpfc_hba *phba) | ||
282 | { | ||
283 | wake_up(phba->work_wait); | ||
284 | return; | ||
285 | } | ||
286 | |||
287 | static void | 279 | static void |
288 | lpfc_work_list_done(struct lpfc_hba *phba) | 280 | lpfc_work_list_done(struct lpfc_hba *phba) |
289 | { | 281 | { |
@@ -429,6 +421,8 @@ lpfc_work_done(struct lpfc_hba *phba) | |||
429 | || (pring->flag & LPFC_DEFERRED_RING_EVENT)) { | 421 | || (pring->flag & LPFC_DEFERRED_RING_EVENT)) { |
430 | if (pring->flag & LPFC_STOP_IOCB_EVENT) { | 422 | if (pring->flag & LPFC_STOP_IOCB_EVENT) { |
431 | pring->flag |= LPFC_DEFERRED_RING_EVENT; | 423 | pring->flag |= LPFC_DEFERRED_RING_EVENT; |
424 | /* Set the lpfc data pending flag */ | ||
425 | set_bit(LPFC_DATA_READY, &phba->data_flags); | ||
432 | } else { | 426 | } else { |
433 | pring->flag &= ~LPFC_DEFERRED_RING_EVENT; | 427 | pring->flag &= ~LPFC_DEFERRED_RING_EVENT; |
434 | lpfc_sli_handle_slow_ring_event(phba, pring, | 428 | lpfc_sli_handle_slow_ring_event(phba, pring, |
@@ -459,69 +453,29 @@ lpfc_work_done(struct lpfc_hba *phba) | |||
459 | lpfc_work_list_done(phba); | 453 | lpfc_work_list_done(phba); |
460 | } | 454 | } |
461 | 455 | ||
462 | static int | ||
463 | check_work_wait_done(struct lpfc_hba *phba) | ||
464 | { | ||
465 | struct lpfc_vport *vport; | ||
466 | struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING]; | ||
467 | int rc = 0; | ||
468 | |||
469 | spin_lock_irq(&phba->hbalock); | ||
470 | list_for_each_entry(vport, &phba->port_list, listentry) { | ||
471 | if (vport->work_port_events) { | ||
472 | rc = 1; | ||
473 | break; | ||
474 | } | ||
475 | } | ||
476 | if (rc || phba->work_ha || (!list_empty(&phba->work_list)) || | ||
477 | kthread_should_stop() || pring->flag & LPFC_DEFERRED_RING_EVENT) { | ||
478 | rc = 1; | ||
479 | phba->work_found++; | ||
480 | } else | ||
481 | phba->work_found = 0; | ||
482 | spin_unlock_irq(&phba->hbalock); | ||
483 | return rc; | ||
484 | } | ||
485 | |||
486 | |||
487 | int | 456 | int |
488 | lpfc_do_work(void *p) | 457 | lpfc_do_work(void *p) |
489 | { | 458 | { |
490 | struct lpfc_hba *phba = p; | 459 | struct lpfc_hba *phba = p; |
491 | int rc; | 460 | int rc; |
492 | DECLARE_WAIT_QUEUE_HEAD_ONSTACK(work_waitq); | ||
493 | 461 | ||
494 | set_user_nice(current, -20); | 462 | set_user_nice(current, -20); |
495 | phba->work_wait = &work_waitq; | 463 | phba->data_flags = 0; |
496 | phba->work_found = 0; | ||
497 | 464 | ||
498 | while (1) { | 465 | while (1) { |
499 | 466 | /* wait and check worker queue activities */ | |
500 | rc = wait_event_interruptible(work_waitq, | 467 | rc = wait_event_interruptible(phba->work_waitq, |
501 | check_work_wait_done(phba)); | 468 | (test_and_clear_bit(LPFC_DATA_READY, |
502 | 469 | &phba->data_flags) | |
470 | || kthread_should_stop())); | ||
503 | BUG_ON(rc); | 471 | BUG_ON(rc); |
504 | 472 | ||
505 | if (kthread_should_stop()) | 473 | if (kthread_should_stop()) |
506 | break; | 474 | break; |
507 | 475 | ||
476 | /* Attend pending lpfc data processing */ | ||
508 | lpfc_work_done(phba); | 477 | lpfc_work_done(phba); |
509 | |||
510 | /* If there is alot of slow ring work, like during link up | ||
511 | * check_work_wait_done() may cause this thread to not give | ||
512 | * up the CPU for very long periods of time. This may cause | ||
513 | * soft lockups or other problems. To avoid these situations | ||
514 | * give up the CPU here after LPFC_MAX_WORKER_ITERATION | ||
515 | * consecutive iterations. | ||
516 | */ | ||
517 | if (phba->work_found >= LPFC_MAX_WORKER_ITERATION) { | ||
518 | phba->work_found = 0; | ||
519 | schedule(); | ||
520 | } | ||
521 | } | 478 | } |
522 | spin_lock_irq(&phba->hbalock); | ||
523 | phba->work_wait = NULL; | ||
524 | spin_unlock_irq(&phba->hbalock); | ||
525 | return 0; | 479 | return 0; |
526 | } | 480 | } |
527 | 481 | ||
@@ -551,10 +505,10 @@ lpfc_workq_post_event(struct lpfc_hba *phba, void *arg1, void *arg2, | |||
551 | 505 | ||
552 | spin_lock_irqsave(&phba->hbalock, flags); | 506 | spin_lock_irqsave(&phba->hbalock, flags); |
553 | list_add_tail(&evtp->evt_listp, &phba->work_list); | 507 | list_add_tail(&evtp->evt_listp, &phba->work_list); |
554 | if (phba->work_wait) | ||
555 | lpfc_worker_wake_up(phba); | ||
556 | spin_unlock_irqrestore(&phba->hbalock, flags); | 508 | spin_unlock_irqrestore(&phba->hbalock, flags); |
557 | 509 | ||
510 | lpfc_worker_wake_up(phba); | ||
511 | |||
558 | return 1; | 512 | return 1; |
559 | } | 513 | } |
560 | 514 | ||
@@ -2636,21 +2590,20 @@ lpfc_disc_timeout(unsigned long ptr) | |||
2636 | { | 2590 | { |
2637 | struct lpfc_vport *vport = (struct lpfc_vport *) ptr; | 2591 | struct lpfc_vport *vport = (struct lpfc_vport *) ptr; |
2638 | struct lpfc_hba *phba = vport->phba; | 2592 | struct lpfc_hba *phba = vport->phba; |
2593 | uint32_t tmo_posted; | ||
2639 | unsigned long flags = 0; | 2594 | unsigned long flags = 0; |
2640 | 2595 | ||
2641 | if (unlikely(!phba)) | 2596 | if (unlikely(!phba)) |
2642 | return; | 2597 | return; |
2643 | 2598 | ||
2644 | if ((vport->work_port_events & WORKER_DISC_TMO) == 0) { | 2599 | spin_lock_irqsave(&vport->work_port_lock, flags); |
2645 | spin_lock_irqsave(&vport->work_port_lock, flags); | 2600 | tmo_posted = vport->work_port_events & WORKER_DISC_TMO; |
2601 | if (!tmo_posted) | ||
2646 | vport->work_port_events |= WORKER_DISC_TMO; | 2602 | vport->work_port_events |= WORKER_DISC_TMO; |
2647 | spin_unlock_irqrestore(&vport->work_port_lock, flags); | 2603 | spin_unlock_irqrestore(&vport->work_port_lock, flags); |
2648 | 2604 | ||
2649 | spin_lock_irqsave(&phba->hbalock, flags); | 2605 | if (!tmo_posted) |
2650 | if (phba->work_wait) | 2606 | lpfc_worker_wake_up(phba); |
2651 | lpfc_worker_wake_up(phba); | ||
2652 | spin_unlock_irqrestore(&phba->hbalock, flags); | ||
2653 | } | ||
2654 | return; | 2607 | return; |
2655 | } | 2608 | } |
2656 | 2609 | ||
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 6fcddda58512..53cedbafffba 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -551,18 +551,18 @@ static void | |||
551 | lpfc_hb_timeout(unsigned long ptr) | 551 | lpfc_hb_timeout(unsigned long ptr) |
552 | { | 552 | { |
553 | struct lpfc_hba *phba; | 553 | struct lpfc_hba *phba; |
554 | uint32_t tmo_posted; | ||
554 | unsigned long iflag; | 555 | unsigned long iflag; |
555 | 556 | ||
556 | phba = (struct lpfc_hba *)ptr; | 557 | phba = (struct lpfc_hba *)ptr; |
557 | spin_lock_irqsave(&phba->pport->work_port_lock, iflag); | 558 | spin_lock_irqsave(&phba->pport->work_port_lock, iflag); |
558 | if (!(phba->pport->work_port_events & WORKER_HB_TMO)) | 559 | tmo_posted = phba->pport->work_port_events & WORKER_HB_TMO; |
560 | if (!tmo_posted) | ||
559 | phba->pport->work_port_events |= WORKER_HB_TMO; | 561 | phba->pport->work_port_events |= WORKER_HB_TMO; |
560 | spin_unlock_irqrestore(&phba->pport->work_port_lock, iflag); | 562 | spin_unlock_irqrestore(&phba->pport->work_port_lock, iflag); |
561 | 563 | ||
562 | spin_lock_irqsave(&phba->hbalock, iflag); | 564 | if (!tmo_posted) |
563 | if (phba->work_wait) | 565 | lpfc_worker_wake_up(phba); |
564 | wake_up(phba->work_wait); | ||
565 | spin_unlock_irqrestore(&phba->hbalock, iflag); | ||
566 | return; | 566 | return; |
567 | } | 567 | } |
568 | 568 | ||
@@ -2104,6 +2104,9 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
2104 | phba->work_ha_mask = (HA_ERATT|HA_MBATT|HA_LATT); | 2104 | phba->work_ha_mask = (HA_ERATT|HA_MBATT|HA_LATT); |
2105 | phba->work_ha_mask |= (HA_RXMASK << (LPFC_ELS_RING * 4)); | 2105 | phba->work_ha_mask |= (HA_RXMASK << (LPFC_ELS_RING * 4)); |
2106 | 2106 | ||
2107 | /* Initialize the wait queue head for the kernel thread */ | ||
2108 | init_waitqueue_head(&phba->work_waitq); | ||
2109 | |||
2107 | /* Startup the kernel thread for this host adapter. */ | 2110 | /* Startup the kernel thread for this host adapter. */ |
2108 | phba->worker_thread = kthread_run(lpfc_do_work, phba, | 2111 | phba->worker_thread = kthread_run(lpfc_do_work, phba, |
2109 | "lpfc_worker_%d", phba->brd_no); | 2112 | "lpfc_worker_%d", phba->brd_no); |
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 3926affaf727..1e88b7a8a451 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
@@ -50,6 +50,7 @@ void | |||
50 | lpfc_adjust_queue_depth(struct lpfc_hba *phba) | 50 | lpfc_adjust_queue_depth(struct lpfc_hba *phba) |
51 | { | 51 | { |
52 | unsigned long flags; | 52 | unsigned long flags; |
53 | uint32_t evt_posted; | ||
53 | 54 | ||
54 | spin_lock_irqsave(&phba->hbalock, flags); | 55 | spin_lock_irqsave(&phba->hbalock, flags); |
55 | atomic_inc(&phba->num_rsrc_err); | 56 | atomic_inc(&phba->num_rsrc_err); |
@@ -65,17 +66,13 @@ lpfc_adjust_queue_depth(struct lpfc_hba *phba) | |||
65 | spin_unlock_irqrestore(&phba->hbalock, flags); | 66 | spin_unlock_irqrestore(&phba->hbalock, flags); |
66 | 67 | ||
67 | spin_lock_irqsave(&phba->pport->work_port_lock, flags); | 68 | spin_lock_irqsave(&phba->pport->work_port_lock, flags); |
68 | if ((phba->pport->work_port_events & | 69 | evt_posted = phba->pport->work_port_events & WORKER_RAMP_DOWN_QUEUE; |
69 | WORKER_RAMP_DOWN_QUEUE) == 0) { | 70 | if (!evt_posted) |
70 | phba->pport->work_port_events |= WORKER_RAMP_DOWN_QUEUE; | 71 | phba->pport->work_port_events |= WORKER_RAMP_DOWN_QUEUE; |
71 | } | ||
72 | spin_unlock_irqrestore(&phba->pport->work_port_lock, flags); | 72 | spin_unlock_irqrestore(&phba->pport->work_port_lock, flags); |
73 | 73 | ||
74 | spin_lock_irqsave(&phba->hbalock, flags); | 74 | if (!evt_posted) |
75 | if (phba->work_wait) | 75 | lpfc_worker_wake_up(phba); |
76 | wake_up(phba->work_wait); | ||
77 | spin_unlock_irqrestore(&phba->hbalock, flags); | ||
78 | |||
79 | return; | 76 | return; |
80 | } | 77 | } |
81 | 78 | ||
@@ -89,6 +86,7 @@ lpfc_rampup_queue_depth(struct lpfc_vport *vport, | |||
89 | { | 86 | { |
90 | unsigned long flags; | 87 | unsigned long flags; |
91 | struct lpfc_hba *phba = vport->phba; | 88 | struct lpfc_hba *phba = vport->phba; |
89 | uint32_t evt_posted; | ||
92 | atomic_inc(&phba->num_cmd_success); | 90 | atomic_inc(&phba->num_cmd_success); |
93 | 91 | ||
94 | if (vport->cfg_lun_queue_depth <= sdev->queue_depth) | 92 | if (vport->cfg_lun_queue_depth <= sdev->queue_depth) |
@@ -103,16 +101,14 @@ lpfc_rampup_queue_depth(struct lpfc_vport *vport, | |||
103 | spin_unlock_irqrestore(&phba->hbalock, flags); | 101 | spin_unlock_irqrestore(&phba->hbalock, flags); |
104 | 102 | ||
105 | spin_lock_irqsave(&phba->pport->work_port_lock, flags); | 103 | spin_lock_irqsave(&phba->pport->work_port_lock, flags); |
106 | if ((phba->pport->work_port_events & | 104 | evt_posted = phba->pport->work_port_events & WORKER_RAMP_UP_QUEUE; |
107 | WORKER_RAMP_UP_QUEUE) == 0) { | 105 | if (!evt_posted) |
108 | phba->pport->work_port_events |= WORKER_RAMP_UP_QUEUE; | 106 | phba->pport->work_port_events |= WORKER_RAMP_UP_QUEUE; |
109 | } | ||
110 | spin_unlock_irqrestore(&phba->pport->work_port_lock, flags); | 107 | spin_unlock_irqrestore(&phba->pport->work_port_lock, flags); |
111 | 108 | ||
112 | spin_lock_irqsave(&phba->hbalock, flags); | 109 | if (!evt_posted) |
113 | if (phba->work_wait) | 110 | lpfc_worker_wake_up(phba); |
114 | wake_up(phba->work_wait); | 111 | return; |
115 | spin_unlock_irqrestore(&phba->hbalock, flags); | ||
116 | } | 112 | } |
117 | 113 | ||
118 | void | 114 | void |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 70a0a9eab211..3dba3a967ed1 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -324,9 +324,7 @@ lpfc_sli_next_iocb_slot (struct lpfc_hba *phba, struct lpfc_sli_ring *pring) | |||
324 | phba->work_ha |= HA_ERATT; | 324 | phba->work_ha |= HA_ERATT; |
325 | phba->work_hs = HS_FFER3; | 325 | phba->work_hs = HS_FFER3; |
326 | 326 | ||
327 | /* hbalock should already be held */ | 327 | lpfc_worker_wake_up(phba); |
328 | if (phba->work_wait) | ||
329 | lpfc_worker_wake_up(phba); | ||
330 | 328 | ||
331 | return NULL; | 329 | return NULL; |
332 | } | 330 | } |
@@ -1309,9 +1307,7 @@ lpfc_sli_rsp_pointers_error(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) | |||
1309 | phba->work_ha |= HA_ERATT; | 1307 | phba->work_ha |= HA_ERATT; |
1310 | phba->work_hs = HS_FFER3; | 1308 | phba->work_hs = HS_FFER3; |
1311 | 1309 | ||
1312 | /* hbalock should already be held */ | 1310 | lpfc_worker_wake_up(phba); |
1313 | if (phba->work_wait) | ||
1314 | lpfc_worker_wake_up(phba); | ||
1315 | 1311 | ||
1316 | return; | 1312 | return; |
1317 | } | 1313 | } |
@@ -2611,12 +2607,9 @@ lpfc_mbox_timeout(unsigned long ptr) | |||
2611 | phba->pport->work_port_events |= WORKER_MBOX_TMO; | 2607 | phba->pport->work_port_events |= WORKER_MBOX_TMO; |
2612 | spin_unlock_irqrestore(&phba->pport->work_port_lock, iflag); | 2608 | spin_unlock_irqrestore(&phba->pport->work_port_lock, iflag); |
2613 | 2609 | ||
2614 | if (!tmo_posted) { | 2610 | if (!tmo_posted) |
2615 | spin_lock_irqsave(&phba->hbalock, iflag); | 2611 | lpfc_worker_wake_up(phba); |
2616 | if (phba->work_wait) | 2612 | return; |
2617 | lpfc_worker_wake_up(phba); | ||
2618 | spin_unlock_irqrestore(&phba->hbalock, iflag); | ||
2619 | } | ||
2620 | } | 2613 | } |
2621 | 2614 | ||
2622 | void | 2615 | void |
@@ -3374,8 +3367,12 @@ lpfc_sli_host_down(struct lpfc_vport *vport) | |||
3374 | for (i = 0; i < psli->num_rings; i++) { | 3367 | for (i = 0; i < psli->num_rings; i++) { |
3375 | pring = &psli->ring[i]; | 3368 | pring = &psli->ring[i]; |
3376 | prev_pring_flag = pring->flag; | 3369 | prev_pring_flag = pring->flag; |
3377 | if (pring->ringno == LPFC_ELS_RING) /* Only slow rings */ | 3370 | /* Only slow rings */ |
3371 | if (pring->ringno == LPFC_ELS_RING) { | ||
3378 | pring->flag |= LPFC_DEFERRED_RING_EVENT; | 3372 | pring->flag |= LPFC_DEFERRED_RING_EVENT; |
3373 | /* Set the lpfc data pending flag */ | ||
3374 | set_bit(LPFC_DATA_READY, &phba->data_flags); | ||
3375 | } | ||
3379 | /* | 3376 | /* |
3380 | * Error everything on the txq since these iocbs have not been | 3377 | * Error everything on the txq since these iocbs have not been |
3381 | * given to the FW yet. | 3378 | * given to the FW yet. |
@@ -3434,8 +3431,12 @@ lpfc_sli_hba_down(struct lpfc_hba *phba) | |||
3434 | spin_lock_irqsave(&phba->hbalock, flags); | 3431 | spin_lock_irqsave(&phba->hbalock, flags); |
3435 | for (i = 0; i < psli->num_rings; i++) { | 3432 | for (i = 0; i < psli->num_rings; i++) { |
3436 | pring = &psli->ring[i]; | 3433 | pring = &psli->ring[i]; |
3437 | if (pring->ringno == LPFC_ELS_RING) /* Only slow rings */ | 3434 | /* Only slow rings */ |
3435 | if (pring->ringno == LPFC_ELS_RING) { | ||
3438 | pring->flag |= LPFC_DEFERRED_RING_EVENT; | 3436 | pring->flag |= LPFC_DEFERRED_RING_EVENT; |
3437 | /* Set the lpfc data pending flag */ | ||
3438 | set_bit(LPFC_DATA_READY, &phba->data_flags); | ||
3439 | } | ||
3439 | 3440 | ||
3440 | /* | 3441 | /* |
3441 | * Error everything on the txq since these iocbs have not been | 3442 | * Error everything on the txq since these iocbs have not been |
@@ -4159,7 +4160,7 @@ lpfc_intr_handler(int irq, void *dev_id) | |||
4159 | "pwork:x%x hawork:x%x wait:x%x", | 4160 | "pwork:x%x hawork:x%x wait:x%x", |
4160 | phba->work_ha, work_ha_copy, | 4161 | phba->work_ha, work_ha_copy, |
4161 | (uint32_t)((unsigned long) | 4162 | (uint32_t)((unsigned long) |
4162 | phba->work_wait)); | 4163 | &phba->work_waitq)); |
4163 | 4164 | ||
4164 | control &= | 4165 | control &= |
4165 | ~(HC_R0INT_ENA << LPFC_ELS_RING); | 4166 | ~(HC_R0INT_ENA << LPFC_ELS_RING); |
@@ -4172,7 +4173,7 @@ lpfc_intr_handler(int irq, void *dev_id) | |||
4172 | "x%x hawork:x%x wait:x%x", | 4173 | "x%x hawork:x%x wait:x%x", |
4173 | phba->work_ha, work_ha_copy, | 4174 | phba->work_ha, work_ha_copy, |
4174 | (uint32_t)((unsigned long) | 4175 | (uint32_t)((unsigned long) |
4175 | phba->work_wait)); | 4176 | &phba->work_waitq)); |
4176 | } | 4177 | } |
4177 | spin_unlock(&phba->hbalock); | 4178 | spin_unlock(&phba->hbalock); |
4178 | } | 4179 | } |
@@ -4297,9 +4298,8 @@ send_current_mbox: | |||
4297 | 4298 | ||
4298 | spin_lock(&phba->hbalock); | 4299 | spin_lock(&phba->hbalock); |
4299 | phba->work_ha |= work_ha_copy; | 4300 | phba->work_ha |= work_ha_copy; |
4300 | if (phba->work_wait) | ||
4301 | lpfc_worker_wake_up(phba); | ||
4302 | spin_unlock(&phba->hbalock); | 4301 | spin_unlock(&phba->hbalock); |
4302 | lpfc_worker_wake_up(phba); | ||
4303 | } | 4303 | } |
4304 | 4304 | ||
4305 | ha_copy &= ~(phba->work_ha_mask); | 4305 | ha_copy &= ~(phba->work_ha_mask); |