diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-03-08 11:49:24 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-03-08 11:49:24 -0500 |
commit | 9446389ef612096704fdf18fa79bab423d4110f0 (patch) | |
tree | 3e4fda7270be58ae176d20d318e61fb115b325b5 /drivers/scsi/libsas | |
parent | cdd0972945dbcb8ea24db365d9b0e100af2a27bb (diff) | |
parent | 84c6f6046c5a2189160a8f0dca8b90427bf690ea (diff) |
Merge commit 'origin' into devel
Diffstat (limited to 'drivers/scsi/libsas')
-rw-r--r-- | drivers/scsi/libsas/sas_ata.c | 39 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_port.c | 11 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_scsi_host.c | 34 |
3 files changed, 23 insertions, 61 deletions
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 7cd05b599a12..b0e5ac372a32 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c | |||
@@ -236,12 +236,12 @@ static void sas_ata_phy_reset(struct ata_port *ap) | |||
236 | struct domain_device *dev = ap->private_data; | 236 | struct domain_device *dev = ap->private_data; |
237 | struct sas_internal *i = | 237 | struct sas_internal *i = |
238 | to_sas_internal(dev->port->ha->core.shost->transportt); | 238 | to_sas_internal(dev->port->ha->core.shost->transportt); |
239 | int res = 0; | 239 | int res = TMF_RESP_FUNC_FAILED; |
240 | 240 | ||
241 | if (i->dft->lldd_I_T_nexus_reset) | 241 | if (i->dft->lldd_I_T_nexus_reset) |
242 | res = i->dft->lldd_I_T_nexus_reset(dev); | 242 | res = i->dft->lldd_I_T_nexus_reset(dev); |
243 | 243 | ||
244 | if (res) | 244 | if (res != TMF_RESP_FUNC_COMPLETE) |
245 | SAS_DPRINTK("%s: Unable to reset I T nexus?\n", __FUNCTION__); | 245 | SAS_DPRINTK("%s: Unable to reset I T nexus?\n", __FUNCTION__); |
246 | 246 | ||
247 | switch (dev->sata_dev.command_set) { | 247 | switch (dev->sata_dev.command_set) { |
@@ -656,21 +656,6 @@ out: | |||
656 | return res; | 656 | return res; |
657 | } | 657 | } |
658 | 658 | ||
659 | static void sas_sata_propagate_sas_addr(struct domain_device *dev) | ||
660 | { | ||
661 | unsigned long flags; | ||
662 | struct asd_sas_port *port = dev->port; | ||
663 | struct asd_sas_phy *phy; | ||
664 | |||
665 | BUG_ON(dev->parent); | ||
666 | |||
667 | memcpy(port->attached_sas_addr, dev->sas_addr, SAS_ADDR_SIZE); | ||
668 | spin_lock_irqsave(&port->phy_list_lock, flags); | ||
669 | list_for_each_entry(phy, &port->phy_list, port_phy_el) | ||
670 | memcpy(phy->attached_sas_addr, dev->sas_addr, SAS_ADDR_SIZE); | ||
671 | spin_unlock_irqrestore(&port->phy_list_lock, flags); | ||
672 | } | ||
673 | |||
674 | #define ATA_IDENTIFY_DEV 0xEC | 659 | #define ATA_IDENTIFY_DEV 0xEC |
675 | #define ATA_IDENTIFY_PACKET_DEV 0xA1 | 660 | #define ATA_IDENTIFY_PACKET_DEV 0xA1 |
676 | #define ATA_SET_FEATURES 0xEF | 661 | #define ATA_SET_FEATURES 0xEF |
@@ -728,26 +713,6 @@ static int sas_discover_sata_dev(struct domain_device *dev) | |||
728 | goto out_err; | 713 | goto out_err; |
729 | } | 714 | } |
730 | cont1: | 715 | cont1: |
731 | /* Get WWN */ | ||
732 | if (dev->port->oob_mode != SATA_OOB_MODE) { | ||
733 | memcpy(dev->sas_addr, dev->sata_dev.rps_resp.rps.stp_sas_addr, | ||
734 | SAS_ADDR_SIZE); | ||
735 | } else if (dev->sata_dev.command_set == ATA_COMMAND_SET && | ||
736 | (le16_to_cpu(dev->sata_dev.identify_device[108]) & 0xF000) | ||
737 | == 0x5000) { | ||
738 | int i; | ||
739 | |||
740 | for (i = 0; i < 4; i++) { | ||
741 | dev->sas_addr[2*i] = | ||
742 | (le16_to_cpu(dev->sata_dev.identify_device[108+i]) & 0xFF00) >> 8; | ||
743 | dev->sas_addr[2*i+1] = | ||
744 | le16_to_cpu(dev->sata_dev.identify_device[108+i]) & 0x00FF; | ||
745 | } | ||
746 | } | ||
747 | sas_hash_addr(dev->hashed_sas_addr, dev->sas_addr); | ||
748 | if (!dev->parent) | ||
749 | sas_sata_propagate_sas_addr(dev); | ||
750 | |||
751 | /* XXX Hint: register this SATA device with SATL. | 716 | /* XXX Hint: register this SATA device with SATL. |
752 | When this returns, dev->sata_dev->lu is alive and | 717 | When this returns, dev->sata_dev->lu is alive and |
753 | present. | 718 | present. |
diff --git a/drivers/scsi/libsas/sas_port.c b/drivers/scsi/libsas/sas_port.c index e1e2d085c920..39ae68a3b0ef 100644 --- a/drivers/scsi/libsas/sas_port.c +++ b/drivers/scsi/libsas/sas_port.c | |||
@@ -92,9 +92,6 @@ static void sas_form_port(struct asd_sas_phy *phy) | |||
92 | if (!port->phy) | 92 | if (!port->phy) |
93 | port->phy = phy->phy; | 93 | port->phy = phy->phy; |
94 | 94 | ||
95 | SAS_DPRINTK("phy%d added to port%d, phy_mask:0x%x\n", phy->id, | ||
96 | port->id, port->phy_mask); | ||
97 | |||
98 | if (*(u64 *)port->attached_sas_addr == 0) { | 95 | if (*(u64 *)port->attached_sas_addr == 0) { |
99 | port->class = phy->class; | 96 | port->class = phy->class; |
100 | memcpy(port->attached_sas_addr, phy->attached_sas_addr, | 97 | memcpy(port->attached_sas_addr, phy->attached_sas_addr, |
@@ -115,6 +112,11 @@ static void sas_form_port(struct asd_sas_phy *phy) | |||
115 | } | 112 | } |
116 | sas_port_add_phy(port->port, phy->phy); | 113 | sas_port_add_phy(port->port, phy->phy); |
117 | 114 | ||
115 | SAS_DPRINTK("%s added to %s, phy_mask:0x%x (%16llx)\n", | ||
116 | phy->phy->dev.bus_id,port->port->dev.bus_id, | ||
117 | port->phy_mask, | ||
118 | SAS_ADDR(port->attached_sas_addr)); | ||
119 | |||
118 | if (port->port_dev) | 120 | if (port->port_dev) |
119 | port->port_dev->pathways = port->num_phys; | 121 | port->port_dev->pathways = port->num_phys; |
120 | 122 | ||
@@ -255,12 +257,11 @@ void sas_porte_hard_reset(struct work_struct *work) | |||
255 | static void sas_init_port(struct asd_sas_port *port, | 257 | static void sas_init_port(struct asd_sas_port *port, |
256 | struct sas_ha_struct *sas_ha, int i) | 258 | struct sas_ha_struct *sas_ha, int i) |
257 | { | 259 | { |
260 | memset(port, 0, sizeof(*port)); | ||
258 | port->id = i; | 261 | port->id = i; |
259 | INIT_LIST_HEAD(&port->dev_list); | 262 | INIT_LIST_HEAD(&port->dev_list); |
260 | spin_lock_init(&port->phy_list_lock); | 263 | spin_lock_init(&port->phy_list_lock); |
261 | INIT_LIST_HEAD(&port->phy_list); | 264 | INIT_LIST_HEAD(&port->phy_list); |
262 | port->num_phys = 0; | ||
263 | port->phy_mask = 0; | ||
264 | port->ha = sas_ha; | 265 | port->ha = sas_ha; |
265 | 266 | ||
266 | spin_lock_init(&port->dev_list_lock); | 267 | spin_lock_init(&port->dev_list_lock); |
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 704ea06a6e50..1f8241563c6c 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c | |||
@@ -434,7 +434,7 @@ static int sas_recover_I_T(struct domain_device *dev) | |||
434 | } | 434 | } |
435 | 435 | ||
436 | /* Find the sas_phy that's attached to this device */ | 436 | /* Find the sas_phy that's attached to this device */ |
437 | static struct sas_phy *find_local_sas_phy(struct domain_device *dev) | 437 | struct sas_phy *sas_find_local_phy(struct domain_device *dev) |
438 | { | 438 | { |
439 | struct domain_device *pdev = dev->parent; | 439 | struct domain_device *pdev = dev->parent; |
440 | struct ex_phy *exphy = NULL; | 440 | struct ex_phy *exphy = NULL; |
@@ -456,6 +456,7 @@ static struct sas_phy *find_local_sas_phy(struct domain_device *dev) | |||
456 | BUG_ON(!exphy); | 456 | BUG_ON(!exphy); |
457 | return exphy->phy; | 457 | return exphy->phy; |
458 | } | 458 | } |
459 | EXPORT_SYMBOL_GPL(sas_find_local_phy); | ||
459 | 460 | ||
460 | /* Attempt to send a LUN reset message to a device */ | 461 | /* Attempt to send a LUN reset message to a device */ |
461 | int sas_eh_device_reset_handler(struct scsi_cmnd *cmd) | 462 | int sas_eh_device_reset_handler(struct scsi_cmnd *cmd) |
@@ -482,7 +483,7 @@ int sas_eh_device_reset_handler(struct scsi_cmnd *cmd) | |||
482 | int sas_eh_bus_reset_handler(struct scsi_cmnd *cmd) | 483 | int sas_eh_bus_reset_handler(struct scsi_cmnd *cmd) |
483 | { | 484 | { |
484 | struct domain_device *dev = cmd_to_domain_dev(cmd); | 485 | struct domain_device *dev = cmd_to_domain_dev(cmd); |
485 | struct sas_phy *phy = find_local_sas_phy(dev); | 486 | struct sas_phy *phy = sas_find_local_phy(dev); |
486 | int res; | 487 | int res; |
487 | 488 | ||
488 | res = sas_phy_reset(phy, 1); | 489 | res = sas_phy_reset(phy, 1); |
@@ -497,10 +498,10 @@ int sas_eh_bus_reset_handler(struct scsi_cmnd *cmd) | |||
497 | } | 498 | } |
498 | 499 | ||
499 | /* Try to reset a device */ | 500 | /* Try to reset a device */ |
500 | static int try_to_reset_cmd_device(struct Scsi_Host *shost, | 501 | static int try_to_reset_cmd_device(struct scsi_cmnd *cmd) |
501 | struct scsi_cmnd *cmd) | ||
502 | { | 502 | { |
503 | int res; | 503 | int res; |
504 | struct Scsi_Host *shost = cmd->device->host; | ||
504 | 505 | ||
505 | if (!shost->hostt->eh_device_reset_handler) | 506 | if (!shost->hostt->eh_device_reset_handler) |
506 | goto try_bus_reset; | 507 | goto try_bus_reset; |
@@ -540,6 +541,12 @@ Again: | |||
540 | need_reset = task->task_state_flags & SAS_TASK_NEED_DEV_RESET; | 541 | need_reset = task->task_state_flags & SAS_TASK_NEED_DEV_RESET; |
541 | spin_unlock_irqrestore(&task->task_state_lock, flags); | 542 | spin_unlock_irqrestore(&task->task_state_lock, flags); |
542 | 543 | ||
544 | if (need_reset) { | ||
545 | SAS_DPRINTK("%s: task 0x%p requests reset\n", | ||
546 | __FUNCTION__, task); | ||
547 | goto reset; | ||
548 | } | ||
549 | |||
543 | SAS_DPRINTK("trying to find task 0x%p\n", task); | 550 | SAS_DPRINTK("trying to find task 0x%p\n", task); |
544 | res = sas_scsi_find_task(task); | 551 | res = sas_scsi_find_task(task); |
545 | 552 | ||
@@ -550,18 +557,15 @@ Again: | |||
550 | SAS_DPRINTK("%s: task 0x%p is done\n", __FUNCTION__, | 557 | SAS_DPRINTK("%s: task 0x%p is done\n", __FUNCTION__, |
551 | task); | 558 | task); |
552 | sas_eh_finish_cmd(cmd); | 559 | sas_eh_finish_cmd(cmd); |
553 | if (need_reset) | ||
554 | try_to_reset_cmd_device(shost, cmd); | ||
555 | continue; | 560 | continue; |
556 | case TASK_IS_ABORTED: | 561 | case TASK_IS_ABORTED: |
557 | SAS_DPRINTK("%s: task 0x%p is aborted\n", | 562 | SAS_DPRINTK("%s: task 0x%p is aborted\n", |
558 | __FUNCTION__, task); | 563 | __FUNCTION__, task); |
559 | sas_eh_finish_cmd(cmd); | 564 | sas_eh_finish_cmd(cmd); |
560 | if (need_reset) | ||
561 | try_to_reset_cmd_device(shost, cmd); | ||
562 | continue; | 565 | continue; |
563 | case TASK_IS_AT_LU: | 566 | case TASK_IS_AT_LU: |
564 | SAS_DPRINTK("task 0x%p is at LU: lu recover\n", task); | 567 | SAS_DPRINTK("task 0x%p is at LU: lu recover\n", task); |
568 | reset: | ||
565 | tmf_resp = sas_recover_lu(task->dev, cmd); | 569 | tmf_resp = sas_recover_lu(task->dev, cmd); |
566 | if (tmf_resp == TMF_RESP_FUNC_COMPLETE) { | 570 | if (tmf_resp == TMF_RESP_FUNC_COMPLETE) { |
567 | SAS_DPRINTK("dev %016llx LU %x is " | 571 | SAS_DPRINTK("dev %016llx LU %x is " |
@@ -569,8 +573,6 @@ Again: | |||
569 | SAS_ADDR(task->dev), | 573 | SAS_ADDR(task->dev), |
570 | cmd->device->lun); | 574 | cmd->device->lun); |
571 | sas_eh_finish_cmd(cmd); | 575 | sas_eh_finish_cmd(cmd); |
572 | if (need_reset) | ||
573 | try_to_reset_cmd_device(shost, cmd); | ||
574 | sas_scsi_clear_queue_lu(work_q, cmd); | 576 | sas_scsi_clear_queue_lu(work_q, cmd); |
575 | goto Again; | 577 | goto Again; |
576 | } | 578 | } |
@@ -581,15 +583,15 @@ Again: | |||
581 | task); | 583 | task); |
582 | tmf_resp = sas_recover_I_T(task->dev); | 584 | tmf_resp = sas_recover_I_T(task->dev); |
583 | if (tmf_resp == TMF_RESP_FUNC_COMPLETE) { | 585 | if (tmf_resp == TMF_RESP_FUNC_COMPLETE) { |
586 | struct domain_device *dev = task->dev; | ||
584 | SAS_DPRINTK("I_T %016llx recovered\n", | 587 | SAS_DPRINTK("I_T %016llx recovered\n", |
585 | SAS_ADDR(task->dev->sas_addr)); | 588 | SAS_ADDR(task->dev->sas_addr)); |
586 | sas_eh_finish_cmd(cmd); | 589 | sas_eh_finish_cmd(cmd); |
587 | if (need_reset) | 590 | sas_scsi_clear_queue_I_T(work_q, dev); |
588 | try_to_reset_cmd_device(shost, cmd); | ||
589 | sas_scsi_clear_queue_I_T(work_q, task->dev); | ||
590 | goto Again; | 591 | goto Again; |
591 | } | 592 | } |
592 | /* Hammer time :-) */ | 593 | /* Hammer time :-) */ |
594 | try_to_reset_cmd_device(cmd); | ||
593 | if (i->dft->lldd_clear_nexus_port) { | 595 | if (i->dft->lldd_clear_nexus_port) { |
594 | struct asd_sas_port *port = task->dev->port; | 596 | struct asd_sas_port *port = task->dev->port; |
595 | SAS_DPRINTK("clearing nexus for port:%d\n", | 597 | SAS_DPRINTK("clearing nexus for port:%d\n", |
@@ -599,8 +601,6 @@ Again: | |||
599 | SAS_DPRINTK("clear nexus port:%d " | 601 | SAS_DPRINTK("clear nexus port:%d " |
600 | "succeeded\n", port->id); | 602 | "succeeded\n", port->id); |
601 | sas_eh_finish_cmd(cmd); | 603 | sas_eh_finish_cmd(cmd); |
602 | if (need_reset) | ||
603 | try_to_reset_cmd_device(shost, cmd); | ||
604 | sas_scsi_clear_queue_port(work_q, | 604 | sas_scsi_clear_queue_port(work_q, |
605 | port); | 605 | port); |
606 | goto Again; | 606 | goto Again; |
@@ -613,8 +613,6 @@ Again: | |||
613 | SAS_DPRINTK("clear nexus ha " | 613 | SAS_DPRINTK("clear nexus ha " |
614 | "succeeded\n"); | 614 | "succeeded\n"); |
615 | sas_eh_finish_cmd(cmd); | 615 | sas_eh_finish_cmd(cmd); |
616 | if (need_reset) | ||
617 | try_to_reset_cmd_device(shost, cmd); | ||
618 | goto clear_q; | 616 | goto clear_q; |
619 | } | 617 | } |
620 | } | 618 | } |
@@ -628,8 +626,6 @@ Again: | |||
628 | cmd->device->lun); | 626 | cmd->device->lun); |
629 | 627 | ||
630 | sas_eh_finish_cmd(cmd); | 628 | sas_eh_finish_cmd(cmd); |
631 | if (need_reset) | ||
632 | try_to_reset_cmd_device(shost, cmd); | ||
633 | goto clear_q; | 629 | goto clear_q; |
634 | } | 630 | } |
635 | } | 631 | } |