aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorKashyap, Desai <kashyap.desai@lsi.com>2009-05-29 07:17:26 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2009-06-09 18:41:36 -0400
commit3eb0822c6740c5564c37a2fe56449cdb4f3d800c (patch)
tree10c2a016020e4363b4db164b09f48530fbcaa517 /drivers
parentea2a788de4ce5ebab09276e25443f55592af2335 (diff)
[SCSI] mpt fusion: Firmware event implementation using seperate WorkQueue
Now Firmware events are handled by firmware event queue. Previously it was handled in interrupt context/WorkQueue of Linux. Firmware Event handling is restructured and optimized. Signed-off-by: Kashyap Desai <kadesai@lsi.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/message/fusion/mptbase.c10
-rw-r--r--drivers/message/fusion/mptbase.h9
-rw-r--r--drivers/message/fusion/mptsas.c1378
-rw-r--r--drivers/message/fusion/mptsas.h33
4 files changed, 984 insertions, 446 deletions
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index ae203eca831..d67b26378a5 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -1931,6 +1931,11 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
1931 */ 1931 */
1932 mpt_detect_bound_ports(ioc, pdev); 1932 mpt_detect_bound_ports(ioc, pdev);
1933 1933
1934 INIT_LIST_HEAD(&ioc->fw_event_list);
1935 spin_lock_init(&ioc->fw_event_lock);
1936 snprintf(ioc->fw_event_q_name, 20, "mpt/%d", ioc->id);
1937 ioc->fw_event_q = create_singlethread_workqueue(ioc->fw_event_q_name);
1938
1934 if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP, 1939 if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
1935 CAN_SLEEP)) != 0){ 1940 CAN_SLEEP)) != 0){
1936 printk(MYIOC_s_ERR_FMT "didn't initialize properly! (%d)\n", 1941 printk(MYIOC_s_ERR_FMT "didn't initialize properly! (%d)\n",
@@ -2010,6 +2015,11 @@ mpt_detach(struct pci_dev *pdev)
2010 cancel_delayed_work(&ioc->fault_reset_work); 2015 cancel_delayed_work(&ioc->fault_reset_work);
2011 destroy_workqueue(wq); 2016 destroy_workqueue(wq);
2012 2017
2018 spin_lock_irqsave(&ioc->fw_event_lock, flags);
2019 wq = ioc->fw_event_q;
2020 ioc->fw_event_q = NULL;
2021 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
2022 destroy_workqueue(wq);
2013 2023
2014 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name); 2024 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name);
2015 remove_proc_entry(pname, NULL); 2025 remove_proc_entry(pname, NULL);
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index 24d60128bfe..b6efc64e826 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -694,9 +694,18 @@ typedef struct _MPT_ADAPTER
694 struct net_device *netdev; 694 struct net_device *netdev;
695 struct list_head sas_topology; 695 struct list_head sas_topology;
696 struct mutex sas_topology_mutex; 696 struct mutex sas_topology_mutex;
697
698 struct workqueue_struct *fw_event_q;
699 struct list_head fw_event_list;
700 spinlock_t fw_event_lock;
701 u8 fw_events_off; /* if '1', then ignore events */
702 char fw_event_q_name[20];
703
697 struct mutex sas_discovery_mutex; 704 struct mutex sas_discovery_mutex;
698 u8 sas_discovery_runtime; 705 u8 sas_discovery_runtime;
699 u8 sas_discovery_ignore_events; 706 u8 sas_discovery_ignore_events;
707 struct list_head sas_device_info_list;
708 struct mutex sas_device_info_mutex;
700 u8 sas_discovery_quiesce_io; 709 u8 sas_discovery_quiesce_io;
701 int sas_index; /* index refrencing */ 710 int sas_index; /* index refrencing */
702 MPT_MGMT sas_mgmt; 711 MPT_MGMT sas_mgmt;
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index eb6b10eb11d..22a027ec9e5 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -95,7 +95,24 @@ static u8 mptsasInternalCtx = MPT_MAX_PROTOCOL_DRIVERS; /* Used only for interna
95static u8 mptsasMgmtCtx = MPT_MAX_PROTOCOL_DRIVERS; 95static u8 mptsasMgmtCtx = MPT_MAX_PROTOCOL_DRIVERS;
96static u8 mptsasDeviceResetCtx = MPT_MAX_PROTOCOL_DRIVERS; 96static u8 mptsasDeviceResetCtx = MPT_MAX_PROTOCOL_DRIVERS;
97 97
98static void mptsas_hotplug_work(struct work_struct *work); 98static void mptsas_firmware_event_work(struct work_struct *work);
99static void mptsas_send_sas_event(struct fw_event_work *fw_event);
100static void mptsas_send_raid_event(struct fw_event_work *fw_event);
101static void mptsas_send_ir2_event(struct fw_event_work *fw_event);
102static void mptsas_parse_device_info(struct sas_identify *identify,
103 struct mptsas_devinfo *device_info);
104static inline void mptsas_set_rphy(MPT_ADAPTER *ioc,
105 struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy);
106static struct mptsas_phyinfo *mptsas_find_phyinfo_by_sas_address
107 (MPT_ADAPTER *ioc, u64 sas_address);
108static int mptsas_sas_device_pg0(MPT_ADAPTER *ioc,
109 struct mptsas_devinfo *device_info, u32 form, u32 form_specific);
110static int mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc,
111 struct mptsas_enclosure *enclosure, u32 form, u32 form_specific);
112static int mptsas_add_end_device(MPT_ADAPTER *ioc,
113 struct mptsas_phyinfo *phy_info);
114static void mptsas_del_end_device(MPT_ADAPTER *ioc,
115 struct mptsas_phyinfo *phy_info);
99 116
100static void mptsas_print_phy_data(MPT_ADAPTER *ioc, 117static void mptsas_print_phy_data(MPT_ADAPTER *ioc,
101 MPI_SAS_IO_UNIT0_PHY_DATA *phy_data) 118 MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
@@ -219,6 +236,100 @@ static void mptsas_print_expander_pg1(MPT_ADAPTER *ioc, SasExpanderPage1_t *pg1)
219 le16_to_cpu(pg1->AttachedDevHandle))); 236 le16_to_cpu(pg1->AttachedDevHandle)));
220} 237}
221 238
239/* inhibit sas firmware event handling */
240static void
241mptsas_fw_event_off(MPT_ADAPTER *ioc)
242{
243 unsigned long flags;
244
245 spin_lock_irqsave(&ioc->fw_event_lock, flags);
246 ioc->fw_events_off = 1;
247 ioc->sas_discovery_quiesce_io = 0;
248 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
249
250}
251
252/* enable sas firmware event handling */
253static void
254mptsas_fw_event_on(MPT_ADAPTER *ioc)
255{
256 unsigned long flags;
257
258 spin_lock_irqsave(&ioc->fw_event_lock, flags);
259 ioc->fw_events_off = 0;
260 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
261}
262
263/* queue a sas firmware event */
264static void
265mptsas_add_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,
266 unsigned long delay)
267{
268 unsigned long flags;
269
270 spin_lock_irqsave(&ioc->fw_event_lock, flags);
271 list_add_tail(&fw_event->list, &ioc->fw_event_list);
272 INIT_DELAYED_WORK(&fw_event->work, mptsas_firmware_event_work);
273 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: add (fw_event=0x%p)\n",
274 ioc->name, __func__, fw_event));
275 queue_delayed_work(ioc->fw_event_q, &fw_event->work,
276 delay);
277 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
278}
279
280/* free memory assoicated to a sas firmware event */
281static void
282mptsas_free_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event)
283{
284 unsigned long flags;
285
286 spin_lock_irqsave(&ioc->fw_event_lock, flags);
287 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: kfree (fw_event=0x%p)\n",
288 ioc->name, __func__, fw_event));
289 list_del(&fw_event->list);
290 kfree(fw_event);
291 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
292}
293
294/* walk the firmware event queue, and either stop or wait for
295 * outstanding events to complete */
296static void
297mptsas_cleanup_fw_event_q(MPT_ADAPTER *ioc)
298{
299 struct fw_event_work *fw_event, *next;
300 struct mptsas_target_reset_event *target_reset_list, *n;
301 u8 flush_q;
302 MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
303
304 /* flush the target_reset_list */
305 if (!list_empty(&hd->target_reset_list)) {
306 list_for_each_entry_safe(target_reset_list, n,
307 &hd->target_reset_list, list) {
308 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
309 "%s: removing target reset for id=%d\n",
310 ioc->name, __func__,
311 target_reset_list->sas_event_data.TargetID));
312 list_del(&target_reset_list->list);
313 kfree(target_reset_list);
314 }
315 }
316
317 if (list_empty(&ioc->fw_event_list) ||
318 !ioc->fw_event_q || in_interrupt())
319 return;
320
321 flush_q = 0;
322 list_for_each_entry_safe(fw_event, next, &ioc->fw_event_list, list) {
323 if (cancel_delayed_work(&fw_event->work))
324 mptsas_free_fw_event(ioc, fw_event);
325 else
326 flush_q = 1;
327 }
328 if (flush_q)
329 flush_workqueue(ioc->fw_event_q);
330}
331
332
222static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy) 333static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
223{ 334{
224 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); 335 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
@@ -309,6 +420,7 @@ mptsas_port_delete(MPT_ADAPTER *ioc, struct mptsas_portinfo_details * port_detai
309 if(phy_info->port_details != port_details) 420 if(phy_info->port_details != port_details)
310 continue; 421 continue;
311 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo)); 422 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
423 mptsas_set_rphy(ioc, phy_info, NULL);
312 phy_info->port_details = NULL; 424 phy_info->port_details = NULL;
313 } 425 }
314 kfree(port_details); 426 kfree(port_details);
@@ -380,6 +492,157 @@ starget)
380 phy_info->port_details->starget = starget; 492 phy_info->port_details->starget = starget;
381} 493}
382 494
495/**
496 * mptsas_add_device_component -
497 * @ioc: Pointer to MPT_ADAPTER structure
498 * @channel: fw mapped id's
499 * @id:
500 * @sas_address:
501 * @device_info:
502 *
503 **/
504static void
505mptsas_add_device_component(MPT_ADAPTER *ioc, u8 channel, u8 id,
506 u64 sas_address, u32 device_info, u16 slot, u64 enclosure_logical_id)
507{
508 struct mptsas_device_info *sas_info, *next;
509 struct scsi_device *sdev;
510 struct scsi_target *starget;
511 struct sas_rphy *rphy;
512
513 /*
514 * Delete all matching devices out of the list
515 */
516 mutex_lock(&ioc->sas_device_info_mutex);
517 list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
518 list) {
519 if ((sas_info->sas_address == sas_address ||
520 (sas_info->fw.channel == channel &&
521 sas_info->fw.id == id))) {
522 list_del(&sas_info->list);
523 kfree(sas_info);
524 }
525 }
526
527 sas_info = kzalloc(sizeof(struct mptsas_device_info), GFP_KERNEL);
528 if (!sas_info)
529 goto out;
530
531 /*
532 * Set Firmware mapping
533 */
534 sas_info->fw.id = id;
535 sas_info->fw.channel = channel;
536
537 sas_info->sas_address = sas_address;
538 sas_info->device_info = device_info;
539 sas_info->slot = slot;
540 sas_info->enclosure_logical_id = enclosure_logical_id;
541 INIT_LIST_HEAD(&sas_info->list);
542 list_add_tail(&sas_info->list, &ioc->sas_device_info_list);
543
544 /*
545 * Set OS mapping
546 */
547 shost_for_each_device(sdev, ioc->sh) {
548 starget = scsi_target(sdev);
549 rphy = dev_to_rphy(starget->dev.parent);
550 if (rphy->identify.sas_address == sas_address) {
551 sas_info->os.id = starget->id;
552 sas_info->os.channel = starget->channel;
553 }
554 }
555
556 out:
557 mutex_unlock(&ioc->sas_device_info_mutex);
558 return;
559}
560
561/**
562 * mptsas_add_device_component_by_fw -
563 * @ioc: Pointer to MPT_ADAPTER structure
564 * @channel: fw mapped id's
565 * @id:
566 *
567 **/
568static void
569mptsas_add_device_component_by_fw(MPT_ADAPTER *ioc, u8 channel, u8 id)
570{
571 struct mptsas_devinfo sas_device;
572 struct mptsas_enclosure enclosure_info;
573 int rc;
574
575 rc = mptsas_sas_device_pg0(ioc, &sas_device,
576 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
577 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
578 (channel << 8) + id);
579 if (rc)
580 return;
581
582 memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
583 mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
584 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
585 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT),
586 sas_device.handle_enclosure);
587
588 mptsas_add_device_component(ioc, sas_device.channel,
589 sas_device.id, sas_device.sas_address, sas_device.device_info,
590 sas_device.slot, enclosure_info.enclosure_logical_id);
591}
592
593/**
594 * mptsas_add_device_component_starget -
595 * @ioc: Pointer to MPT_ADAPTER structure
596 * @starget:
597 *
598 **/
599static void
600mptsas_add_device_component_starget(MPT_ADAPTER *ioc,
601 struct scsi_target *starget)
602{
603 VirtTarget *vtarget;
604 struct sas_rphy *rphy;
605 struct mptsas_phyinfo *phy_info = NULL;
606 struct mptsas_enclosure enclosure_info;
607
608 rphy = dev_to_rphy(starget->dev.parent);
609 vtarget = starget->hostdata;
610 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
611 rphy->identify.sas_address);
612 if (!phy_info)
613 return;
614
615 memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
616 mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
617 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
618 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT),
619 phy_info->attached.handle_enclosure);
620
621 mptsas_add_device_component(ioc, phy_info->attached.channel,
622 phy_info->attached.id, phy_info->attached.sas_address,
623 phy_info->attached.device_info,
624 phy_info->attached.slot, enclosure_info.enclosure_logical_id);
625}
626
627/**
628 * mptsas_del_device_components - Cleaning the list
629 * @ioc: Pointer to MPT_ADAPTER structure
630 *
631 **/
632static void
633mptsas_del_device_components(MPT_ADAPTER *ioc)
634{
635 struct mptsas_device_info *sas_info, *next;
636
637 mutex_lock(&ioc->sas_device_info_mutex);
638 list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
639 list) {
640 list_del(&sas_info->list);
641 kfree(sas_info);
642 }
643 mutex_unlock(&ioc->sas_device_info_mutex);
644}
645
383 646
384/* 647/*
385 * mptsas_setup_wide_ports 648 * mptsas_setup_wide_ports
@@ -535,6 +798,29 @@ mptsas_find_vtarget(MPT_ADAPTER *ioc, u8 channel, u8 id)
535 return vtarget; 798 return vtarget;
536} 799}
537 800
801static void
802mptsas_queue_device_delete(MPT_ADAPTER *ioc,
803 MpiEventDataSasDeviceStatusChange_t *sas_event_data)
804{
805 struct fw_event_work *fw_event;
806 int sz;
807
808 sz = offsetof(struct fw_event_work, event_data) +
809 sizeof(MpiEventDataSasDeviceStatusChange_t);
810 fw_event = kzalloc(sz, GFP_ATOMIC);
811 if (!fw_event) {
812 printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n",
813 ioc->name, __func__, __LINE__);
814 return;
815 }
816 memcpy(fw_event->event_data, sas_event_data,
817 sizeof(MpiEventDataSasDeviceStatusChange_t));
818 fw_event->event = MPI_EVENT_SAS_DEVICE_STATUS_CHANGE;
819 fw_event->ioc = ioc;
820 mptsas_add_fw_event(ioc, fw_event, msecs_to_jiffies(1));
821}
822
823
538/** 824/**
539 * mptsas_target_reset 825 * mptsas_target_reset
540 * 826 *
@@ -654,10 +940,8 @@ mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
654{ 940{
655 MPT_SCSI_HOST *hd = shost_priv(ioc->sh); 941 MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
656 struct list_head *head = &hd->target_reset_list; 942 struct list_head *head = &hd->target_reset_list;
657 struct mptsas_hotplug_event *ev;
658 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data; 943 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data;
659 u8 id, channel; 944 u8 id, channel;
660 __le64 sas_address;
661 struct mptsas_target_reset_event *target_reset_list; 945 struct mptsas_target_reset_event *target_reset_list;
662 SCSITaskMgmtReply_t *pScsiTmReply; 946 SCSITaskMgmtReply_t *pScsiTmReply;
663 947
@@ -729,41 +1013,9 @@ mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
729 * enable work queue to remove device from upper layers 1013 * enable work queue to remove device from upper layers
730 */ 1014 */
731 list_del(&target_reset_list->list); 1015 list_del(&target_reset_list->list);
732 1016 if ((mptsas_find_vtarget(ioc, channel, id)) && !ioc->fw_events_off)
733 ev = kzalloc(sizeof(*ev), GFP_ATOMIC); 1017 mptsas_queue_device_delete(ioc,
734 if (!ev) { 1018 &target_reset_list->sas_event_data);
735 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n",
736 ioc->name,__func__, __LINE__));
737 goto out_fail;
738 }
739
740 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request (mf=%p)\n",
741 ioc->name, mf));
742
743 INIT_WORK(&ev->work, mptsas_hotplug_work);
744 ev->ioc = ioc;
745 ev->handle = le16_to_cpu(sas_event_data->DevHandle);
746 ev->parent_handle =
747 le16_to_cpu(sas_event_data->ParentDevHandle);
748 ev->channel = channel;
749 ev->id =id;
750 ev->phy_id = sas_event_data->PhyNum;
751 memcpy(&sas_address, &sas_event_data->SASAddress,
752 sizeof(__le64));
753 ev->sas_address = le64_to_cpu(sas_address);
754 ev->device_info = le32_to_cpu(sas_event_data->DeviceInfo);
755 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
756 "TaskMgmt type=%d (sas device delete) fw_channel = %d fw_id = %d)\n",
757 ioc->name, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, channel, id));
758
759 ev->event_type = MPTSAS_DEL_DEVICE;
760 schedule_work(&ev->work);
761 kfree(target_reset_list);
762
763 out_fail:
764
765 mpt_clear_taskmgmt_in_progress_flag(ioc);
766 return 0;
767 1019
768 1020
769 /* 1021 /*
@@ -798,37 +1050,58 @@ static int
798mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) 1050mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
799{ 1051{
800 MPT_SCSI_HOST *hd; 1052 MPT_SCSI_HOST *hd;
801 struct mptsas_target_reset_event *target_reset_list, *n;
802 int rc; 1053 int rc;
803 1054
804 rc = mptscsih_ioc_reset(ioc, reset_phase); 1055 rc = mptscsih_ioc_reset(ioc, reset_phase);
1056 if ((ioc->bus_type != SAS) || (!rc))
1057 return rc;
805 1058
806 if (ioc->bus_type != SAS)
807 goto out;
808
809 if (reset_phase != MPT_IOC_POST_RESET)
810 goto out;
811
812 if (!ioc->sh || !ioc->sh->hostdata)
813 goto out;
814 hd = shost_priv(ioc->sh); 1059 hd = shost_priv(ioc->sh);
815 if (!hd->ioc) 1060 if (!hd->ioc)
816 goto out; 1061 goto out;
817 1062
818 if (list_empty(&hd->target_reset_list)) 1063 switch (reset_phase) {
819 goto out; 1064 case MPT_IOC_SETUP_RESET:
820 1065 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
821 /* flush the target_reset_list */ 1066 "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __func__));
822 list_for_each_entry_safe(target_reset_list, n, 1067 mptsas_fw_event_off(ioc);
823 &hd->target_reset_list, list) { 1068 break;
824 list_del(&target_reset_list->list); 1069 case MPT_IOC_PRE_RESET:
825 kfree(target_reset_list); 1070 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1071 "%s: MPT_IOC_PRE_RESET\n", ioc->name, __func__));
1072 break;
1073 case MPT_IOC_POST_RESET:
1074 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1075 "%s: MPT_IOC_POST_RESET\n", ioc->name, __func__));
1076 if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_PENDING) {
1077 ioc->sas_mgmt.status |= MPT_MGMT_STATUS_DID_IOCRESET;
1078 complete(&ioc->sas_mgmt.done);
1079 }
1080 mptsas_cleanup_fw_event_q(ioc);
1081 mptsas_fw_event_on(ioc);
1082 break;
1083 default:
1084 break;
826 } 1085 }
827 1086
828 out: 1087 out:
829 return rc; 1088 return rc;
830} 1089}
831 1090
1091
1092/**
1093 * enum device_state -
1094 * @DEVICE_RETRY: need to retry the TUR
1095 * @DEVICE_ERROR: TUR return error, don't add device
1096 * @DEVICE_READY: device can be added
1097 *
1098 */
1099enum device_state{
1100 DEVICE_RETRY,
1101 DEVICE_ERROR,
1102 DEVICE_READY,
1103};
1104
832static int 1105static int
833mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure, 1106mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
834 u32 form, u32 form_specific) 1107 u32 form, u32 form_specific)
@@ -894,15 +1167,268 @@ mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
894 return error; 1167 return error;
895} 1168}
896 1169
1170/**
1171 * mptsas_add_end_device - report a new end device to sas transport layer
1172 * @ioc: Pointer to MPT_ADAPTER structure
1173 * @phy_info: decribes attached device
1174 *
1175 * return (0) success (1) failure
1176 *
1177 **/
1178static int
1179mptsas_add_end_device(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info)
1180{
1181 struct sas_rphy *rphy;
1182 struct sas_port *port;
1183 struct sas_identify identify;
1184 char *ds = NULL;
1185 u8 fw_id;
1186
1187 if (!phy_info) {
1188 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1189 "%s: exit at line=%d\n", ioc->name,
1190 __func__, __LINE__));
1191 return 1;
1192 }
1193
1194 fw_id = phy_info->attached.id;
1195
1196 if (mptsas_get_rphy(phy_info)) {
1197 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1198 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1199 __func__, fw_id, __LINE__));
1200 return 2;
1201 }
1202
1203 port = mptsas_get_port(phy_info);
1204 if (!port) {
1205 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1206 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1207 __func__, fw_id, __LINE__));
1208 return 3;
1209 }
1210
1211 if (phy_info->attached.device_info &
1212 MPI_SAS_DEVICE_INFO_SSP_TARGET)
1213 ds = "ssp";
1214 if (phy_info->attached.device_info &
1215 MPI_SAS_DEVICE_INFO_STP_TARGET)
1216 ds = "stp";
1217 if (phy_info->attached.device_info &
1218 MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1219 ds = "sata";
1220
1221 printk(MYIOC_s_INFO_FMT "attaching %s device: fw_channel %d, fw_id %d,"
1222 " phy %d, sas_addr 0x%llx\n", ioc->name, ds,
1223 phy_info->attached.channel, phy_info->attached.id,
1224 phy_info->attached.phy_id, (unsigned long long)
1225 phy_info->attached.sas_address);
1226
1227 mptsas_parse_device_info(&identify, &phy_info->attached);
1228 rphy = sas_end_device_alloc(port);
1229 if (!rphy) {
1230 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1231 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1232 __func__, fw_id, __LINE__));
1233 return 5; /* non-fatal: an rphy can be added later */
1234 }
1235
1236 rphy->identify = identify;
1237 if (sas_rphy_add(rphy)) {
1238 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1239 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1240 __func__, fw_id, __LINE__));
1241 sas_rphy_free(rphy);
1242 return 6;
1243 }
1244 mptsas_set_rphy(ioc, phy_info, rphy);
1245 return 0;
1246}
1247
1248/**
1249 * mptsas_del_end_device - report a deleted end device to sas transport
1250 * layer
1251 * @ioc: Pointer to MPT_ADAPTER structure
1252 * @phy_info: decribes attached device
1253 *
1254 **/
1255static void
1256mptsas_del_end_device(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info)
1257{
1258 struct sas_rphy *rphy;
1259 struct sas_port *port;
1260 struct mptsas_portinfo *port_info;
1261 struct mptsas_phyinfo *phy_info_parent;
1262 int i;
1263 char *ds = NULL;
1264 u8 fw_id;
1265 u64 sas_address;
1266
1267 if (!phy_info)
1268 return;
1269
1270 fw_id = phy_info->attached.id;
1271 sas_address = phy_info->attached.sas_address;
1272
1273 if (!phy_info->port_details) {
1274 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1275 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1276 __func__, fw_id, __LINE__));
1277 return;
1278 }
1279 rphy = mptsas_get_rphy(phy_info);
1280 if (!rphy) {
1281 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1282 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1283 __func__, fw_id, __LINE__));
1284 return;
1285 }
1286
1287 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_INITIATOR
1288 || phy_info->attached.device_info
1289 & MPI_SAS_DEVICE_INFO_SMP_INITIATOR
1290 || phy_info->attached.device_info
1291 & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
1292 ds = "initiator";
1293 if (phy_info->attached.device_info &
1294 MPI_SAS_DEVICE_INFO_SSP_TARGET)
1295 ds = "ssp";
1296 if (phy_info->attached.device_info &
1297 MPI_SAS_DEVICE_INFO_STP_TARGET)
1298 ds = "stp";
1299 if (phy_info->attached.device_info &
1300 MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1301 ds = "sata";
1302
1303 dev_printk(KERN_DEBUG, &rphy->dev, MYIOC_s_FMT
1304 "removing %s device: fw_channel %d, fw_id %d, phy %d,"
1305 "sas_addr 0x%llx\n", ioc->name, ds, phy_info->attached.channel,
1306 phy_info->attached.id, phy_info->attached.phy_id,
1307 (unsigned long long) sas_address);
1308
1309 port = mptsas_get_port(phy_info);
1310 if (!port) {
1311 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1312 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1313 __func__, fw_id, __LINE__));
1314 return;
1315 }
1316 port_info = phy_info->portinfo;
1317 phy_info_parent = port_info->phy_info;
1318 for (i = 0; i < port_info->num_phys; i++, phy_info_parent++) {
1319 if (!phy_info_parent->phy)
1320 continue;
1321 if (phy_info_parent->attached.sas_address !=
1322 sas_address)
1323 continue;
1324 dev_printk(KERN_DEBUG, &phy_info_parent->phy->dev,
1325 MYIOC_s_FMT "delete phy %d, phy-obj (0x%p)\n",
1326 ioc->name, phy_info_parent->phy_id,
1327 phy_info_parent->phy);
1328 sas_port_delete_phy(port, phy_info_parent->phy);
1329 }
1330
1331 dev_printk(KERN_DEBUG, &port->dev, MYIOC_s_FMT
1332 "delete port %d, sas_addr (0x%llx)\n", ioc->name,
1333 port->port_identifier, (unsigned long long)sas_address);
1334 sas_port_delete(port);
1335 mptsas_set_port(ioc, phy_info, NULL);
1336 mptsas_port_delete(ioc, phy_info->port_details);
1337}
1338
1339struct mptsas_phyinfo *
1340mptsas_refreshing_device_handles(MPT_ADAPTER *ioc,
1341 struct mptsas_devinfo *sas_device)
1342{
1343 struct mptsas_phyinfo *phy_info;
1344 struct mptsas_portinfo *port_info;
1345 int i;
1346
1347 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
1348 sas_device->sas_address);
1349 if (!phy_info)
1350 goto out;
1351 port_info = phy_info->portinfo;
1352 if (!port_info)
1353 goto out;
1354 mutex_lock(&ioc->sas_topology_mutex);
1355 for (i = 0; i < port_info->num_phys; i++) {
1356 if (port_info->phy_info[i].attached.sas_address !=
1357 sas_device->sas_address)
1358 continue;
1359 port_info->phy_info[i].attached.channel = sas_device->channel;
1360 port_info->phy_info[i].attached.id = sas_device->id;
1361 port_info->phy_info[i].attached.sas_address =
1362 sas_device->sas_address;
1363 port_info->phy_info[i].attached.handle = sas_device->handle;
1364 port_info->phy_info[i].attached.handle_parent =
1365 sas_device->handle_parent;
1366 port_info->phy_info[i].attached.handle_enclosure =
1367 sas_device->handle_enclosure;
1368 }
1369 mutex_unlock(&ioc->sas_topology_mutex);
1370 out:
1371 return phy_info;
1372}
1373
1374/**
1375 * mptsas_firmware_event_work - work thread for processing fw events
1376 * @work: work queue payload containing info describing the event
1377 * Context: user
1378 *
1379 */
1380static void
1381mptsas_firmware_event_work(struct work_struct *work)
1382{
1383 struct fw_event_work *fw_event =
1384 container_of(work, struct fw_event_work, work.work);
1385 MPT_ADAPTER *ioc = fw_event->ioc;
1386
1387
1388 /* events handling turned off during host reset */
1389 if (ioc->fw_events_off) {
1390 mptsas_free_fw_event(ioc, fw_event);
1391 return;
1392 }
1393
1394 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: fw_event=(0x%p), "
1395 "event = (0x%02x)\n", ioc->name, __func__, fw_event,
1396 (fw_event->event & 0xFF)));
1397
1398 switch (fw_event->event) {
1399 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
1400 mptsas_send_sas_event(fw_event);
1401 break;
1402 case MPI_EVENT_INTEGRATED_RAID:
1403 mptsas_send_raid_event(fw_event);
1404 break;
1405 case MPI_EVENT_IR2:
1406 mptsas_send_ir2_event(fw_event);
1407 break;
1408 case MPI_EVENT_PERSISTENT_TABLE_FULL:
1409 mptbase_sas_persist_operation(ioc,
1410 MPI_SAS_OP_CLEAR_NOT_PRESENT);
1411 mptsas_free_fw_event(ioc, fw_event);
1412 break;
1413 }
1414}
1415
1416
1417
897static int 1418static int
898mptsas_slave_configure(struct scsi_device *sdev) 1419mptsas_slave_configure(struct scsi_device *sdev)
899{ 1420{
1421 struct Scsi_Host *host = sdev->host;
1422 MPT_SCSI_HOST *hd = shost_priv(host);
1423 MPT_ADAPTER *ioc = hd->ioc;
900 1424
901 if (sdev->channel == MPTSAS_RAID_CHANNEL) 1425 if (sdev->channel == MPTSAS_RAID_CHANNEL)
902 goto out; 1426 goto out;
903 1427
904 sas_read_port_mode_page(sdev); 1428 sas_read_port_mode_page(sdev);
905 1429
1430 mptsas_add_device_component_starget(ioc, scsi_target(sdev));
1431
906 out: 1432 out:
907 return mptscsih_slave_configure(sdev); 1433 return mptscsih_slave_configure(sdev);
908} 1434}
@@ -984,11 +1510,15 @@ mptsas_target_destroy(struct scsi_target *starget)
984 struct sas_rphy *rphy; 1510 struct sas_rphy *rphy;
985 struct mptsas_portinfo *p; 1511 struct mptsas_portinfo *p;
986 int i; 1512 int i;
987 MPT_ADAPTER *ioc = hd->ioc; 1513 MPT_ADAPTER *ioc = hd->ioc;
1514 VirtTarget *vtarget;
988 1515
989 if (!starget->hostdata) 1516 if (!starget->hostdata)
990 return; 1517 return;
991 1518
1519 vtarget = starget->hostdata;
1520
1521
992 if (starget->channel == MPTSAS_RAID_CHANNEL) 1522 if (starget->channel == MPTSAS_RAID_CHANNEL)
993 goto out; 1523 goto out;
994 1524
@@ -998,12 +1528,21 @@ mptsas_target_destroy(struct scsi_target *starget)
998 if (p->phy_info[i].attached.sas_address != 1528 if (p->phy_info[i].attached.sas_address !=
999 rphy->identify.sas_address) 1529 rphy->identify.sas_address)
1000 continue; 1530 continue;
1531
1532 starget_printk(KERN_INFO, starget, MYIOC_s_FMT
1533 "delete device: fw_channel %d, fw_id %d, phy %d, "
1534 "sas_addr 0x%llx\n", ioc->name,
1535 p->phy_info[i].attached.channel,
1536 p->phy_info[i].attached.id,
1537 p->phy_info[i].attached.phy_id, (unsigned long long)
1538 p->phy_info[i].attached.sas_address);
1539
1001 mptsas_set_starget(&p->phy_info[i], NULL); 1540 mptsas_set_starget(&p->phy_info[i], NULL);
1002 goto out;
1003 } 1541 }
1004 } 1542 }
1005 1543
1006 out: 1544 out:
1545 vtarget->starget = NULL;
1007 kfree(starget->hostdata); 1546 kfree(starget->hostdata);
1008 starget->hostdata = NULL; 1547 starget->hostdata = NULL;
1009} 1548}
@@ -2471,6 +3010,7 @@ mptsas_discovery_work(struct work_struct *work)
2471 kfree(ev); 3010 kfree(ev);
2472} 3011}
2473 3012
3013
2474static struct mptsas_phyinfo * 3014static struct mptsas_phyinfo *
2475mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address) 3015mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
2476{ 3016{
@@ -2495,30 +3035,6 @@ mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
2495 return phy_info; 3035 return phy_info;
2496} 3036}
2497 3037
2498static struct mptsas_phyinfo *
2499mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u8 channel, u8 id)
2500{
2501 struct mptsas_portinfo *port_info;
2502 struct mptsas_phyinfo *phy_info = NULL;
2503 int i;
2504
2505 mutex_lock(&ioc->sas_topology_mutex);
2506 list_for_each_entry(port_info, &ioc->sas_topology, list) {
2507 for (i = 0; i < port_info->num_phys; i++) {
2508 if (!mptsas_is_end_device(
2509 &port_info->phy_info[i].attached))
2510 continue;
2511 if (port_info->phy_info[i].attached.id != id)
2512 continue;
2513 if (port_info->phy_info[i].attached.channel != channel)
2514 continue;
2515 phy_info = &port_info->phy_info[i];
2516 break;
2517 }
2518 }
2519 mutex_unlock(&ioc->sas_topology_mutex);
2520 return phy_info;
2521}
2522 3038
2523static struct mptsas_phyinfo * 3039static struct mptsas_phyinfo *
2524mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 channel, u8 id) 3040mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
@@ -2547,17 +3063,6 @@ mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
2547 return phy_info; 3063 return phy_info;
2548} 3064}
2549 3065
2550/*
2551 * Work queue thread to clear the persitency table
2552 */
2553static void
2554mptsas_persist_clear_table(struct work_struct *work)
2555{
2556 MPT_ADAPTER *ioc = container_of(work, MPT_ADAPTER, sas_persist_task);
2557
2558 mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
2559}
2560
2561static void 3066static void
2562mptsas_reprobe_lun(struct scsi_device *sdev, void *data) 3067mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
2563{ 3068{
@@ -2583,7 +3088,8 @@ mptsas_adding_inactive_raid_components(MPT_ADAPTER *ioc, u8 channel, u8 id)
2583 pRaidVolumePage0_t buffer = NULL; 3088 pRaidVolumePage0_t buffer = NULL;
2584 RaidPhysDiskPage0_t phys_disk; 3089 RaidPhysDiskPage0_t phys_disk;
2585 int i; 3090 int i;
2586 struct mptsas_hotplug_event *ev; 3091 struct mptsas_phyinfo *phy_info;
3092 struct mptsas_devinfo sas_device;
2587 3093
2588 memset(&cfg, 0 , sizeof(CONFIGPARMS)); 3094 memset(&cfg, 0 , sizeof(CONFIGPARMS));
2589 memset(&hdr, 0 , sizeof(ConfigPageHeader_t)); 3095 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
@@ -2623,20 +3129,16 @@ mptsas_adding_inactive_raid_components(MPT_ADAPTER *ioc, u8 channel, u8 id)
2623 buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0) 3129 buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
2624 continue; 3130 continue;
2625 3131
2626 ev = kzalloc(sizeof(*ev), GFP_ATOMIC); 3132 if (mptsas_sas_device_pg0(ioc, &sas_device,
2627 if (!ev) { 3133 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
2628 printk(MYIOC_s_WARN_FMT "mptsas: lost hotplug event\n", ioc->name); 3134 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2629 goto out; 3135 (phys_disk.PhysDiskBus << 8) +
2630 } 3136 phys_disk.PhysDiskID))
3137 continue;
2631 3138
2632 INIT_WORK(&ev->work, mptsas_hotplug_work); 3139 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
2633 ev->ioc = ioc; 3140 sas_device.sas_address);
2634 ev->id = phys_disk.PhysDiskID; 3141 mptsas_add_end_device(ioc, phy_info);
2635 ev->channel = phys_disk.PhysDiskBus;
2636 ev->phys_disk_num_valid = 1;
2637 ev->phys_disk_num = phys_disk.PhysDiskNum;
2638 ev->event_type = MPTSAS_ADD_DEVICE;
2639 schedule_work(&ev->work);
2640 } 3142 }
2641 3143
2642 out: 3144 out:
@@ -2648,417 +3150,385 @@ mptsas_adding_inactive_raid_components(MPT_ADAPTER *ioc, u8 channel, u8 id)
2648 * Work queue thread to handle SAS hotplug events 3150 * Work queue thread to handle SAS hotplug events
2649 */ 3151 */
2650static void 3152static void
2651mptsas_hotplug_work(struct work_struct *work) 3153mptsas_hotplug_work(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,
3154 struct mptsas_hotplug_event *hot_plug_info)
2652{ 3155{
2653 struct mptsas_hotplug_event *ev =
2654 container_of(work, struct mptsas_hotplug_event, work);
2655
2656 MPT_ADAPTER *ioc = ev->ioc;
2657 struct mptsas_phyinfo *phy_info; 3156 struct mptsas_phyinfo *phy_info;
2658 struct sas_rphy *rphy;
2659 struct sas_port *port;
2660 struct scsi_device *sdev;
2661 struct scsi_target * starget; 3157 struct scsi_target * starget;
2662 struct sas_identify identify;
2663 char *ds = NULL;
2664 struct mptsas_devinfo sas_device; 3158 struct mptsas_devinfo sas_device;
2665 VirtTarget *vtarget; 3159 VirtTarget *vtarget;
2666 VirtDevice *vdevice; 3160 int i;
2667 3161
2668 mutex_lock(&ioc->sas_discovery_mutex); 3162 switch (hot_plug_info->event_type) {
2669 switch (ev->event_type) {
2670 case MPTSAS_DEL_DEVICE:
2671 3163
2672 phy_info = NULL; 3164 case MPTSAS_ADD_PHYSDISK:
2673 if (ev->phys_disk_num_valid) { 3165
2674 if (ev->hidden_raid_component){ 3166 if (!ioc->raid_data.pIocPg2)
2675 if (mptsas_sas_device_pg0(ioc, &sas_device, 3167 break;
2676 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID << 3168
2677 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), 3169 for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
2678 (ev->channel << 8) + ev->id)) { 3170 if (ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID ==
2679 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT 3171 hot_plug_info->id) {
2680 "%s: exit at line=%d\n", ioc->name, 3172 printk(MYIOC_s_WARN_FMT "firmware bug: unable "
2681 __func__, __LINE__)); 3173 "to add hidden disk - target_id matchs "
2682 break; 3174 "volume_id\n", ioc->name);
2683 } 3175 mptsas_free_fw_event(ioc, fw_event);
2684 phy_info = mptsas_find_phyinfo_by_sas_address( 3176 return;
2685 ioc, sas_device.sas_address); 3177 }
2686 }else
2687 phy_info = mptsas_find_phyinfo_by_phys_disk_num(
2688 ioc, ev->channel, ev->phys_disk_num);
2689 } 3178 }
3179 mpt_findImVolumes(ioc);
2690 3180
3181 case MPTSAS_ADD_DEVICE:
3182 memset(&sas_device, 0, sizeof(struct mptsas_devinfo));
3183 mptsas_sas_device_pg0(ioc, &sas_device,
3184 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
3185 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3186 (hot_plug_info->channel << 8) +
3187 hot_plug_info->id);
3188
3189 if (!sas_device.handle)
3190 return;
3191
3192 phy_info = mptsas_refreshing_device_handles(ioc, &sas_device);
2691 if (!phy_info) 3193 if (!phy_info)
2692 phy_info = mptsas_find_phyinfo_by_target(ioc, 3194 break;
2693 ev->channel, ev->id);
2694 3195
2695 /* 3196 if (mptsas_get_rphy(phy_info))
2696 * Sanity checks, for non-existing phys and remote rphys. 3197 break;
2697 */ 3198
2698 if (!phy_info){ 3199 mptsas_add_end_device(ioc, phy_info);
3200 break;
3201
3202 case MPTSAS_DEL_DEVICE:
3203 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
3204 hot_plug_info->sas_address);
3205 mptsas_del_end_device(ioc, phy_info);
3206 break;
3207
3208 case MPTSAS_DEL_PHYSDISK:
3209
3210 mpt_findImVolumes(ioc);
3211
3212 phy_info = mptsas_find_phyinfo_by_phys_disk_num(
3213 ioc, hot_plug_info->channel,
3214 hot_plug_info->phys_disk_num);
3215 mptsas_del_end_device(ioc, phy_info);
3216 break;
3217
3218 case MPTSAS_ADD_PHYSDISK_REPROBE:
3219
3220 if (mptsas_sas_device_pg0(ioc, &sas_device,
3221 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
3222 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3223 (hot_plug_info->channel << 8) + hot_plug_info->id)) {
2699 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT 3224 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
2700 "%s: exit at line=%d\n", ioc->name, 3225 "%s: fw_id=%d exit at line=%d\n", ioc->name,
2701 __func__, __LINE__)); 3226 __func__, hot_plug_info->id, __LINE__));
2702 break; 3227 break;
2703 } 3228 }
2704 if (!phy_info->port_details) { 3229
3230 phy_info = mptsas_find_phyinfo_by_sas_address(
3231 ioc, sas_device.sas_address);
3232
3233 if (!phy_info) {
2705 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT 3234 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
2706 "%s: exit at line=%d\n", ioc->name, 3235 "%s: fw_id=%d exit at line=%d\n", ioc->name,
2707 __func__, __LINE__)); 3236 __func__, hot_plug_info->id, __LINE__));
2708 break; 3237 break;
2709 } 3238 }
2710 rphy = mptsas_get_rphy(phy_info); 3239
2711 if (!rphy) { 3240 starget = mptsas_get_starget(phy_info);
3241 if (!starget) {
2712 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT 3242 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
2713 "%s: exit at line=%d\n", ioc->name, 3243 "%s: fw_id=%d exit at line=%d\n", ioc->name,
2714 __func__, __LINE__)); 3244 __func__, hot_plug_info->id, __LINE__));
2715 break; 3245 break;
2716 } 3246 }
2717 3247
2718 port = mptsas_get_port(phy_info); 3248 vtarget = starget->hostdata;
2719 if (!port) { 3249 if (!vtarget) {
2720 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT 3250 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
2721 "%s: exit at line=%d\n", ioc->name, 3251 "%s: fw_id=%d exit at line=%d\n", ioc->name,
2722 __func__, __LINE__)); 3252 __func__, hot_plug_info->id, __LINE__));
2723 break; 3253 break;
2724 } 3254 }
2725 3255
2726 starget = mptsas_get_starget(phy_info); 3256 mpt_findImVolumes(ioc);
2727 if (starget) {
2728 vtarget = starget->hostdata;
2729
2730 if (!vtarget) {
2731 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
2732 "%s: exit at line=%d\n", ioc->name,
2733 __func__, __LINE__));
2734 break;
2735 }
2736 3257
2737 /* 3258 starget_printk(KERN_INFO, starget, MYIOC_s_FMT "RAID Hidding: "
2738 * Handling RAID components 3259 "fw_channel=%d, fw_id=%d, physdsk %d, sas_addr 0x%llx\n",
2739 */ 3260 ioc->name, hot_plug_info->channel, hot_plug_info->id,
2740 if (ev->phys_disk_num_valid && 3261 hot_plug_info->phys_disk_num, (unsigned long long)
2741 ev->hidden_raid_component) { 3262 sas_device.sas_address);
2742 printk(MYIOC_s_INFO_FMT
2743 "RAID Hidding: channel=%d, id=%d, "
2744 "physdsk %d \n", ioc->name, ev->channel,
2745 ev->id, ev->phys_disk_num);
2746 vtarget->id = ev->phys_disk_num;
2747 vtarget->tflags |=
2748 MPT_TARGET_FLAGS_RAID_COMPONENT;
2749 mptsas_reprobe_target(starget, 1);
2750 phy_info->attached.phys_disk_num =
2751 ev->phys_disk_num;
2752 break;
2753 }
2754 }
2755 3263
2756 if (phy_info->attached.device_info & 3264 vtarget->id = hot_plug_info->phys_disk_num;
2757 MPI_SAS_DEVICE_INFO_SSP_TARGET) 3265 vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
2758 ds = "ssp"; 3266 phy_info->attached.phys_disk_num = hot_plug_info->phys_disk_num;
2759 if (phy_info->attached.device_info & 3267 mptsas_reprobe_target(starget, 1);
2760 MPI_SAS_DEVICE_INFO_STP_TARGET)
2761 ds = "stp";
2762 if (phy_info->attached.device_info &
2763 MPI_SAS_DEVICE_INFO_SATA_DEVICE)
2764 ds = "sata";
2765
2766 printk(MYIOC_s_INFO_FMT
2767 "removing %s device, channel %d, id %d, phy %d\n",
2768 ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
2769 dev_printk(KERN_DEBUG, &port->dev, MYIOC_s_FMT
2770 "delete port (%d)\n", ioc->name, port->port_identifier);
2771 sas_port_delete(port);
2772 mptsas_port_delete(ioc, phy_info->port_details);
2773 break; 3268 break;
2774 case MPTSAS_ADD_DEVICE:
2775 3269
2776 if (ev->phys_disk_num_valid) 3270 case MPTSAS_DEL_PHYSDISK_REPROBE:
2777 mpt_findImVolumes(ioc);
2778 3271
2779 /*
2780 * Refresh sas device pg0 data
2781 */
2782 if (mptsas_sas_device_pg0(ioc, &sas_device, 3272 if (mptsas_sas_device_pg0(ioc, &sas_device,
2783 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID << 3273 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
2784 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), 3274 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2785 (ev->channel << 8) + ev->id)) { 3275 (hot_plug_info->channel << 8) + hot_plug_info->id)) {
2786 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT 3276 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
2787 "%s: exit at line=%d\n", ioc->name, 3277 "%s: fw_id=%d exit at line=%d\n",
2788 __func__, __LINE__)); 3278 ioc->name, __func__,
3279 hot_plug_info->id, __LINE__));
2789 break; 3280 break;
2790 } 3281 }
2791 3282
2792 __mptsas_discovery_work(ioc);
2793
2794 phy_info = mptsas_find_phyinfo_by_sas_address(ioc, 3283 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
2795 sas_device.sas_address); 3284 sas_device.sas_address);
2796 3285 if (!phy_info) {
2797 if (!phy_info || !phy_info->port_details) {
2798 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT 3286 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
2799 "%s: exit at line=%d\n", ioc->name, 3287 "%s: fw_id=%d exit at line=%d\n", ioc->name,
2800 __func__, __LINE__)); 3288 __func__, hot_plug_info->id, __LINE__));
2801 break; 3289 break;
2802 } 3290 }
2803 3291
2804 starget = mptsas_get_starget(phy_info); 3292 starget = mptsas_get_starget(phy_info);
2805 if (starget && (!ev->hidden_raid_component)){ 3293 if (!starget) {
2806 3294 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
2807 vtarget = starget->hostdata; 3295 "%s: fw_id=%d exit at line=%d\n", ioc->name,
2808 3296 __func__, hot_plug_info->id, __LINE__));
2809 if (!vtarget) {
2810 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
2811 "%s: exit at line=%d\n", ioc->name,
2812 __func__, __LINE__));
2813 break;
2814 }
2815 /*
2816 * Handling RAID components
2817 */
2818 if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
2819 printk(MYIOC_s_INFO_FMT
2820 "RAID Exposing: channel=%d, id=%d, "
2821 "physdsk %d \n", ioc->name, ev->channel,
2822 ev->id, ev->phys_disk_num);
2823 vtarget->tflags &=
2824 ~MPT_TARGET_FLAGS_RAID_COMPONENT;
2825 vtarget->id = ev->id;
2826 mptsas_reprobe_target(starget, 0);
2827 phy_info->attached.phys_disk_num = ~0;
2828 }
2829 break; 3297 break;
2830 } 3298 }
2831 3299
2832 if (mptsas_get_rphy(phy_info)) { 3300 vtarget = starget->hostdata;
3301 if (!vtarget) {
2833 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT 3302 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
2834 "%s: exit at line=%d\n", ioc->name, 3303 "%s: fw_id=%d exit at line=%d\n", ioc->name,
2835 __func__, __LINE__)); 3304 __func__, hot_plug_info->id, __LINE__));
2836 if (ev->channel) printk("%d\n", __LINE__);
2837 break; 3305 break;
2838 } 3306 }
2839 3307
2840 port = mptsas_get_port(phy_info); 3308 if (!(vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)) {
2841 if (!port) {
2842 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT 3309 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
2843 "%s: exit at line=%d\n", ioc->name, 3310 "%s: fw_id=%d exit at line=%d\n", ioc->name,
2844 __func__, __LINE__)); 3311 __func__, hot_plug_info->id, __LINE__));
2845 break; 3312 break;
2846 } 3313 }
2847 memcpy(&phy_info->attached, &sas_device,
2848 sizeof(struct mptsas_devinfo));
2849
2850 if (phy_info->attached.device_info &
2851 MPI_SAS_DEVICE_INFO_SSP_TARGET)
2852 ds = "ssp";
2853 if (phy_info->attached.device_info &
2854 MPI_SAS_DEVICE_INFO_STP_TARGET)
2855 ds = "stp";
2856 if (phy_info->attached.device_info &
2857 MPI_SAS_DEVICE_INFO_SATA_DEVICE)
2858 ds = "sata";
2859
2860 printk(MYIOC_s_INFO_FMT
2861 "attaching %s device, channel %d, id %d, phy %d\n",
2862 ioc->name, ds, ev->channel, ev->id, ev->phy_id);
2863 3314
2864 mptsas_parse_device_info(&identify, &phy_info->attached); 3315 mpt_findImVolumes(ioc);
2865 rphy = sas_end_device_alloc(port);
2866 if (!rphy) {
2867 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
2868 "%s: exit at line=%d\n", ioc->name,
2869 __func__, __LINE__));
2870 break; /* non-fatal: an rphy can be added later */
2871 }
2872 3316
2873 rphy->identify = identify; 3317 starget_printk(KERN_INFO, starget, MYIOC_s_FMT "RAID Exposing:"
2874 if (sas_rphy_add(rphy)) { 3318 " fw_channel=%d, fw_id=%d, physdsk %d, sas_addr 0x%llx\n",
2875 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT 3319 ioc->name, hot_plug_info->channel, hot_plug_info->id,
2876 "%s: exit at line=%d\n", ioc->name, 3320 hot_plug_info->phys_disk_num, (unsigned long long)
2877 __func__, __LINE__)); 3321 sas_device.sas_address);
2878 sas_rphy_free(rphy); 3322
2879 break; 3323 vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT;
2880 } 3324 vtarget->id = hot_plug_info->id;
2881 mptsas_set_rphy(ioc, phy_info, rphy); 3325 phy_info->attached.phys_disk_num = ~0;
3326 mptsas_reprobe_target(starget, 0);
3327 mptsas_add_device_component_by_fw(ioc,
3328 hot_plug_info->channel, hot_plug_info->id);
2882 break; 3329 break;
3330
2883 case MPTSAS_ADD_RAID: 3331 case MPTSAS_ADD_RAID:
2884 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL, 3332
2885 ev->id, 0);
2886 if (sdev) {
2887 scsi_device_put(sdev);
2888 break;
2889 }
2890 printk(MYIOC_s_INFO_FMT
2891 "attaching raid volume, channel %d, id %d\n",
2892 ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
2893 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL, ev->id, 0);
2894 mpt_findImVolumes(ioc); 3333 mpt_findImVolumes(ioc);
3334 printk(MYIOC_s_INFO_FMT "attaching raid volume, channel %d, "
3335 "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL,
3336 hot_plug_info->id);
3337 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
3338 hot_plug_info->id, 0);
2895 break; 3339 break;
3340
2896 case MPTSAS_DEL_RAID: 3341 case MPTSAS_DEL_RAID:
2897 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL, 3342
2898 ev->id, 0);
2899 if (!sdev)
2900 break;
2901 printk(MYIOC_s_INFO_FMT
2902 "removing raid volume, channel %d, id %d\n",
2903 ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
2904 vdevice = sdev->hostdata;
2905 scsi_remove_device(sdev);
2906 scsi_device_put(sdev);
2907 mpt_findImVolumes(ioc); 3343 mpt_findImVolumes(ioc);
3344 printk(MYIOC_s_INFO_FMT "removing raid volume, channel %d, "
3345 "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL,
3346 hot_plug_info->id);
3347 scsi_remove_device(hot_plug_info->sdev);
3348 scsi_device_put(hot_plug_info->sdev);
2908 break; 3349 break;
3350
2909 case MPTSAS_ADD_INACTIVE_VOLUME: 3351 case MPTSAS_ADD_INACTIVE_VOLUME:
3352
3353 mpt_findImVolumes(ioc);
2910 mptsas_adding_inactive_raid_components(ioc, 3354 mptsas_adding_inactive_raid_components(ioc,
2911 ev->channel, ev->id); 3355 hot_plug_info->channel, hot_plug_info->id);
2912 break; 3356 break;
2913 case MPTSAS_IGNORE_EVENT: 3357
2914 default: 3358 default:
2915 break; 3359 break;
2916 } 3360 }
2917 3361
2918 mutex_unlock(&ioc->sas_discovery_mutex); 3362 mptsas_free_fw_event(ioc, fw_event);
2919 kfree(ev);
2920} 3363}
2921 3364
2922static void 3365static void
2923mptsas_send_sas_event(MPT_ADAPTER *ioc, 3366mptsas_send_sas_event(struct fw_event_work *fw_event)
2924 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
2925{ 3367{
2926 struct mptsas_hotplug_event *ev; 3368 MPT_ADAPTER *ioc;
2927 u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo); 3369 struct mptsas_hotplug_event hot_plug_info;
2928 __le64 sas_address; 3370 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data;
3371 u32 device_info;
3372 u64 sas_address;
3373
3374 ioc = fw_event->ioc;
3375 sas_event_data = (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)
3376 fw_event->event_data;
3377 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
2929 3378
2930 if ((device_info & 3379 if ((device_info &
2931 (MPI_SAS_DEVICE_INFO_SSP_TARGET | 3380 (MPI_SAS_DEVICE_INFO_SSP_TARGET |
2932 MPI_SAS_DEVICE_INFO_STP_TARGET | 3381 MPI_SAS_DEVICE_INFO_STP_TARGET |
2933 MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0) 3382 MPI_SAS_DEVICE_INFO_SATA_DEVICE)) == 0) {
3383 mptsas_free_fw_event(ioc, fw_event);
3384 return;
3385 }
3386
3387 if (sas_event_data->ReasonCode ==
3388 MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED) {
3389 mptbase_sas_persist_operation(ioc,
3390 MPI_SAS_OP_CLEAR_NOT_PRESENT);
3391 mptsas_free_fw_event(ioc, fw_event);
2934 return; 3392 return;
3393 }
2935 3394
2936 switch (sas_event_data->ReasonCode) { 3395 switch (sas_event_data->ReasonCode) {
2937 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING: 3396 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
2938
2939 mptsas_target_reset_queue(ioc, sas_event_data);
2940 break;
2941
2942 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED: 3397 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
2943 ev = kzalloc(sizeof(*ev), GFP_ATOMIC); 3398 memset(&hot_plug_info, 0, sizeof(struct mptsas_hotplug_event));
2944 if (!ev) { 3399 hot_plug_info.handle = le16_to_cpu(sas_event_data->DevHandle);
2945 printk(MYIOC_s_WARN_FMT "lost hotplug event\n", ioc->name); 3400 hot_plug_info.channel = sas_event_data->Bus;
2946 break; 3401 hot_plug_info.id = sas_event_data->TargetID;
2947 } 3402 hot_plug_info.phy_id = sas_event_data->PhyNum;
2948
2949 INIT_WORK(&ev->work, mptsas_hotplug_work);
2950 ev->ioc = ioc;
2951 ev->handle = le16_to_cpu(sas_event_data->DevHandle);
2952 ev->parent_handle =
2953 le16_to_cpu(sas_event_data->ParentDevHandle);
2954 ev->channel = sas_event_data->Bus;
2955 ev->id = sas_event_data->TargetID;
2956 ev->phy_id = sas_event_data->PhyNum;
2957 memcpy(&sas_address, &sas_event_data->SASAddress, 3403 memcpy(&sas_address, &sas_event_data->SASAddress,
2958 sizeof(__le64)); 3404 sizeof(u64));
2959 ev->sas_address = le64_to_cpu(sas_address); 3405 hot_plug_info.sas_address = le64_to_cpu(sas_address);
2960 ev->device_info = device_info; 3406 hot_plug_info.device_info = device_info;
2961
2962 if (sas_event_data->ReasonCode & 3407 if (sas_event_data->ReasonCode &
2963 MPI_EVENT_SAS_DEV_STAT_RC_ADDED) 3408 MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
2964 ev->event_type = MPTSAS_ADD_DEVICE; 3409 hot_plug_info.event_type = MPTSAS_ADD_DEVICE;
2965 else 3410 else
2966 ev->event_type = MPTSAS_DEL_DEVICE; 3411 hot_plug_info.event_type = MPTSAS_DEL_DEVICE;
2967 schedule_work(&ev->work); 3412 mptsas_hotplug_work(ioc, fw_event, &hot_plug_info);
2968 break; 3413 break;
3414
2969 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED: 3415 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
2970 /* 3416 mptbase_sas_persist_operation(ioc,
2971 * Persistent table is full. 3417 MPI_SAS_OP_CLEAR_NOT_PRESENT);
2972 */ 3418 mptsas_free_fw_event(ioc, fw_event);
2973 INIT_WORK(&ioc->sas_persist_task,
2974 mptsas_persist_clear_table);
2975 schedule_work(&ioc->sas_persist_task);
2976 break; 3419 break;
2977 /* 3420
2978 * TODO, handle other events
2979 */
2980 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA: 3421 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
2981 case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED: 3422 /* TODO */
2982 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET: 3423 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
2983 case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL: 3424 /* TODO */
2984 case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
2985 case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
2986 case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
2987 default: 3425 default:
3426 mptsas_free_fw_event(ioc, fw_event);
2988 break; 3427 break;
2989 } 3428 }
2990} 3429}
3430
2991static void 3431static void
2992mptsas_send_raid_event(MPT_ADAPTER *ioc, 3432mptsas_send_raid_event(struct fw_event_work *fw_event)
2993 EVENT_DATA_RAID *raid_event_data)
2994{ 3433{
2995 struct mptsas_hotplug_event *ev; 3434 MPT_ADAPTER *ioc;
2996 int status = le32_to_cpu(raid_event_data->SettingsStatus); 3435 EVENT_DATA_RAID *raid_event_data;
2997 int state = (status >> 8) & 0xff; 3436 struct mptsas_hotplug_event hot_plug_info;
2998 3437 int status;
2999 if (ioc->bus_type != SAS) 3438 int state;
3000 return; 3439 struct scsi_device *sdev = NULL;
3001 3440 VirtDevice *vdevice = NULL;
3002 ev = kzalloc(sizeof(*ev), GFP_ATOMIC); 3441 RaidPhysDiskPage0_t phys_disk;
3003 if (!ev) { 3442
3004 printk(MYIOC_s_WARN_FMT "lost hotplug event\n", ioc->name); 3443 ioc = fw_event->ioc;
3005 return; 3444 raid_event_data = (EVENT_DATA_RAID *)fw_event->event_data;
3445 status = le32_to_cpu(raid_event_data->SettingsStatus);
3446 state = (status >> 8) & 0xff;
3447
3448 memset(&hot_plug_info, 0, sizeof(struct mptsas_hotplug_event));
3449 hot_plug_info.id = raid_event_data->VolumeID;
3450 hot_plug_info.channel = raid_event_data->VolumeBus;
3451 hot_plug_info.phys_disk_num = raid_event_data->PhysDiskNum;
3452
3453 if (raid_event_data->ReasonCode == MPI_EVENT_RAID_RC_VOLUME_DELETED ||
3454 raid_event_data->ReasonCode == MPI_EVENT_RAID_RC_VOLUME_CREATED ||
3455 raid_event_data->ReasonCode ==
3456 MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED) {
3457 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
3458 hot_plug_info.id, 0);
3459 hot_plug_info.sdev = sdev;
3460 if (sdev)
3461 vdevice = sdev->hostdata;
3006 } 3462 }
3007 3463
3008 INIT_WORK(&ev->work, mptsas_hotplug_work); 3464 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Entering %s: "
3009 ev->ioc = ioc; 3465 "ReasonCode=%02x\n", ioc->name, __func__,
3010 ev->id = raid_event_data->VolumeID; 3466 raid_event_data->ReasonCode));
3011 ev->channel = raid_event_data->VolumeBus;
3012 ev->event_type = MPTSAS_IGNORE_EVENT;
3013 3467
3014 switch (raid_event_data->ReasonCode) { 3468 switch (raid_event_data->ReasonCode) {
3015 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED: 3469 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
3016 ev->phys_disk_num_valid = 1; 3470 hot_plug_info.event_type = MPTSAS_DEL_PHYSDISK_REPROBE;
3017 ev->phys_disk_num = raid_event_data->PhysDiskNum;
3018 ev->event_type = MPTSAS_ADD_DEVICE;
3019 break; 3471 break;
3020 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED: 3472 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
3021 ev->phys_disk_num_valid = 1; 3473 hot_plug_info.event_type = MPTSAS_ADD_PHYSDISK_REPROBE;
3022 ev->phys_disk_num = raid_event_data->PhysDiskNum;
3023 ev->hidden_raid_component = 1;
3024 ev->event_type = MPTSAS_DEL_DEVICE;
3025 break; 3474 break;
3026 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED: 3475 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
3027 switch (state) { 3476 switch (state) {
3028 case MPI_PD_STATE_ONLINE: 3477 case MPI_PD_STATE_ONLINE:
3029 case MPI_PD_STATE_NOT_COMPATIBLE: 3478 case MPI_PD_STATE_NOT_COMPATIBLE:
3030 ev->phys_disk_num_valid = 1; 3479 mpt_raid_phys_disk_pg0(ioc,
3031 ev->phys_disk_num = raid_event_data->PhysDiskNum; 3480 raid_event_data->PhysDiskNum, &phys_disk);
3032 ev->hidden_raid_component = 1; 3481 hot_plug_info.id = phys_disk.PhysDiskID;
3033 ev->event_type = MPTSAS_ADD_DEVICE; 3482 hot_plug_info.channel = phys_disk.PhysDiskBus;
3483 hot_plug_info.event_type = MPTSAS_ADD_PHYSDISK;
3034 break; 3484 break;
3485 case MPI_PD_STATE_FAILED:
3035 case MPI_PD_STATE_MISSING: 3486 case MPI_PD_STATE_MISSING:
3036 case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST: 3487 case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST:
3037 case MPI_PD_STATE_FAILED_AT_HOST_REQUEST: 3488 case MPI_PD_STATE_FAILED_AT_HOST_REQUEST:
3038 case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON: 3489 case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON:
3039 ev->phys_disk_num_valid = 1; 3490 hot_plug_info.event_type = MPTSAS_DEL_PHYSDISK;
3040 ev->phys_disk_num = raid_event_data->PhysDiskNum;
3041 ev->event_type = MPTSAS_DEL_DEVICE;
3042 break; 3491 break;
3043 default: 3492 default:
3044 break; 3493 break;
3045 } 3494 }
3046 break; 3495 break;
3047 case MPI_EVENT_RAID_RC_VOLUME_DELETED: 3496 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
3048 ev->event_type = MPTSAS_DEL_RAID; 3497 if (!sdev)
3498 break;
3499 vdevice->vtarget->deleted = 1; /* block IO */
3500 hot_plug_info.event_type = MPTSAS_DEL_RAID;
3049 break; 3501 break;
3050 case MPI_EVENT_RAID_RC_VOLUME_CREATED: 3502 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
3051 ev->event_type = MPTSAS_ADD_RAID; 3503 if (sdev) {
3504 scsi_device_put(sdev);
3505 break;
3506 }
3507 hot_plug_info.event_type = MPTSAS_ADD_RAID;
3052 break; 3508 break;
3053 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED: 3509 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
3510 if (!(status & MPI_RAIDVOL0_STATUS_FLAG_ENABLED)) {
3511 if (!sdev)
3512 break;
3513 vdevice->vtarget->deleted = 1; /* block IO */
3514 hot_plug_info.event_type = MPTSAS_DEL_RAID;
3515 break;
3516 }
3054 switch (state) { 3517 switch (state) {
3055 case MPI_RAIDVOL0_STATUS_STATE_FAILED: 3518 case MPI_RAIDVOL0_STATUS_STATE_FAILED:
3056 case MPI_RAIDVOL0_STATUS_STATE_MISSING: 3519 case MPI_RAIDVOL0_STATUS_STATE_MISSING:
3057 ev->event_type = MPTSAS_DEL_RAID; 3520 if (!sdev)
3521 break;
3522 vdevice->vtarget->deleted = 1; /* block IO */
3523 hot_plug_info.event_type = MPTSAS_DEL_RAID;
3058 break; 3524 break;
3059 case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL: 3525 case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
3060 case MPI_RAIDVOL0_STATUS_STATE_DEGRADED: 3526 case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
3061 ev->event_type = MPTSAS_ADD_RAID; 3527 if (sdev) {
3528 scsi_device_put(sdev);
3529 break;
3530 }
3531 hot_plug_info.event_type = MPTSAS_ADD_RAID;
3062 break; 3532 break;
3063 default: 3533 default:
3064 break; 3534 break;
@@ -3067,7 +3537,11 @@ mptsas_send_raid_event(MPT_ADAPTER *ioc,
3067 default: 3537 default:
3068 break; 3538 break;
3069 } 3539 }
3070 schedule_work(&ev->work); 3540
3541 if (hot_plug_info.event_type != MPTSAS_IGNORE_EVENT)
3542 mptsas_hotplug_work(ioc, fw_event, &hot_plug_info);
3543 else
3544 mptsas_free_fw_event(ioc, fw_event);
3071} 3545}
3072 3546
3073static void 3547static void
@@ -3106,76 +3580,88 @@ mptsas_send_discovery_event(MPT_ADAPTER *ioc,
3106 * 3580 *
3107 */ 3581 */
3108static void 3582static void
3109mptsas_send_ir2_event(MPT_ADAPTER *ioc, PTR_MPI_EVENT_DATA_IR2 ir2_data) 3583mptsas_send_ir2_event(struct fw_event_work *fw_event)
3110{ 3584{
3111 struct mptsas_hotplug_event *ev; 3585 MPT_ADAPTER *ioc;
3112 3586 struct mptsas_hotplug_event hot_plug_info;
3113 if (ir2_data->ReasonCode != 3587 MPI_EVENT_DATA_IR2 *ir2_data;
3114 MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED) 3588 u8 reasonCode;
3115 return; 3589
3116 3590 ioc = fw_event->ioc;
3117 ev = kzalloc(sizeof(*ev), GFP_ATOMIC); 3591 ir2_data = (MPI_EVENT_DATA_IR2 *)fw_event->event_data;
3118 if (!ev) 3592 reasonCode = ir2_data->ReasonCode;
3593
3594 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Entering %s: "
3595 "ReasonCode=%02x\n", ioc->name, __func__, reasonCode));
3596
3597 memset(&hot_plug_info, 0, sizeof(struct mptsas_hotplug_event));
3598 hot_plug_info.id = ir2_data->TargetID;
3599 hot_plug_info.channel = ir2_data->Bus;
3600 switch (reasonCode) {
3601 case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED:
3602 hot_plug_info.event_type = MPTSAS_ADD_INACTIVE_VOLUME;
3603 break;
3604 default:
3605 mptsas_free_fw_event(ioc, fw_event);
3119 return; 3606 return;
3120 3607 }
3121 INIT_WORK(&ev->work, mptsas_hotplug_work); 3608 mptsas_hotplug_work(ioc, fw_event, &hot_plug_info);
3122 ev->ioc = ioc; 3609}
3123 ev->id = ir2_data->TargetID;
3124 ev->channel = ir2_data->Bus;
3125 ev->event_type = MPTSAS_ADD_INACTIVE_VOLUME;
3126
3127 schedule_work(&ev->work);
3128};
3129 3610
3130static int 3611static int
3131mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) 3612mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
3132{ 3613{
3133 int rc=1; 3614 u32 event = le32_to_cpu(reply->Event);
3134 u8 event = le32_to_cpu(reply->Event) & 0xFF; 3615 int sz, event_data_sz;
3135 3616 struct fw_event_work *fw_event;
3136 if (!ioc->sh) 3617 unsigned long delay;
3137 goto out;
3138 3618
3139 /* 3619 /* events turned off due to host reset or driver unloading */
3140 * sas_discovery_ignore_events 3620 if (ioc->fw_events_off)
3141 * 3621 return 0;
3142 * This flag is to prevent anymore processing of
3143 * sas events once mptsas_remove function is called.
3144 */
3145 if (ioc->sas_discovery_ignore_events) {
3146 rc = mptscsih_event_process(ioc, reply);
3147 goto out;
3148 }
3149 3622
3623 delay = msecs_to_jiffies(1);
3150 switch (event) { 3624 switch (event) {
3151 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE: 3625 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
3152 mptsas_send_sas_event(ioc, 3626 {
3153 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data); 3627 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data =
3154 break; 3628 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data;
3155 case MPI_EVENT_INTEGRATED_RAID: 3629
3156 mptsas_send_raid_event(ioc, 3630 if (sas_event_data->ReasonCode ==
3157 (EVENT_DATA_RAID *)reply->Data); 3631 MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING) {
3158 break; 3632 mptsas_target_reset_queue(ioc, sas_event_data);
3159 case MPI_EVENT_PERSISTENT_TABLE_FULL: 3633 return 0;
3160 INIT_WORK(&ioc->sas_persist_task, 3634 }
3161 mptsas_persist_clear_table);
3162 schedule_work(&ioc->sas_persist_task);
3163 break; 3635 break;
3164 case MPI_EVENT_SAS_DISCOVERY: 3636 }
3637 case MPI_EVENT_SAS_DISCOVERY:
3165 mptsas_send_discovery_event(ioc, 3638 mptsas_send_discovery_event(ioc,
3166 (EVENT_DATA_SAS_DISCOVERY *)reply->Data); 3639 (EVENT_DATA_SAS_DISCOVERY *)reply->Data);
3167 break; 3640 break;
3641 case MPI_EVENT_INTEGRATED_RAID:
3642 case MPI_EVENT_PERSISTENT_TABLE_FULL:
3168 case MPI_EVENT_IR2: 3643 case MPI_EVENT_IR2:
3169 mptsas_send_ir2_event(ioc, 3644 case MPI_EVENT_SAS_PHY_LINK_STATUS:
3170 (PTR_MPI_EVENT_DATA_IR2)reply->Data); 3645 case MPI_EVENT_QUEUE_FULL:
3171 break; 3646 break;
3172 default: 3647 default:
3173 rc = mptscsih_event_process(ioc, reply); 3648 return 0;
3174 break;
3175 } 3649 }
3176 out:
3177 3650
3178 return rc; 3651 event_data_sz = ((reply->MsgLength * 4) -
3652 offsetof(EventNotificationReply_t, Data));
3653 sz = offsetof(struct fw_event_work, event_data) + event_data_sz;
3654 fw_event = kzalloc(sz, GFP_ATOMIC);
3655 if (!fw_event) {
3656 printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n", ioc->name,
3657 __func__, __LINE__);
3658 return 0;
3659 }
3660 memcpy(fw_event->event_data, reply->Data, event_data_sz);
3661 fw_event->event = event;
3662 fw_event->ioc = ioc;
3663 mptsas_add_fw_event(ioc, fw_event, delay);
3664 return 0;
3179} 3665}
3180 3666
3181static int 3667static int
@@ -3197,6 +3683,7 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
3197 return r; 3683 return r;
3198 3684
3199 ioc = pci_get_drvdata(pdev); 3685 ioc = pci_get_drvdata(pdev);
3686 mptsas_fw_event_off(ioc);
3200 ioc->DoneCtx = mptsasDoneCtx; 3687 ioc->DoneCtx = mptsasDoneCtx;
3201 ioc->TaskCtx = mptsasTaskCtx; 3688 ioc->TaskCtx = mptsasTaskCtx;
3202 ioc->InternalCtx = mptsasInternalCtx; 3689 ioc->InternalCtx = mptsasInternalCtx;
@@ -3339,6 +3826,9 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
3339 3826
3340 hd->last_queue_full = 0; 3827 hd->last_queue_full = 0;
3341 INIT_LIST_HEAD(&hd->target_reset_list); 3828 INIT_LIST_HEAD(&hd->target_reset_list);
3829 INIT_LIST_HEAD(&ioc->sas_device_info_list);
3830 mutex_init(&ioc->sas_device_info_mutex);
3831
3342 spin_unlock_irqrestore(&ioc->FreeQlock, flags); 3832 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3343 3833
3344 if (ioc->sas_data.ptClear==1) { 3834 if (ioc->sas_data.ptClear==1) {
@@ -3354,7 +3844,7 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
3354 } 3844 }
3355 3845
3356 mptsas_scan_sas_topology(ioc); 3846 mptsas_scan_sas_topology(ioc);
3357 3847 mptsas_fw_event_on(ioc);
3358 return 0; 3848 return 0;
3359 3849
3360 out_mptsas_probe: 3850 out_mptsas_probe:
@@ -3368,7 +3858,8 @@ mptsas_shutdown(struct pci_dev *pdev)
3368{ 3858{
3369 MPT_ADAPTER *ioc = pci_get_drvdata(pdev); 3859 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
3370 3860
3371 ioc->sas_discovery_quiesce_io = 0; 3861 mptsas_fw_event_off(ioc);
3862 mptsas_cleanup_fw_event_q(ioc);
3372} 3863}
3373 3864
3374static void __devexit mptsas_remove(struct pci_dev *pdev) 3865static void __devexit mptsas_remove(struct pci_dev *pdev)
@@ -3379,6 +3870,8 @@ static void __devexit mptsas_remove(struct pci_dev *pdev)
3379 3870
3380 mptsas_shutdown(pdev); 3871 mptsas_shutdown(pdev);
3381 3872
3873 mptsas_del_device_components(ioc);
3874
3382 ioc->sas_discovery_ignore_events = 1; 3875 ioc->sas_discovery_ignore_events = 1;
3383 sas_remove_host(ioc->sh); 3876 sas_remove_host(ioc->sh);
3384 3877
@@ -3387,6 +3880,7 @@ static void __devexit mptsas_remove(struct pci_dev *pdev)
3387 list_del(&p->list); 3880 list_del(&p->list);
3388 for (i = 0 ; i < p->num_phys ; i++) 3881 for (i = 0 ; i < p->num_phys ; i++)
3389 mptsas_port_delete(ioc, p->phy_info[i].port_details); 3882 mptsas_port_delete(ioc, p->phy_info[i].port_details);
3883
3390 kfree(p->phy_info); 3884 kfree(p->phy_info);
3391 kfree(p); 3885 kfree(p);
3392 } 3886 }
diff --git a/drivers/message/fusion/mptsas.h b/drivers/message/fusion/mptsas.h
index bf528a5b59b..9e0885a86d2 100644
--- a/drivers/message/fusion/mptsas.h
+++ b/drivers/message/fusion/mptsas.h
@@ -61,12 +61,30 @@ enum mptsas_hotplug_action {
61 MPTSAS_DEL_DEVICE, 61 MPTSAS_DEL_DEVICE,
62 MPTSAS_ADD_RAID, 62 MPTSAS_ADD_RAID,
63 MPTSAS_DEL_RAID, 63 MPTSAS_DEL_RAID,
64 MPTSAS_ADD_PHYSDISK,
65 MPTSAS_ADD_PHYSDISK_REPROBE,
66 MPTSAS_DEL_PHYSDISK,
67 MPTSAS_DEL_PHYSDISK_REPROBE,
64 MPTSAS_ADD_INACTIVE_VOLUME, 68 MPTSAS_ADD_INACTIVE_VOLUME,
65 MPTSAS_IGNORE_EVENT, 69 MPTSAS_IGNORE_EVENT,
66}; 70};
67 71
72struct mptsas_mapping{
73 u8 id;
74 u8 channel;
75};
76
77struct mptsas_device_info {
78 struct list_head list;
79 struct mptsas_mapping os; /* operating system mapping*/
80 struct mptsas_mapping fw; /* firmware mapping */
81 u64 sas_address;
82 u32 device_info; /* specific bits for devices */
83 u16 slot; /* enclosure slot id */
84 u64 enclosure_logical_id; /*enclosure address */
85};
86
68struct mptsas_hotplug_event { 87struct mptsas_hotplug_event {
69 struct work_struct work;
70 MPT_ADAPTER *ioc; 88 MPT_ADAPTER *ioc;
71 enum mptsas_hotplug_action event_type; 89 enum mptsas_hotplug_action event_type;
72 u64 sas_address; 90 u64 sas_address;
@@ -74,11 +92,18 @@ struct mptsas_hotplug_event {
74 u8 id; 92 u8 id;
75 u32 device_info; 93 u32 device_info;
76 u16 handle; 94 u16 handle;
77 u16 parent_handle;
78 u8 phy_id; 95 u8 phy_id;
79 u8 phys_disk_num_valid; /* hrc (hidden raid component) */
80 u8 phys_disk_num; /* hrc - unique index*/ 96 u8 phys_disk_num; /* hrc - unique index*/
81 u8 hidden_raid_component; /* hrc - don't expose*/ 97 struct scsi_device *sdev;
98};
99
100struct fw_event_work {
101 struct list_head list;
102 struct delayed_work work;
103 MPT_ADAPTER *ioc;
104 u32 event;
105 u8 retries;
106 u8 event_data[1];
82}; 107};
83 108
84struct mptsas_discovery_event { 109struct mptsas_discovery_event {