diff options
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_base.c | 17 | ||||
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_base.h | 14 | ||||
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_scsih.c | 463 |
3 files changed, 391 insertions, 103 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 3774b0742b2b..bb8acf781690 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c | |||
@@ -3468,6 +3468,12 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | |||
3468 | kfree(delayed_tr); | 3468 | kfree(delayed_tr); |
3469 | } | 3469 | } |
3470 | 3470 | ||
3471 | list_for_each_entry_safe(delayed_tr, delayed_tr_next, | ||
3472 | &ioc->delayed_tr_volume_list, list) { | ||
3473 | list_del(&delayed_tr->list); | ||
3474 | kfree(delayed_tr); | ||
3475 | } | ||
3476 | |||
3471 | /* initialize the scsi lookup free list */ | 3477 | /* initialize the scsi lookup free list */ |
3472 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | 3478 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); |
3473 | INIT_LIST_HEAD(&ioc->free_list); | 3479 | INIT_LIST_HEAD(&ioc->free_list); |
@@ -3622,6 +3628,15 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) | |||
3622 | 3628 | ||
3623 | init_waitqueue_head(&ioc->reset_wq); | 3629 | init_waitqueue_head(&ioc->reset_wq); |
3624 | 3630 | ||
3631 | /* allocate memory pd handle bitmask list */ | ||
3632 | ioc->pd_handles_sz = (ioc->facts.MaxDevHandle / 8); | ||
3633 | if (ioc->facts.MaxDevHandle % 8) | ||
3634 | ioc->pd_handles_sz++; | ||
3635 | ioc->pd_handles = kzalloc(ioc->pd_handles_sz, | ||
3636 | GFP_KERNEL); | ||
3637 | if (!ioc->pd_handles) | ||
3638 | goto out_free_resources; | ||
3639 | |||
3625 | ioc->fwfault_debug = mpt2sas_fwfault_debug; | 3640 | ioc->fwfault_debug = mpt2sas_fwfault_debug; |
3626 | 3641 | ||
3627 | /* base internal command bits */ | 3642 | /* base internal command bits */ |
@@ -3691,6 +3706,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) | |||
3691 | mpt2sas_base_free_resources(ioc); | 3706 | mpt2sas_base_free_resources(ioc); |
3692 | _base_release_memory_pools(ioc); | 3707 | _base_release_memory_pools(ioc); |
3693 | pci_set_drvdata(ioc->pdev, NULL); | 3708 | pci_set_drvdata(ioc->pdev, NULL); |
3709 | kfree(ioc->pd_handles); | ||
3694 | kfree(ioc->tm_cmds.reply); | 3710 | kfree(ioc->tm_cmds.reply); |
3695 | kfree(ioc->transport_cmds.reply); | 3711 | kfree(ioc->transport_cmds.reply); |
3696 | kfree(ioc->scsih_cmds.reply); | 3712 | kfree(ioc->scsih_cmds.reply); |
@@ -3726,6 +3742,7 @@ mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc) | |||
3726 | mpt2sas_base_free_resources(ioc); | 3742 | mpt2sas_base_free_resources(ioc); |
3727 | _base_release_memory_pools(ioc); | 3743 | _base_release_memory_pools(ioc); |
3728 | pci_set_drvdata(ioc->pdev, NULL); | 3744 | pci_set_drvdata(ioc->pdev, NULL); |
3745 | kfree(ioc->pd_handles); | ||
3729 | kfree(ioc->pfacts); | 3746 | kfree(ioc->pfacts); |
3730 | kfree(ioc->ctl_cmds.reply); | 3747 | kfree(ioc->ctl_cmds.reply); |
3731 | kfree(ioc->base_cmds.reply); | 3748 | kfree(ioc->base_cmds.reply); |
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index e2c5cee6450e..6fdee1680a6b 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h | |||
@@ -276,7 +276,6 @@ struct _internal_cmd { | |||
276 | * @channel: target channel | 276 | * @channel: target channel |
277 | * @slot: number number | 277 | * @slot: number number |
278 | * @phy: phy identifier provided in sas device page 0 | 278 | * @phy: phy identifier provided in sas device page 0 |
279 | * @hidden_raid_component: set to 1 when this is a raid member | ||
280 | * @responding: used in _scsih_sas_device_mark_responding | 279 | * @responding: used in _scsih_sas_device_mark_responding |
281 | */ | 280 | */ |
282 | struct _sas_device { | 281 | struct _sas_device { |
@@ -295,7 +294,6 @@ struct _sas_device { | |||
295 | int channel; | 294 | int channel; |
296 | u16 slot; | 295 | u16 slot; |
297 | u8 phy; | 296 | u8 phy; |
298 | u8 hidden_raid_component; | ||
299 | u8 responding; | 297 | u8 responding; |
300 | }; | 298 | }; |
301 | 299 | ||
@@ -489,6 +487,8 @@ typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr); | |||
489 | * @ctl_cb_idx: clt internal commands | 487 | * @ctl_cb_idx: clt internal commands |
490 | * @base_cb_idx: base internal commands | 488 | * @base_cb_idx: base internal commands |
491 | * @config_cb_idx: base internal commands | 489 | * @config_cb_idx: base internal commands |
490 | * @tm_tr_cb_idx : device removal target reset handshake | ||
491 | * @tm_tr_volume_cb_idx : volume removal target reset | ||
492 | * @base_cmds: | 492 | * @base_cmds: |
493 | * @transport_cmds: | 493 | * @transport_cmds: |
494 | * @scsih_cmds: | 494 | * @scsih_cmds: |
@@ -517,6 +517,9 @@ typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr); | |||
517 | * @sas_device_lock: | 517 | * @sas_device_lock: |
518 | * @io_missing_delay: time for IO completed by fw when PDR enabled | 518 | * @io_missing_delay: time for IO completed by fw when PDR enabled |
519 | * @device_missing_delay: time for device missing by fw when PDR enabled | 519 | * @device_missing_delay: time for device missing by fw when PDR enabled |
520 | * @sas_id : used for setting volume target IDs | ||
521 | * @pd_handles : bitmask for PD handles | ||
522 | * @pd_handles_sz : size of pd_handle bitmask | ||
520 | * @config_page_sz: config page size | 523 | * @config_page_sz: config page size |
521 | * @config_page: reserve memory for config page payload | 524 | * @config_page: reserve memory for config page payload |
522 | * @config_page_dma: | 525 | * @config_page_dma: |
@@ -569,6 +572,8 @@ typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr); | |||
569 | * @reply_post_free_dma: | 572 | * @reply_post_free_dma: |
570 | * @reply_post_free_dma_pool: | 573 | * @reply_post_free_dma_pool: |
571 | * @reply_post_host_index: head index in the pool where FW completes IO | 574 | * @reply_post_host_index: head index in the pool where FW completes IO |
575 | * @delayed_tr_list: target reset link list | ||
576 | * @delayed_tr_volume_list: volume target reset link list | ||
572 | */ | 577 | */ |
573 | struct MPT2SAS_ADAPTER { | 578 | struct MPT2SAS_ADAPTER { |
574 | struct list_head list; | 579 | struct list_head list; |
@@ -627,6 +632,7 @@ struct MPT2SAS_ADAPTER { | |||
627 | u8 base_cb_idx; | 632 | u8 base_cb_idx; |
628 | u8 config_cb_idx; | 633 | u8 config_cb_idx; |
629 | u8 tm_tr_cb_idx; | 634 | u8 tm_tr_cb_idx; |
635 | u8 tm_tr_volume_cb_idx; | ||
630 | u8 tm_sas_control_cb_idx; | 636 | u8 tm_sas_control_cb_idx; |
631 | struct _internal_cmd base_cmds; | 637 | struct _internal_cmd base_cmds; |
632 | struct _internal_cmd transport_cmds; | 638 | struct _internal_cmd transport_cmds; |
@@ -670,6 +676,9 @@ struct MPT2SAS_ADAPTER { | |||
670 | u16 device_missing_delay; | 676 | u16 device_missing_delay; |
671 | int sas_id; | 677 | int sas_id; |
672 | 678 | ||
679 | void *pd_handles; | ||
680 | u16 pd_handles_sz; | ||
681 | |||
673 | /* config page */ | 682 | /* config page */ |
674 | u16 config_page_sz; | 683 | u16 config_page_sz; |
675 | void *config_page; | 684 | void *config_page; |
@@ -741,6 +750,7 @@ struct MPT2SAS_ADAPTER { | |||
741 | u32 reply_post_host_index; | 750 | u32 reply_post_host_index; |
742 | 751 | ||
743 | struct list_head delayed_tr_list; | 752 | struct list_head delayed_tr_list; |
753 | struct list_head delayed_tr_volume_list; | ||
744 | 754 | ||
745 | /* diag buffer support */ | 755 | /* diag buffer support */ |
746 | u8 *diag_buffer[MPI2_DIAG_BUF_TYPE_COUNT]; | 756 | u8 *diag_buffer[MPI2_DIAG_BUF_TYPE_COUNT]; |
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index db12e184d1d9..b327d60fad1b 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c | |||
@@ -70,6 +70,8 @@ static void _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc, | |||
70 | struct _sas_node *sas_expander); | 70 | struct _sas_node *sas_expander); |
71 | static void _firmware_event_work(struct work_struct *work); | 71 | static void _firmware_event_work(struct work_struct *work); |
72 | 72 | ||
73 | static u8 _scsih_check_for_pending_tm(struct MPT2SAS_ADAPTER *ioc, u16 smid); | ||
74 | |||
73 | /* global parameters */ | 75 | /* global parameters */ |
74 | LIST_HEAD(mpt2sas_ioc_list); | 76 | LIST_HEAD(mpt2sas_ioc_list); |
75 | 77 | ||
@@ -84,6 +86,7 @@ static u8 config_cb_idx = -1; | |||
84 | static int mpt_ids; | 86 | static int mpt_ids; |
85 | 87 | ||
86 | static u8 tm_tr_cb_idx = -1 ; | 88 | static u8 tm_tr_cb_idx = -1 ; |
89 | static u8 tm_tr_volume_cb_idx = -1 ; | ||
87 | static u8 tm_sas_control_cb_idx = -1; | 90 | static u8 tm_sas_control_cb_idx = -1; |
88 | 91 | ||
89 | /* command line options */ | 92 | /* command line options */ |
@@ -1226,7 +1229,7 @@ _scsih_target_alloc(struct scsi_target *starget) | |||
1226 | sas_device->starget = starget; | 1229 | sas_device->starget = starget; |
1227 | sas_device->id = starget->id; | 1230 | sas_device->id = starget->id; |
1228 | sas_device->channel = starget->channel; | 1231 | sas_device->channel = starget->channel; |
1229 | if (sas_device->hidden_raid_component) | 1232 | if (test_bit(sas_device->handle, ioc->pd_handles)) |
1230 | sas_target_priv_data->flags |= | 1233 | sas_target_priv_data->flags |= |
1231 | MPT_TARGET_FLAGS_RAID_COMPONENT; | 1234 | MPT_TARGET_FLAGS_RAID_COMPONENT; |
1232 | } | 1235 | } |
@@ -2583,6 +2586,7 @@ _scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
2583 | Mpi2SCSITaskManagementRequest_t *mpi_request; | 2586 | Mpi2SCSITaskManagementRequest_t *mpi_request; |
2584 | u16 smid; | 2587 | u16 smid; |
2585 | struct _sas_device *sas_device; | 2588 | struct _sas_device *sas_device; |
2589 | struct MPT2SAS_TARGET *sas_target_priv_data; | ||
2586 | unsigned long flags; | 2590 | unsigned long flags; |
2587 | struct _tr_list *delayed_tr; | 2591 | struct _tr_list *delayed_tr; |
2588 | 2592 | ||
@@ -2592,11 +2596,20 @@ _scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
2592 | return; | 2596 | return; |
2593 | } | 2597 | } |
2594 | 2598 | ||
2599 | /* if PD, then return */ | ||
2600 | if (test_bit(handle, ioc->pd_handles)) | ||
2601 | return; | ||
2602 | |||
2595 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 2603 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
2596 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | 2604 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); |
2597 | if (sas_device && sas_device->hidden_raid_component) { | 2605 | if (sas_device && sas_device->starget && |
2598 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 2606 | sas_device->starget->hostdata) { |
2599 | return; | 2607 | sas_target_priv_data = sas_device->starget->hostdata; |
2608 | sas_target_priv_data->deleted = 1; | ||
2609 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
2610 | "setting delete flag: handle(0x%04x), " | ||
2611 | "sas_addr(0x%016llx)\n", ioc->name, handle, | ||
2612 | (unsigned long long) sas_device->sas_address)); | ||
2600 | } | 2613 | } |
2601 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 2614 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
2602 | 2615 | ||
@@ -2659,6 +2672,99 @@ _scsih_sas_control_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, | |||
2659 | } | 2672 | } |
2660 | 2673 | ||
2661 | /** | 2674 | /** |
2675 | * _scsih_tm_tr_volume_send - send target reset request for volumes | ||
2676 | * @ioc: per adapter object | ||
2677 | * @handle: device handle | ||
2678 | * Context: interrupt time. | ||
2679 | * | ||
2680 | * This is designed to send muliple task management request at the same | ||
2681 | * time to the fifo. If the fifo is full, we will append the request, | ||
2682 | * and process it in a future completion. | ||
2683 | */ | ||
2684 | static void | ||
2685 | _scsih_tm_tr_volume_send(struct MPT2SAS_ADAPTER *ioc, u16 handle) | ||
2686 | { | ||
2687 | Mpi2SCSITaskManagementRequest_t *mpi_request; | ||
2688 | u16 smid; | ||
2689 | struct _tr_list *delayed_tr; | ||
2690 | |||
2691 | if (ioc->shost_recovery || ioc->remove_host) { | ||
2692 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host reset in " | ||
2693 | "progress!\n", __func__, ioc->name)); | ||
2694 | return; | ||
2695 | } | ||
2696 | |||
2697 | smid = mpt2sas_base_get_smid_hpr(ioc, ioc->tm_tr_volume_cb_idx); | ||
2698 | if (!smid) { | ||
2699 | delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC); | ||
2700 | if (!delayed_tr) | ||
2701 | return; | ||
2702 | INIT_LIST_HEAD(&delayed_tr->list); | ||
2703 | delayed_tr->handle = handle; | ||
2704 | list_add_tail(&delayed_tr->list, &ioc->delayed_tr_volume_list); | ||
2705 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
2706 | "DELAYED:tr:handle(0x%04x), (open)\n", | ||
2707 | ioc->name, handle)); | ||
2708 | return; | ||
2709 | } | ||
2710 | |||
2711 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "tr_send:handle(0x%04x), " | ||
2712 | "(open), smid(%d), cb(%d)\n", ioc->name, handle, smid, | ||
2713 | ioc->tm_tr_volume_cb_idx)); | ||
2714 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); | ||
2715 | memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t)); | ||
2716 | mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; | ||
2717 | mpi_request->DevHandle = cpu_to_le16(handle); | ||
2718 | mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; | ||
2719 | mpt2sas_base_put_smid_hi_priority(ioc, smid); | ||
2720 | } | ||
2721 | |||
2722 | /** | ||
2723 | * _scsih_tm_volume_tr_complete - target reset completion | ||
2724 | * @ioc: per adapter object | ||
2725 | * @smid: system request message index | ||
2726 | * @msix_index: MSIX table index supplied by the OS | ||
2727 | * @reply: reply message frame(lower 32bit addr) | ||
2728 | * Context: interrupt time. | ||
2729 | * | ||
2730 | * Return 1 meaning mf should be freed from _base_interrupt | ||
2731 | * 0 means the mf is freed from this function. | ||
2732 | */ | ||
2733 | static u8 | ||
2734 | _scsih_tm_volume_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, | ||
2735 | u8 msix_index, u32 reply) | ||
2736 | { | ||
2737 | u16 handle; | ||
2738 | Mpi2SCSITaskManagementRequest_t *mpi_request_tm; | ||
2739 | Mpi2SCSITaskManagementReply_t *mpi_reply = | ||
2740 | mpt2sas_base_get_reply_virt_addr(ioc, reply); | ||
2741 | |||
2742 | if (ioc->shost_recovery || ioc->remove_host) { | ||
2743 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host reset in " | ||
2744 | "progress!\n", __func__, ioc->name)); | ||
2745 | return 1; | ||
2746 | } | ||
2747 | |||
2748 | mpi_request_tm = mpt2sas_base_get_msg_frame(ioc, smid); | ||
2749 | handle = le16_to_cpu(mpi_request_tm->DevHandle); | ||
2750 | if (handle != le16_to_cpu(mpi_reply->DevHandle)) { | ||
2751 | dewtprintk(ioc, printk("spurious interrupt: " | ||
2752 | "handle(0x%04x:0x%04x), smid(%d)!!!\n", handle, | ||
2753 | le16_to_cpu(mpi_reply->DevHandle), smid)); | ||
2754 | return 0; | ||
2755 | } | ||
2756 | |||
2757 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
2758 | "tr_complete:handle(0x%04x), (open) smid(%d), ioc_status(0x%04x), " | ||
2759 | "loginfo(0x%08x), completed(%d)\n", ioc->name, | ||
2760 | handle, smid, le16_to_cpu(mpi_reply->IOCStatus), | ||
2761 | le32_to_cpu(mpi_reply->IOCLogInfo), | ||
2762 | le32_to_cpu(mpi_reply->TerminationCount))); | ||
2763 | |||
2764 | return _scsih_check_for_pending_tm(ioc, smid); | ||
2765 | } | ||
2766 | |||
2767 | /** | ||
2662 | * _scsih_tm_tr_complete - | 2768 | * _scsih_tm_tr_complete - |
2663 | * @ioc: per adapter object | 2769 | * @ioc: per adapter object |
2664 | * @smid: system request message index | 2770 | * @smid: system request message index |
@@ -2684,7 +2790,6 @@ _scsih_tm_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | |||
2684 | mpt2sas_base_get_reply_virt_addr(ioc, reply); | 2790 | mpt2sas_base_get_reply_virt_addr(ioc, reply); |
2685 | Mpi2SasIoUnitControlRequest_t *mpi_request; | 2791 | Mpi2SasIoUnitControlRequest_t *mpi_request; |
2686 | u16 smid_sas_ctrl; | 2792 | u16 smid_sas_ctrl; |
2687 | struct _tr_list *delayed_tr; | ||
2688 | 2793 | ||
2689 | if (ioc->shost_recovery || ioc->remove_host) { | 2794 | if (ioc->shost_recovery || ioc->remove_host) { |
2690 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host reset in " | 2795 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host reset in " |
@@ -2725,6 +2830,35 @@ _scsih_tm_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | |||
2725 | mpi_request->DevHandle = mpi_request_tm->DevHandle; | 2830 | mpi_request->DevHandle = mpi_request_tm->DevHandle; |
2726 | mpt2sas_base_put_smid_default(ioc, smid_sas_ctrl); | 2831 | mpt2sas_base_put_smid_default(ioc, smid_sas_ctrl); |
2727 | 2832 | ||
2833 | return _scsih_check_for_pending_tm(ioc, smid); | ||
2834 | } | ||
2835 | |||
2836 | /** | ||
2837 | * _scsih_check_for_pending_tm - check for pending task management | ||
2838 | * @ioc: per adapter object | ||
2839 | * @smid: system request message index | ||
2840 | * | ||
2841 | * This will check delayed target reset list, and feed the | ||
2842 | * next reqeust. | ||
2843 | * | ||
2844 | * Return 1 meaning mf should be freed from _base_interrupt | ||
2845 | * 0 means the mf is freed from this function. | ||
2846 | */ | ||
2847 | static u8 | ||
2848 | _scsih_check_for_pending_tm(struct MPT2SAS_ADAPTER *ioc, u16 smid) | ||
2849 | { | ||
2850 | struct _tr_list *delayed_tr; | ||
2851 | |||
2852 | if (!list_empty(&ioc->delayed_tr_volume_list)) { | ||
2853 | delayed_tr = list_entry(ioc->delayed_tr_volume_list.next, | ||
2854 | struct _tr_list, list); | ||
2855 | mpt2sas_base_free_smid(ioc, smid); | ||
2856 | _scsih_tm_tr_volume_send(ioc, delayed_tr->handle); | ||
2857 | list_del(&delayed_tr->list); | ||
2858 | kfree(delayed_tr); | ||
2859 | return 0; | ||
2860 | } | ||
2861 | |||
2728 | if (!list_empty(&ioc->delayed_tr_list)) { | 2862 | if (!list_empty(&ioc->delayed_tr_list)) { |
2729 | delayed_tr = list_entry(ioc->delayed_tr_list.next, | 2863 | delayed_tr = list_entry(ioc->delayed_tr_list.next, |
2730 | struct _tr_list, list); | 2864 | struct _tr_list, list); |
@@ -2732,8 +2866,9 @@ _scsih_tm_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | |||
2732 | _scsih_tm_tr_send(ioc, delayed_tr->handle); | 2866 | _scsih_tm_tr_send(ioc, delayed_tr->handle); |
2733 | list_del(&delayed_tr->list); | 2867 | list_del(&delayed_tr->list); |
2734 | kfree(delayed_tr); | 2868 | kfree(delayed_tr); |
2735 | return 0; /* tells base_interrupt not to free mf */ | 2869 | return 0; |
2736 | } | 2870 | } |
2871 | |||
2737 | return 1; | 2872 | return 1; |
2738 | } | 2873 | } |
2739 | 2874 | ||
@@ -2817,6 +2952,165 @@ _scsih_check_topo_delete_events(struct MPT2SAS_ADAPTER *ioc, | |||
2817 | } | 2952 | } |
2818 | 2953 | ||
2819 | /** | 2954 | /** |
2955 | * _scsih_set_volume_delete_flag - setting volume delete flag | ||
2956 | * @ioc: per adapter object | ||
2957 | * @handle: device handle | ||
2958 | * | ||
2959 | * This | ||
2960 | * Return nothing. | ||
2961 | */ | ||
2962 | static void | ||
2963 | _scsih_set_volume_delete_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle) | ||
2964 | { | ||
2965 | struct _raid_device *raid_device; | ||
2966 | struct MPT2SAS_TARGET *sas_target_priv_data; | ||
2967 | unsigned long flags; | ||
2968 | |||
2969 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | ||
2970 | raid_device = _scsih_raid_device_find_by_handle(ioc, handle); | ||
2971 | if (raid_device && raid_device->starget && | ||
2972 | raid_device->starget->hostdata) { | ||
2973 | sas_target_priv_data = | ||
2974 | raid_device->starget->hostdata; | ||
2975 | sas_target_priv_data->deleted = 1; | ||
2976 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
2977 | "setting delete flag: handle(0x%04x), " | ||
2978 | "wwid(0x%016llx)\n", ioc->name, handle, | ||
2979 | (unsigned long long) raid_device->wwid)); | ||
2980 | } | ||
2981 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); | ||
2982 | } | ||
2983 | |||
2984 | /** | ||
2985 | * _scsih_set_volume_handle_for_tr - set handle for target reset to volume | ||
2986 | * @handle: input handle | ||
2987 | * @a: handle for volume a | ||
2988 | * @b: handle for volume b | ||
2989 | * | ||
2990 | * IR firmware only supports two raid volumes. The purpose of this | ||
2991 | * routine is to set the volume handle in either a or b. When the given | ||
2992 | * input handle is non-zero, or when a and b have not been set before. | ||
2993 | */ | ||
2994 | static void | ||
2995 | _scsih_set_volume_handle_for_tr(u16 handle, u16 *a, u16 *b) | ||
2996 | { | ||
2997 | if (!handle || handle == *a || handle == *b) | ||
2998 | return; | ||
2999 | if (!*a) | ||
3000 | *a = handle; | ||
3001 | else if (!*b) | ||
3002 | *b = handle; | ||
3003 | } | ||
3004 | |||
3005 | /** | ||
3006 | * _scsih_check_ir_config_unhide_events - check for UNHIDE events | ||
3007 | * @ioc: per adapter object | ||
3008 | * @event_data: the event data payload | ||
3009 | * Context: interrupt time. | ||
3010 | * | ||
3011 | * This routine will send target reset to volume, followed by target | ||
3012 | * resets to the PDs. This is called when a PD has been removed, or | ||
3013 | * volume has been deleted or removed. When the target reset is sent | ||
3014 | * to volume, the PD target resets need to be queued to start upon | ||
3015 | * completion of the volume target reset. | ||
3016 | * | ||
3017 | * Return nothing. | ||
3018 | */ | ||
3019 | static void | ||
3020 | _scsih_check_ir_config_unhide_events(struct MPT2SAS_ADAPTER *ioc, | ||
3021 | Mpi2EventDataIrConfigChangeList_t *event_data) | ||
3022 | { | ||
3023 | Mpi2EventIrConfigElement_t *element; | ||
3024 | int i; | ||
3025 | u16 handle, volume_handle, a, b; | ||
3026 | struct _tr_list *delayed_tr; | ||
3027 | |||
3028 | a = 0; | ||
3029 | b = 0; | ||
3030 | |||
3031 | /* Volume Resets for Deleted or Removed */ | ||
3032 | element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; | ||
3033 | for (i = 0; i < event_data->NumElements; i++, element++) { | ||
3034 | if (element->ReasonCode == | ||
3035 | MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED || | ||
3036 | element->ReasonCode == | ||
3037 | MPI2_EVENT_IR_CHANGE_RC_REMOVED) { | ||
3038 | volume_handle = le16_to_cpu(element->VolDevHandle); | ||
3039 | _scsih_set_volume_delete_flag(ioc, volume_handle); | ||
3040 | _scsih_set_volume_handle_for_tr(volume_handle, &a, &b); | ||
3041 | } | ||
3042 | } | ||
3043 | |||
3044 | /* Volume Resets for UNHIDE events */ | ||
3045 | element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; | ||
3046 | for (i = 0; i < event_data->NumElements; i++, element++) { | ||
3047 | if (le32_to_cpu(event_data->Flags) & | ||
3048 | MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) | ||
3049 | continue; | ||
3050 | if (element->ReasonCode == MPI2_EVENT_IR_CHANGE_RC_UNHIDE) { | ||
3051 | volume_handle = le16_to_cpu(element->VolDevHandle); | ||
3052 | _scsih_set_volume_handle_for_tr(volume_handle, &a, &b); | ||
3053 | } | ||
3054 | } | ||
3055 | |||
3056 | if (a) | ||
3057 | _scsih_tm_tr_volume_send(ioc, a); | ||
3058 | if (b) | ||
3059 | _scsih_tm_tr_volume_send(ioc, b); | ||
3060 | |||
3061 | /* PD target resets */ | ||
3062 | element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; | ||
3063 | for (i = 0; i < event_data->NumElements; i++, element++) { | ||
3064 | if (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_UNHIDE) | ||
3065 | continue; | ||
3066 | handle = le16_to_cpu(element->PhysDiskDevHandle); | ||
3067 | volume_handle = le16_to_cpu(element->VolDevHandle); | ||
3068 | clear_bit(handle, ioc->pd_handles); | ||
3069 | if (!volume_handle) | ||
3070 | _scsih_tm_tr_send(ioc, handle); | ||
3071 | else if (volume_handle == a || volume_handle == b) { | ||
3072 | delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC); | ||
3073 | BUG_ON(!delayed_tr); | ||
3074 | INIT_LIST_HEAD(&delayed_tr->list); | ||
3075 | delayed_tr->handle = handle; | ||
3076 | list_add_tail(&delayed_tr->list, &ioc->delayed_tr_list); | ||
3077 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
3078 | "DELAYED:tr:handle(0x%04x), (open)\n", ioc->name, | ||
3079 | handle)); | ||
3080 | } else | ||
3081 | _scsih_tm_tr_send(ioc, handle); | ||
3082 | } | ||
3083 | } | ||
3084 | |||
3085 | |||
3086 | /** | ||
3087 | * _scsih_check_volume_delete_events - set delete flag for volumes | ||
3088 | * @ioc: per adapter object | ||
3089 | * @event_data: the event data payload | ||
3090 | * Context: interrupt time. | ||
3091 | * | ||
3092 | * This will handle the case when the cable connected to entire volume is | ||
3093 | * pulled. We will take care of setting the deleted flag so normal IO will | ||
3094 | * not be sent. | ||
3095 | * | ||
3096 | * Return nothing. | ||
3097 | */ | ||
3098 | static void | ||
3099 | _scsih_check_volume_delete_events(struct MPT2SAS_ADAPTER *ioc, | ||
3100 | Mpi2EventDataIrVolume_t *event_data) | ||
3101 | { | ||
3102 | u32 state; | ||
3103 | |||
3104 | if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED) | ||
3105 | return; | ||
3106 | state = le32_to_cpu(event_data->NewValue); | ||
3107 | if (state == MPI2_RAID_VOL_STATE_MISSING || state == | ||
3108 | MPI2_RAID_VOL_STATE_FAILED) | ||
3109 | _scsih_set_volume_delete_flag(ioc, | ||
3110 | le16_to_cpu(event_data->VolDevHandle)); | ||
3111 | } | ||
3112 | |||
3113 | /** | ||
2820 | * _scsih_flush_running_cmds - completing outstanding commands. | 3114 | * _scsih_flush_running_cmds - completing outstanding commands. |
2821 | * @ioc: per adapter object | 3115 | * @ioc: per adapter object |
2822 | * | 3116 | * |
@@ -4204,7 +4498,6 @@ _scsih_add_device(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 phy_num, u8 is_pd) | |||
4204 | sas_device->device_info = device_info; | 4498 | sas_device->device_info = device_info; |
4205 | sas_device->sas_address = sas_address; | 4499 | sas_device->sas_address = sas_address; |
4206 | sas_device->phy = sas_device_pg0.PhyNum; | 4500 | sas_device->phy = sas_device_pg0.PhyNum; |
4207 | sas_device->hidden_raid_component = is_pd; | ||
4208 | 4501 | ||
4209 | /* get enclosure_logical_id */ | 4502 | /* get enclosure_logical_id */ |
4210 | if (sas_device->enclosure_handle && !(mpt2sas_config_get_enclosure_pg0( | 4503 | if (sas_device->enclosure_handle && !(mpt2sas_config_get_enclosure_pg0( |
@@ -4225,62 +4518,6 @@ _scsih_add_device(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 phy_num, u8 is_pd) | |||
4225 | } | 4518 | } |
4226 | 4519 | ||
4227 | /** | 4520 | /** |
4228 | * _scsih_remove_pd_device - removing sas device pd object | ||
4229 | * @ioc: per adapter object | ||
4230 | * @sas_device_delete: the sas_device object | ||
4231 | * | ||
4232 | * For hidden raid components, we do driver-fw handshake from | ||
4233 | * hotplug work threads. | ||
4234 | * Return nothing. | ||
4235 | */ | ||
4236 | static void | ||
4237 | _scsih_remove_pd_device(struct MPT2SAS_ADAPTER *ioc, struct _sas_device | ||
4238 | sas_device) | ||
4239 | { | ||
4240 | Mpi2SasIoUnitControlReply_t mpi_reply; | ||
4241 | Mpi2SasIoUnitControlRequest_t mpi_request; | ||
4242 | u16 vol_handle, handle; | ||
4243 | |||
4244 | handle = sas_device.handle; | ||
4245 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter: handle(0x%04x)," | ||
4246 | " sas_addr(0x%016llx)\n", ioc->name, __func__, handle, | ||
4247 | (unsigned long long) sas_device.sas_address)); | ||
4248 | |||
4249 | vol_handle = sas_device.volume_handle; | ||
4250 | if (!vol_handle) | ||
4251 | return; | ||
4252 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "issue target reset: " | ||
4253 | "handle(0x%04x)\n", ioc->name, vol_handle)); | ||
4254 | mpt2sas_scsih_issue_tm(ioc, vol_handle, 0, 0, 0, | ||
4255 | MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 30, NULL); | ||
4256 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "issue target reset " | ||
4257 | "done: handle(0x%04x)\n", ioc->name, vol_handle)); | ||
4258 | if (ioc->shost_recovery) | ||
4259 | return; | ||
4260 | |||
4261 | /* SAS_IO_UNIT_CNTR - send REMOVE_DEVICE */ | ||
4262 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "sas_iounit: handle" | ||
4263 | "(0x%04x)\n", ioc->name, handle)); | ||
4264 | memset(&mpi_request, 0, sizeof(Mpi2SasIoUnitControlRequest_t)); | ||
4265 | mpi_request.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL; | ||
4266 | mpi_request.Operation = MPI2_SAS_OP_REMOVE_DEVICE; | ||
4267 | mpi_request.DevHandle = cpu_to_le16(handle); | ||
4268 | if ((mpt2sas_base_sas_iounit_control(ioc, &mpi_reply, | ||
4269 | &mpi_request)) != 0) | ||
4270 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
4271 | ioc->name, __FILE__, __LINE__, __func__); | ||
4272 | |||
4273 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "sas_iounit: ioc_status" | ||
4274 | "(0x%04x), loginfo(0x%08x)\n", ioc->name, | ||
4275 | le16_to_cpu(mpi_reply.IOCStatus), | ||
4276 | le32_to_cpu(mpi_reply.IOCLogInfo))); | ||
4277 | |||
4278 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: exit: handle(0x%04x)," | ||
4279 | " sas_addr(0x%016llx)\n", ioc->name, __func__, handle, | ||
4280 | (unsigned long long) sas_device.sas_address)); | ||
4281 | } | ||
4282 | |||
4283 | /** | ||
4284 | * _scsih_remove_device - removing sas device object | 4521 | * _scsih_remove_device - removing sas device object |
4285 | * @ioc: per adapter object | 4522 | * @ioc: per adapter object |
4286 | * @sas_device_delete: the sas_device object | 4523 | * @sas_device_delete: the sas_device object |
@@ -4310,9 +4547,6 @@ _scsih_remove_device(struct MPT2SAS_ADAPTER *ioc, | |||
4310 | sas_target_priv_data->deleted = 1; | 4547 | sas_target_priv_data->deleted = 1; |
4311 | } | 4548 | } |
4312 | 4549 | ||
4313 | if (sas_device_backup.hidden_raid_component) | ||
4314 | _scsih_remove_pd_device(ioc, sas_device_backup); | ||
4315 | |||
4316 | _scsih_ublock_io_device(ioc, sas_device_backup.handle); | 4550 | _scsih_ublock_io_device(ioc, sas_device_backup.handle); |
4317 | 4551 | ||
4318 | mpt2sas_transport_port_remove(ioc, sas_device_backup.sas_address, | 4552 | mpt2sas_transport_port_remove(ioc, sas_device_backup.sas_address, |
@@ -4909,17 +5143,15 @@ _scsih_sas_volume_add(struct MPT2SAS_ADAPTER *ioc, | |||
4909 | /** | 5143 | /** |
4910 | * _scsih_sas_volume_delete - delete volume | 5144 | * _scsih_sas_volume_delete - delete volume |
4911 | * @ioc: per adapter object | 5145 | * @ioc: per adapter object |
4912 | * @element: IR config element data | 5146 | * @handle: volume device handle |
4913 | * Context: user. | 5147 | * Context: user. |
4914 | * | 5148 | * |
4915 | * Return nothing. | 5149 | * Return nothing. |
4916 | */ | 5150 | */ |
4917 | static void | 5151 | static void |
4918 | _scsih_sas_volume_delete(struct MPT2SAS_ADAPTER *ioc, | 5152 | _scsih_sas_volume_delete(struct MPT2SAS_ADAPTER *ioc, u16 handle) |
4919 | Mpi2EventIrConfigElement_t *element) | ||
4920 | { | 5153 | { |
4921 | struct _raid_device *raid_device; | 5154 | struct _raid_device *raid_device; |
4922 | u16 handle = le16_to_cpu(element->VolDevHandle); | ||
4923 | unsigned long flags; | 5155 | unsigned long flags; |
4924 | struct MPT2SAS_TARGET *sas_target_priv_data; | 5156 | struct MPT2SAS_TARGET *sas_target_priv_data; |
4925 | 5157 | ||
@@ -4933,6 +5165,9 @@ _scsih_sas_volume_delete(struct MPT2SAS_ADAPTER *ioc, | |||
4933 | sas_target_priv_data->deleted = 1; | 5165 | sas_target_priv_data->deleted = 1; |
4934 | scsi_remove_target(&raid_device->starget->dev); | 5166 | scsi_remove_target(&raid_device->starget->dev); |
4935 | } | 5167 | } |
5168 | printk(MPT2SAS_INFO_FMT "removing handle(0x%04x), wwid" | ||
5169 | "(0x%016llx)\n", ioc->name, raid_device->handle, | ||
5170 | (unsigned long long) raid_device->wwid); | ||
4936 | _scsih_raid_device_remove(ioc, raid_device); | 5171 | _scsih_raid_device_remove(ioc, raid_device); |
4937 | } | 5172 | } |
4938 | 5173 | ||
@@ -4961,7 +5196,7 @@ _scsih_sas_pd_expose(struct MPT2SAS_ADAPTER *ioc, | |||
4961 | /* exposing raid component */ | 5196 | /* exposing raid component */ |
4962 | sas_device->volume_handle = 0; | 5197 | sas_device->volume_handle = 0; |
4963 | sas_device->volume_wwid = 0; | 5198 | sas_device->volume_wwid = 0; |
4964 | sas_device->hidden_raid_component = 0; | 5199 | clear_bit(handle, ioc->pd_handles); |
4965 | _scsih_reprobe_target(sas_device->starget, 0); | 5200 | _scsih_reprobe_target(sas_device->starget, 0); |
4966 | } | 5201 | } |
4967 | 5202 | ||
@@ -4992,7 +5227,7 @@ _scsih_sas_pd_hide(struct MPT2SAS_ADAPTER *ioc, | |||
4992 | &sas_device->volume_handle); | 5227 | &sas_device->volume_handle); |
4993 | mpt2sas_config_get_volume_wwid(ioc, sas_device->volume_handle, | 5228 | mpt2sas_config_get_volume_wwid(ioc, sas_device->volume_handle, |
4994 | &sas_device->volume_wwid); | 5229 | &sas_device->volume_wwid); |
4995 | sas_device->hidden_raid_component = 1; | 5230 | set_bit(handle, ioc->pd_handles); |
4996 | _scsih_reprobe_target(sas_device->starget, 1); | 5231 | _scsih_reprobe_target(sas_device->starget, 1); |
4997 | } | 5232 | } |
4998 | 5233 | ||
@@ -5041,13 +5276,13 @@ _scsih_sas_pd_add(struct MPT2SAS_ADAPTER *ioc, | |||
5041 | u64 sas_address; | 5276 | u64 sas_address; |
5042 | u16 parent_handle; | 5277 | u16 parent_handle; |
5043 | 5278 | ||
5279 | set_bit(handle, ioc->pd_handles); | ||
5280 | |||
5044 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 5281 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
5045 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | 5282 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); |
5046 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 5283 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
5047 | if (sas_device) { | 5284 | if (sas_device) |
5048 | sas_device->hidden_raid_component = 1; | ||
5049 | return; | 5285 | return; |
5050 | } | ||
5051 | 5286 | ||
5052 | if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, | 5287 | if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, |
5053 | MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { | 5288 | MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { |
@@ -5191,7 +5426,8 @@ _scsih_sas_ir_config_change_event(struct MPT2SAS_ADAPTER *ioc, | |||
5191 | case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED: | 5426 | case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED: |
5192 | case MPI2_EVENT_IR_CHANGE_RC_REMOVED: | 5427 | case MPI2_EVENT_IR_CHANGE_RC_REMOVED: |
5193 | if (!foreign_config) | 5428 | if (!foreign_config) |
5194 | _scsih_sas_volume_delete(ioc, element); | 5429 | _scsih_sas_volume_delete(ioc, |
5430 | le16_to_cpu(element->VolDevHandle)); | ||
5195 | break; | 5431 | break; |
5196 | case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED: | 5432 | case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED: |
5197 | _scsih_sas_pd_hide(ioc, element); | 5433 | _scsih_sas_pd_hide(ioc, element); |
@@ -5227,7 +5463,6 @@ _scsih_sas_ir_volume_event(struct MPT2SAS_ADAPTER *ioc, | |||
5227 | u16 handle; | 5463 | u16 handle; |
5228 | u32 state; | 5464 | u32 state; |
5229 | int rc; | 5465 | int rc; |
5230 | struct MPT2SAS_TARGET *sas_target_priv_data; | ||
5231 | Mpi2EventDataIrVolume_t *event_data = fw_event->event_data; | 5466 | Mpi2EventDataIrVolume_t *event_data = fw_event->event_data; |
5232 | 5467 | ||
5233 | if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED) | 5468 | if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED) |
@@ -5239,26 +5474,20 @@ _scsih_sas_ir_volume_event(struct MPT2SAS_ADAPTER *ioc, | |||
5239 | "old(0x%08x), new(0x%08x)\n", ioc->name, __func__, handle, | 5474 | "old(0x%08x), new(0x%08x)\n", ioc->name, __func__, handle, |
5240 | le32_to_cpu(event_data->PreviousValue), state)); | 5475 | le32_to_cpu(event_data->PreviousValue), state)); |
5241 | 5476 | ||
5242 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | ||
5243 | raid_device = _scsih_raid_device_find_by_handle(ioc, handle); | ||
5244 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); | ||
5245 | |||
5246 | switch (state) { | 5477 | switch (state) { |
5247 | case MPI2_RAID_VOL_STATE_MISSING: | 5478 | case MPI2_RAID_VOL_STATE_MISSING: |
5248 | case MPI2_RAID_VOL_STATE_FAILED: | 5479 | case MPI2_RAID_VOL_STATE_FAILED: |
5249 | if (!raid_device) | 5480 | _scsih_sas_volume_delete(ioc, handle); |
5250 | break; | ||
5251 | if (raid_device->starget) { | ||
5252 | sas_target_priv_data = raid_device->starget->hostdata; | ||
5253 | sas_target_priv_data->deleted = 1; | ||
5254 | scsi_remove_target(&raid_device->starget->dev); | ||
5255 | } | ||
5256 | _scsih_raid_device_remove(ioc, raid_device); | ||
5257 | break; | 5481 | break; |
5258 | 5482 | ||
5259 | case MPI2_RAID_VOL_STATE_ONLINE: | 5483 | case MPI2_RAID_VOL_STATE_ONLINE: |
5260 | case MPI2_RAID_VOL_STATE_DEGRADED: | 5484 | case MPI2_RAID_VOL_STATE_DEGRADED: |
5261 | case MPI2_RAID_VOL_STATE_OPTIMAL: | 5485 | case MPI2_RAID_VOL_STATE_OPTIMAL: |
5486 | |||
5487 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | ||
5488 | raid_device = _scsih_raid_device_find_by_handle(ioc, handle); | ||
5489 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); | ||
5490 | |||
5262 | if (raid_device) | 5491 | if (raid_device) |
5263 | break; | 5492 | break; |
5264 | 5493 | ||
@@ -5327,19 +5556,21 @@ _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, | |||
5327 | "old(0x%08x), new(0x%08x)\n", ioc->name, __func__, handle, | 5556 | "old(0x%08x), new(0x%08x)\n", ioc->name, __func__, handle, |
5328 | le32_to_cpu(event_data->PreviousValue), state)); | 5557 | le32_to_cpu(event_data->PreviousValue), state)); |
5329 | 5558 | ||
5330 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
5331 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | ||
5332 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
5333 | |||
5334 | switch (state) { | 5559 | switch (state) { |
5335 | case MPI2_RAID_PD_STATE_ONLINE: | 5560 | case MPI2_RAID_PD_STATE_ONLINE: |
5336 | case MPI2_RAID_PD_STATE_DEGRADED: | 5561 | case MPI2_RAID_PD_STATE_DEGRADED: |
5337 | case MPI2_RAID_PD_STATE_REBUILDING: | 5562 | case MPI2_RAID_PD_STATE_REBUILDING: |
5338 | case MPI2_RAID_PD_STATE_OPTIMAL: | 5563 | case MPI2_RAID_PD_STATE_OPTIMAL: |
5339 | if (sas_device) { | 5564 | case MPI2_RAID_PD_STATE_HOT_SPARE: |
5340 | sas_device->hidden_raid_component = 1; | 5565 | |
5566 | set_bit(handle, ioc->pd_handles); | ||
5567 | |||
5568 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
5569 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | ||
5570 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
5571 | |||
5572 | if (sas_device) | ||
5341 | return; | 5573 | return; |
5342 | } | ||
5343 | 5574 | ||
5344 | if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, | 5575 | if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, |
5345 | &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, | 5576 | &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, |
@@ -5369,7 +5600,6 @@ _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, | |||
5369 | case MPI2_RAID_PD_STATE_OFFLINE: | 5600 | case MPI2_RAID_PD_STATE_OFFLINE: |
5370 | case MPI2_RAID_PD_STATE_NOT_CONFIGURED: | 5601 | case MPI2_RAID_PD_STATE_NOT_CONFIGURED: |
5371 | case MPI2_RAID_PD_STATE_NOT_COMPATIBLE: | 5602 | case MPI2_RAID_PD_STATE_NOT_COMPATIBLE: |
5372 | case MPI2_RAID_PD_STATE_HOT_SPARE: | ||
5373 | default: | 5603 | default: |
5374 | break; | 5604 | break; |
5375 | } | 5605 | } |
@@ -5497,7 +5727,7 @@ _scsih_task_set_full(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work | |||
5497 | sas_address = sas_device->sas_address; | 5727 | sas_address = sas_device->sas_address; |
5498 | 5728 | ||
5499 | /* if hidden raid component, then change to volume characteristics */ | 5729 | /* if hidden raid component, then change to volume characteristics */ |
5500 | if (sas_device->hidden_raid_component && sas_device->volume_handle) { | 5730 | if (test_bit(handle, ioc->pd_handles) && sas_device->volume_handle) { |
5501 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | 5731 | spin_lock_irqsave(&ioc->raid_device_lock, flags); |
5502 | raid_device = _scsih_raid_device_find_by_handle( | 5732 | raid_device = _scsih_raid_device_find_by_handle( |
5503 | ioc, sas_device->volume_handle); | 5733 | ioc, sas_device->volume_handle); |
@@ -5722,9 +5952,11 @@ static void | |||
5722 | _scsih_search_responding_raid_devices(struct MPT2SAS_ADAPTER *ioc) | 5952 | _scsih_search_responding_raid_devices(struct MPT2SAS_ADAPTER *ioc) |
5723 | { | 5953 | { |
5724 | Mpi2RaidVolPage1_t volume_pg1; | 5954 | Mpi2RaidVolPage1_t volume_pg1; |
5955 | Mpi2RaidPhysDiskPage0_t pd_pg0; | ||
5725 | Mpi2ConfigReply_t mpi_reply; | 5956 | Mpi2ConfigReply_t mpi_reply; |
5726 | u16 ioc_status; | 5957 | u16 ioc_status; |
5727 | u16 handle; | 5958 | u16 handle; |
5959 | u8 phys_disk_num; | ||
5728 | 5960 | ||
5729 | printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__); | 5961 | printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__); |
5730 | 5962 | ||
@@ -5742,6 +5974,21 @@ _scsih_search_responding_raid_devices(struct MPT2SAS_ADAPTER *ioc) | |||
5742 | _scsih_mark_responding_raid_device(ioc, | 5974 | _scsih_mark_responding_raid_device(ioc, |
5743 | le64_to_cpu(volume_pg1.WWID), handle); | 5975 | le64_to_cpu(volume_pg1.WWID), handle); |
5744 | } | 5976 | } |
5977 | |||
5978 | /* refresh the pd_handles */ | ||
5979 | phys_disk_num = 0xFF; | ||
5980 | memset(ioc->pd_handles, 0, ioc->pd_handles_sz); | ||
5981 | while (!(mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply, | ||
5982 | &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM, | ||
5983 | phys_disk_num))) { | ||
5984 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
5985 | MPI2_IOCSTATUS_MASK; | ||
5986 | if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) | ||
5987 | break; | ||
5988 | phys_disk_num = pd_pg0.PhysDiskNum; | ||
5989 | handle = le16_to_cpu(pd_pg0.DevHandle); | ||
5990 | set_bit(handle, ioc->pd_handles); | ||
5991 | } | ||
5745 | } | 5992 | } |
5746 | 5993 | ||
5747 | /** | 5994 | /** |
@@ -6060,14 +6307,21 @@ mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, | |||
6060 | (Mpi2EventDataSasTopologyChangeList_t *) | 6307 | (Mpi2EventDataSasTopologyChangeList_t *) |
6061 | mpi_reply->EventData); | 6308 | mpi_reply->EventData); |
6062 | break; | 6309 | break; |
6063 | 6310 | case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST: | |
6311 | _scsih_check_ir_config_unhide_events(ioc, | ||
6312 | (Mpi2EventDataIrConfigChangeList_t *) | ||
6313 | mpi_reply->EventData); | ||
6314 | break; | ||
6315 | case MPI2_EVENT_IR_VOLUME: | ||
6316 | _scsih_check_volume_delete_events(ioc, | ||
6317 | (Mpi2EventDataIrVolume_t *) | ||
6318 | mpi_reply->EventData); | ||
6319 | break; | ||
6064 | case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE: | 6320 | case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE: |
6065 | case MPI2_EVENT_IR_OPERATION_STATUS: | 6321 | case MPI2_EVENT_IR_OPERATION_STATUS: |
6066 | case MPI2_EVENT_SAS_DISCOVERY: | 6322 | case MPI2_EVENT_SAS_DISCOVERY: |
6067 | case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE: | 6323 | case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE: |
6068 | case MPI2_EVENT_IR_VOLUME: | ||
6069 | case MPI2_EVENT_IR_PHYSICAL_DISK: | 6324 | case MPI2_EVENT_IR_PHYSICAL_DISK: |
6070 | case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST: | ||
6071 | case MPI2_EVENT_TASK_SET_FULL: | 6325 | case MPI2_EVENT_TASK_SET_FULL: |
6072 | break; | 6326 | break; |
6073 | 6327 | ||
@@ -6574,6 +6828,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
6574 | ioc->scsih_cb_idx = scsih_cb_idx; | 6828 | ioc->scsih_cb_idx = scsih_cb_idx; |
6575 | ioc->config_cb_idx = config_cb_idx; | 6829 | ioc->config_cb_idx = config_cb_idx; |
6576 | ioc->tm_tr_cb_idx = tm_tr_cb_idx; | 6830 | ioc->tm_tr_cb_idx = tm_tr_cb_idx; |
6831 | ioc->tm_tr_volume_cb_idx = tm_tr_volume_cb_idx; | ||
6577 | ioc->tm_sas_control_cb_idx = tm_sas_control_cb_idx; | 6832 | ioc->tm_sas_control_cb_idx = tm_sas_control_cb_idx; |
6578 | ioc->logging_level = logging_level; | 6833 | ioc->logging_level = logging_level; |
6579 | /* misc semaphores and spin locks */ | 6834 | /* misc semaphores and spin locks */ |
@@ -6592,6 +6847,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
6592 | INIT_LIST_HEAD(&ioc->raid_device_list); | 6847 | INIT_LIST_HEAD(&ioc->raid_device_list); |
6593 | INIT_LIST_HEAD(&ioc->sas_hba.sas_port_list); | 6848 | INIT_LIST_HEAD(&ioc->sas_hba.sas_port_list); |
6594 | INIT_LIST_HEAD(&ioc->delayed_tr_list); | 6849 | INIT_LIST_HEAD(&ioc->delayed_tr_list); |
6850 | INIT_LIST_HEAD(&ioc->delayed_tr_volume_list); | ||
6595 | 6851 | ||
6596 | /* init shost parameters */ | 6852 | /* init shost parameters */ |
6597 | shost->max_cmd_len = 32; | 6853 | shost->max_cmd_len = 32; |
@@ -6894,6 +7150,10 @@ _scsih_init(void) | |||
6894 | 7150 | ||
6895 | tm_tr_cb_idx = mpt2sas_base_register_callback_handler( | 7151 | tm_tr_cb_idx = mpt2sas_base_register_callback_handler( |
6896 | _scsih_tm_tr_complete); | 7152 | _scsih_tm_tr_complete); |
7153 | |||
7154 | tm_tr_volume_cb_idx = mpt2sas_base_register_callback_handler( | ||
7155 | _scsih_tm_volume_tr_complete); | ||
7156 | |||
6897 | tm_sas_control_cb_idx = mpt2sas_base_register_callback_handler( | 7157 | tm_sas_control_cb_idx = mpt2sas_base_register_callback_handler( |
6898 | _scsih_sas_control_complete); | 7158 | _scsih_sas_control_complete); |
6899 | 7159 | ||
@@ -6933,6 +7193,7 @@ _scsih_exit(void) | |||
6933 | mpt2sas_base_release_callback_handler(ctl_cb_idx); | 7193 | mpt2sas_base_release_callback_handler(ctl_cb_idx); |
6934 | 7194 | ||
6935 | mpt2sas_base_release_callback_handler(tm_tr_cb_idx); | 7195 | mpt2sas_base_release_callback_handler(tm_tr_cb_idx); |
7196 | mpt2sas_base_release_callback_handler(tm_tr_volume_cb_idx); | ||
6936 | mpt2sas_base_release_callback_handler(tm_sas_control_cb_idx); | 7197 | mpt2sas_base_release_callback_handler(tm_sas_control_cb_idx); |
6937 | 7198 | ||
6938 | /* raid transport support */ | 7199 | /* raid transport support */ |