[SCSI] libsas: make ATA functions selectable by a config option

Not everyone wants libsas automatically to pull in libata. This patch
makes the behaviour configurable, so you can build libsas with or
without ATA support.

Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>

authored by James Bottomley and committed by James Bottomley b9142174 41e1703b

+436 -397
+7
drivers/scsi/libsas/Kconfig
··· 30 This provides transport specific helpers for SAS drivers which 31 use the domain device construct (like the aic94xxx). 32 33 config SCSI_SAS_LIBSAS_DEBUG 34 bool "Compile the SAS Domain Transport Attributes in debug mode" 35 default y
··· 30 This provides transport specific helpers for SAS drivers which 31 use the domain device construct (like the aic94xxx). 32 33 + config SCSI_SAS_ATA 34 + bool "ATA support for libsas (requires libata)" 35 + depends on SCSI_SAS_LIBSAS && ATA 36 + help 37 + Builds in ATA support into libsas. Will necessitate 38 + the loading of libata along with libsas. 39 + 40 config SCSI_SAS_LIBSAS_DEBUG 41 bool "Compile the SAS Domain Transport Attributes in debug mode" 42 default y
+2 -2
drivers/scsi/libsas/Makefile
··· 33 sas_dump.o \ 34 sas_discover.o \ 35 sas_expander.o \ 36 - sas_scsi_host.o \ 37 - sas_ata.o
··· 33 sas_dump.o \ 34 sas_discover.o \ 35 sas_expander.o \ 36 + sas_scsi_host.o 37 + libsas-$(CONFIG_SCSI_SAS_ATA) += sas_ata.o
+397
drivers/scsi/libsas/sas_ata.c
··· 21 * USA 22 */ 23 24 #include <scsi/sas_ata.h> 25 #include "sas_internal.h" 26 #include <scsi/scsi_host.h> ··· 419 qc->err_mask |= AC_ERR_TIMEOUT; 420 waiting = qc->private_data; 421 complete(waiting); 422 }
··· 21 * USA 22 */ 23 24 + #include <linux/scatterlist.h> 25 + 26 #include <scsi/sas_ata.h> 27 #include "sas_internal.h" 28 #include <scsi/scsi_host.h> ··· 417 qc->err_mask |= AC_ERR_TIMEOUT; 418 waiting = qc->private_data; 419 complete(waiting); 420 + } 421 + 422 + static void sas_task_timedout(unsigned long _task) 423 + { 424 + struct sas_task *task = (void *) _task; 425 + unsigned long flags; 426 + 427 + spin_lock_irqsave(&task->task_state_lock, flags); 428 + if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) 429 + task->task_state_flags |= SAS_TASK_STATE_ABORTED; 430 + spin_unlock_irqrestore(&task->task_state_lock, flags); 431 + 432 + complete(&task->completion); 433 + } 434 + 435 + static void sas_disc_task_done(struct sas_task *task) 436 + { 437 + if (!del_timer(&task->timer)) 438 + return; 439 + complete(&task->completion); 440 + } 441 + 442 + #define SAS_DEV_TIMEOUT 10 443 + 444 + /** 445 + * sas_execute_task -- Basic task processing for discovery 446 + * @task: the task to be executed 447 + * @buffer: pointer to buffer to do I/O 448 + * @size: size of @buffer 449 + * @pci_dma_dir: PCI_DMA_... 450 + */ 451 + static int sas_execute_task(struct sas_task *task, void *buffer, int size, 452 + int pci_dma_dir) 453 + { 454 + int res = 0; 455 + struct scatterlist *scatter = NULL; 456 + struct task_status_struct *ts = &task->task_status; 457 + int num_scatter = 0; 458 + int retries = 0; 459 + struct sas_internal *i = 460 + to_sas_internal(task->dev->port->ha->core.shost->transportt); 461 + 462 + if (pci_dma_dir != PCI_DMA_NONE) { 463 + scatter = kzalloc(sizeof(*scatter), GFP_KERNEL); 464 + if (!scatter) 465 + goto out; 466 + 467 + sg_init_one(scatter, buffer, size); 468 + num_scatter = 1; 469 + } 470 + 471 + task->task_proto = task->dev->tproto; 472 + task->scatter = scatter; 473 + task->num_scatter = num_scatter; 474 + task->total_xfer_len = size; 475 + task->data_dir = pci_dma_dir; 476 + task->task_done = sas_disc_task_done; 477 + if (pci_dma_dir != PCI_DMA_NONE && 478 + sas_protocol_ata(task->task_proto)) { 479 + task->num_scatter = pci_map_sg(task->dev->port->ha->pcidev, 480 + task->scatter, 481 + task->num_scatter, 482 + task->data_dir); 483 + } 484 + 485 + for (retries = 0; retries < 5; retries++) { 486 + task->task_state_flags = SAS_TASK_STATE_PENDING; 487 + init_completion(&task->completion); 488 + 489 + task->timer.data = (unsigned long) task; 490 + task->timer.function = sas_task_timedout; 491 + task->timer.expires = jiffies + SAS_DEV_TIMEOUT*HZ; 492 + add_timer(&task->timer); 493 + 494 + res = i->dft->lldd_execute_task(task, 1, GFP_KERNEL); 495 + if (res) { 496 + del_timer(&task->timer); 497 + SAS_DPRINTK("executing SAS discovery task failed:%d\n", 498 + res); 499 + goto ex_err; 500 + } 501 + wait_for_completion(&task->completion); 502 + res = -ETASK; 503 + if (task->task_state_flags & SAS_TASK_STATE_ABORTED) { 504 + int res2; 505 + SAS_DPRINTK("task aborted, flags:0x%x\n", 506 + task->task_state_flags); 507 + res2 = i->dft->lldd_abort_task(task); 508 + SAS_DPRINTK("came back from abort task\n"); 509 + if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { 510 + if (res2 == TMF_RESP_FUNC_COMPLETE) 511 + continue; /* Retry the task */ 512 + else 513 + goto ex_err; 514 + } 515 + } 516 + if (task->task_status.stat == SAM_BUSY || 517 + task->task_status.stat == SAM_TASK_SET_FULL || 518 + task->task_status.stat == SAS_QUEUE_FULL) { 519 + SAS_DPRINTK("task: q busy, sleeping...\n"); 520 + schedule_timeout_interruptible(HZ); 521 + } else if (task->task_status.stat == SAM_CHECK_COND) { 522 + struct scsi_sense_hdr shdr; 523 + 524 + if (!scsi_normalize_sense(ts->buf, ts->buf_valid_size, 525 + &shdr)) { 526 + SAS_DPRINTK("couldn't normalize sense\n"); 527 + continue; 528 + } 529 + if ((shdr.sense_key == 6 && shdr.asc == 0x29) || 530 + (shdr.sense_key == 2 && shdr.asc == 4 && 531 + shdr.ascq == 1)) { 532 + SAS_DPRINTK("device %016llx LUN: %016llx " 533 + "powering up or not ready yet, " 534 + "sleeping...\n", 535 + SAS_ADDR(task->dev->sas_addr), 536 + SAS_ADDR(task->ssp_task.LUN)); 537 + 538 + schedule_timeout_interruptible(5*HZ); 539 + } else if (shdr.sense_key == 1) { 540 + res = 0; 541 + break; 542 + } else if (shdr.sense_key == 5) { 543 + break; 544 + } else { 545 + SAS_DPRINTK("dev %016llx LUN: %016llx " 546 + "sense key:0x%x ASC:0x%x ASCQ:0x%x" 547 + "\n", 548 + SAS_ADDR(task->dev->sas_addr), 549 + SAS_ADDR(task->ssp_task.LUN), 550 + shdr.sense_key, 551 + shdr.asc, shdr.ascq); 552 + } 553 + } else if (task->task_status.resp != SAS_TASK_COMPLETE || 554 + task->task_status.stat != SAM_GOOD) { 555 + SAS_DPRINTK("task finished with resp:0x%x, " 556 + "stat:0x%x\n", 557 + task->task_status.resp, 558 + task->task_status.stat); 559 + goto ex_err; 560 + } else { 561 + res = 0; 562 + break; 563 + } 564 + } 565 + ex_err: 566 + if (pci_dma_dir != PCI_DMA_NONE) { 567 + if (sas_protocol_ata(task->task_proto)) 568 + pci_unmap_sg(task->dev->port->ha->pcidev, 569 + task->scatter, task->num_scatter, 570 + task->data_dir); 571 + kfree(scatter); 572 + } 573 + out: 574 + return res; 575 + } 576 + 577 + /* ---------- SATA ---------- */ 578 + 579 + static void sas_get_ata_command_set(struct domain_device *dev) 580 + { 581 + struct dev_to_host_fis *fis = 582 + (struct dev_to_host_fis *) dev->frame_rcvd; 583 + 584 + if ((fis->sector_count == 1 && /* ATA */ 585 + fis->lbal == 1 && 586 + fis->lbam == 0 && 587 + fis->lbah == 0 && 588 + fis->device == 0) 589 + || 590 + (fis->sector_count == 0 && /* CE-ATA (mATA) */ 591 + fis->lbal == 0 && 592 + fis->lbam == 0xCE && 593 + fis->lbah == 0xAA && 594 + (fis->device & ~0x10) == 0)) 595 + 596 + dev->sata_dev.command_set = ATA_COMMAND_SET; 597 + 598 + else if ((fis->interrupt_reason == 1 && /* ATAPI */ 599 + fis->lbal == 1 && 600 + fis->byte_count_low == 0x14 && 601 + fis->byte_count_high == 0xEB && 602 + (fis->device & ~0x10) == 0)) 603 + 604 + dev->sata_dev.command_set = ATAPI_COMMAND_SET; 605 + 606 + else if ((fis->sector_count == 1 && /* SEMB */ 607 + fis->lbal == 1 && 608 + fis->lbam == 0x3C && 609 + fis->lbah == 0xC3 && 610 + fis->device == 0) 611 + || 612 + (fis->interrupt_reason == 1 && /* SATA PM */ 613 + fis->lbal == 1 && 614 + fis->byte_count_low == 0x69 && 615 + fis->byte_count_high == 0x96 && 616 + (fis->device & ~0x10) == 0)) 617 + 618 + /* Treat it as a superset? */ 619 + dev->sata_dev.command_set = ATAPI_COMMAND_SET; 620 + } 621 + 622 + /** 623 + * sas_issue_ata_cmd -- Basic SATA command processing for discovery 624 + * @dev: the device to send the command to 625 + * @command: the command register 626 + * @features: the features register 627 + * @buffer: pointer to buffer to do I/O 628 + * @size: size of @buffer 629 + * @pci_dma_dir: PCI_DMA_... 630 + */ 631 + static int sas_issue_ata_cmd(struct domain_device *dev, u8 command, 632 + u8 features, void *buffer, int size, 633 + int pci_dma_dir) 634 + { 635 + int res = 0; 636 + struct sas_task *task; 637 + struct dev_to_host_fis *d2h_fis = (struct dev_to_host_fis *) 638 + &dev->frame_rcvd[0]; 639 + 640 + res = -ENOMEM; 641 + task = sas_alloc_task(GFP_KERNEL); 642 + if (!task) 643 + goto out; 644 + 645 + task->dev = dev; 646 + 647 + task->ata_task.fis.fis_type = 0x27; 648 + task->ata_task.fis.command = command; 649 + task->ata_task.fis.features = features; 650 + task->ata_task.fis.device = d2h_fis->device; 651 + task->ata_task.retry_count = 1; 652 + 653 + res = sas_execute_task(task, buffer, size, pci_dma_dir); 654 + 655 + sas_free_task(task); 656 + out: 657 + return res; 658 + } 659 + 660 + static void sas_sata_propagate_sas_addr(struct domain_device *dev) 661 + { 662 + unsigned long flags; 663 + struct asd_sas_port *port = dev->port; 664 + struct asd_sas_phy *phy; 665 + 666 + BUG_ON(dev->parent); 667 + 668 + memcpy(port->attached_sas_addr, dev->sas_addr, SAS_ADDR_SIZE); 669 + spin_lock_irqsave(&port->phy_list_lock, flags); 670 + list_for_each_entry(phy, &port->phy_list, port_phy_el) 671 + memcpy(phy->attached_sas_addr, dev->sas_addr, SAS_ADDR_SIZE); 672 + spin_unlock_irqrestore(&port->phy_list_lock, flags); 673 + } 674 + 675 + #define ATA_IDENTIFY_DEV 0xEC 676 + #define ATA_IDENTIFY_PACKET_DEV 0xA1 677 + #define ATA_SET_FEATURES 0xEF 678 + #define ATA_FEATURE_PUP_STBY_SPIN_UP 0x07 679 + 680 + /** 681 + * sas_discover_sata_dev -- discover a STP/SATA device (SATA_DEV) 682 + * @dev: STP/SATA device of interest (ATA/ATAPI) 683 + * 684 + * The LLDD has already been notified of this device, so that we can 685 + * send FISes to it. Here we try to get IDENTIFY DEVICE or IDENTIFY 686 + * PACKET DEVICE, if ATAPI device, so that the LLDD can fine-tune its 687 + * performance for this device. 688 + */ 689 + static int sas_discover_sata_dev(struct domain_device *dev) 690 + { 691 + int res; 692 + __le16 *identify_x; 693 + u8 command; 694 + 695 + identify_x = kzalloc(512, GFP_KERNEL); 696 + if (!identify_x) 697 + return -ENOMEM; 698 + 699 + if (dev->sata_dev.command_set == ATA_COMMAND_SET) { 700 + dev->sata_dev.identify_device = identify_x; 701 + command = ATA_IDENTIFY_DEV; 702 + } else { 703 + dev->sata_dev.identify_packet_device = identify_x; 704 + command = ATA_IDENTIFY_PACKET_DEV; 705 + } 706 + 707 + res = sas_issue_ata_cmd(dev, command, 0, identify_x, 512, 708 + PCI_DMA_FROMDEVICE); 709 + if (res) 710 + goto out_err; 711 + 712 + /* lives on the media? */ 713 + if (le16_to_cpu(identify_x[0]) & 4) { 714 + /* incomplete response */ 715 + SAS_DPRINTK("sending SET FEATURE/PUP_STBY_SPIN_UP to " 716 + "dev %llx\n", SAS_ADDR(dev->sas_addr)); 717 + if (!le16_to_cpu(identify_x[83] & (1<<6))) 718 + goto cont1; 719 + res = sas_issue_ata_cmd(dev, ATA_SET_FEATURES, 720 + ATA_FEATURE_PUP_STBY_SPIN_UP, 721 + NULL, 0, PCI_DMA_NONE); 722 + if (res) 723 + goto cont1; 724 + 725 + schedule_timeout_interruptible(5*HZ); /* More time? */ 726 + res = sas_issue_ata_cmd(dev, command, 0, identify_x, 512, 727 + PCI_DMA_FROMDEVICE); 728 + if (res) 729 + goto out_err; 730 + } 731 + cont1: 732 + /* Get WWN */ 733 + if (dev->port->oob_mode != SATA_OOB_MODE) { 734 + memcpy(dev->sas_addr, dev->sata_dev.rps_resp.rps.stp_sas_addr, 735 + SAS_ADDR_SIZE); 736 + } else if (dev->sata_dev.command_set == ATA_COMMAND_SET && 737 + (le16_to_cpu(dev->sata_dev.identify_device[108]) & 0xF000) 738 + == 0x5000) { 739 + int i; 740 + 741 + for (i = 0; i < 4; i++) { 742 + dev->sas_addr[2*i] = 743 + (le16_to_cpu(dev->sata_dev.identify_device[108+i]) & 0xFF00) >> 8; 744 + dev->sas_addr[2*i+1] = 745 + le16_to_cpu(dev->sata_dev.identify_device[108+i]) & 0x00FF; 746 + } 747 + } 748 + sas_hash_addr(dev->hashed_sas_addr, dev->sas_addr); 749 + if (!dev->parent) 750 + sas_sata_propagate_sas_addr(dev); 751 + 752 + /* XXX Hint: register this SATA device with SATL. 753 + When this returns, dev->sata_dev->lu is alive and 754 + present. 755 + sas_satl_register_dev(dev); 756 + */ 757 + 758 + sas_fill_in_rphy(dev, dev->rphy); 759 + 760 + return 0; 761 + out_err: 762 + dev->sata_dev.identify_packet_device = NULL; 763 + dev->sata_dev.identify_device = NULL; 764 + kfree(identify_x); 765 + return res; 766 + } 767 + 768 + static int sas_discover_sata_pm(struct domain_device *dev) 769 + { 770 + return -ENODEV; 771 + } 772 + 773 + /** 774 + * sas_discover_sata -- discover an STP/SATA domain device 775 + * @dev: pointer to struct domain_device of interest 776 + * 777 + * First we notify the LLDD of this device, so we can send frames to 778 + * it. Then depending on the type of device we call the appropriate 779 + * discover functions. Once device discover is done, we notify the 780 + * LLDD so that it can fine-tune its parameters for the device, by 781 + * removing it and then adding it. That is, the second time around, 782 + * the driver would have certain fields, that it is looking at, set. 783 + * Finally we initialize the kobj so that the device can be added to 784 + * the system at registration time. Devices directly attached to a HA 785 + * port, have no parents. All other devices do, and should have their 786 + * "parent" pointer set appropriately before calling this function. 787 + */ 788 + int sas_discover_sata(struct domain_device *dev) 789 + { 790 + int res; 791 + 792 + sas_get_ata_command_set(dev); 793 + 794 + res = sas_notify_lldd_dev_found(dev); 795 + if (res) 796 + return res; 797 + 798 + switch (dev->dev_type) { 799 + case SATA_DEV: 800 + res = sas_discover_sata_dev(dev); 801 + break; 802 + case SATA_PM: 803 + res = sas_discover_sata_pm(dev); 804 + break; 805 + default: 806 + break; 807 + } 808 + sas_notify_lldd_dev_gone(dev); 809 + if (!res) { 810 + sas_notify_lldd_dev_found(dev); 811 + res = sas_rphy_add(dev->rphy); 812 + } 813 + 814 + return res; 815 }
+3 -394
drivers/scsi/libsas/sas_discover.c
··· 55 } 56 } 57 58 - static void sas_task_timedout(unsigned long _task) 59 - { 60 - struct sas_task *task = (void *) _task; 61 - unsigned long flags; 62 - 63 - spin_lock_irqsave(&task->task_state_lock, flags); 64 - if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) 65 - task->task_state_flags |= SAS_TASK_STATE_ABORTED; 66 - spin_unlock_irqrestore(&task->task_state_lock, flags); 67 - 68 - complete(&task->completion); 69 - } 70 - 71 - static void sas_disc_task_done(struct sas_task *task) 72 - { 73 - if (!del_timer(&task->timer)) 74 - return; 75 - complete(&task->completion); 76 - } 77 - 78 - #define SAS_DEV_TIMEOUT 10 79 - 80 - /** 81 - * sas_execute_task -- Basic task processing for discovery 82 - * @task: the task to be executed 83 - * @buffer: pointer to buffer to do I/O 84 - * @size: size of @buffer 85 - * @pci_dma_dir: PCI_DMA_... 86 - */ 87 - static int sas_execute_task(struct sas_task *task, void *buffer, int size, 88 - int pci_dma_dir) 89 - { 90 - int res = 0; 91 - struct scatterlist *scatter = NULL; 92 - struct task_status_struct *ts = &task->task_status; 93 - int num_scatter = 0; 94 - int retries = 0; 95 - struct sas_internal *i = 96 - to_sas_internal(task->dev->port->ha->core.shost->transportt); 97 - 98 - if (pci_dma_dir != PCI_DMA_NONE) { 99 - scatter = kzalloc(sizeof(*scatter), GFP_KERNEL); 100 - if (!scatter) 101 - goto out; 102 - 103 - sg_init_one(scatter, buffer, size); 104 - num_scatter = 1; 105 - } 106 - 107 - task->task_proto = task->dev->tproto; 108 - task->scatter = scatter; 109 - task->num_scatter = num_scatter; 110 - task->total_xfer_len = size; 111 - task->data_dir = pci_dma_dir; 112 - task->task_done = sas_disc_task_done; 113 - if (pci_dma_dir != PCI_DMA_NONE && 114 - sas_protocol_ata(task->task_proto)) { 115 - task->num_scatter = pci_map_sg(task->dev->port->ha->pcidev, 116 - task->scatter, 117 - task->num_scatter, 118 - task->data_dir); 119 - } 120 - 121 - for (retries = 0; retries < 5; retries++) { 122 - task->task_state_flags = SAS_TASK_STATE_PENDING; 123 - init_completion(&task->completion); 124 - 125 - task->timer.data = (unsigned long) task; 126 - task->timer.function = sas_task_timedout; 127 - task->timer.expires = jiffies + SAS_DEV_TIMEOUT*HZ; 128 - add_timer(&task->timer); 129 - 130 - res = i->dft->lldd_execute_task(task, 1, GFP_KERNEL); 131 - if (res) { 132 - del_timer(&task->timer); 133 - SAS_DPRINTK("executing SAS discovery task failed:%d\n", 134 - res); 135 - goto ex_err; 136 - } 137 - wait_for_completion(&task->completion); 138 - res = -ETASK; 139 - if (task->task_state_flags & SAS_TASK_STATE_ABORTED) { 140 - int res2; 141 - SAS_DPRINTK("task aborted, flags:0x%x\n", 142 - task->task_state_flags); 143 - res2 = i->dft->lldd_abort_task(task); 144 - SAS_DPRINTK("came back from abort task\n"); 145 - if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { 146 - if (res2 == TMF_RESP_FUNC_COMPLETE) 147 - continue; /* Retry the task */ 148 - else 149 - goto ex_err; 150 - } 151 - } 152 - if (task->task_status.stat == SAM_BUSY || 153 - task->task_status.stat == SAM_TASK_SET_FULL || 154 - task->task_status.stat == SAS_QUEUE_FULL) { 155 - SAS_DPRINTK("task: q busy, sleeping...\n"); 156 - schedule_timeout_interruptible(HZ); 157 - } else if (task->task_status.stat == SAM_CHECK_COND) { 158 - struct scsi_sense_hdr shdr; 159 - 160 - if (!scsi_normalize_sense(ts->buf, ts->buf_valid_size, 161 - &shdr)) { 162 - SAS_DPRINTK("couldn't normalize sense\n"); 163 - continue; 164 - } 165 - if ((shdr.sense_key == 6 && shdr.asc == 0x29) || 166 - (shdr.sense_key == 2 && shdr.asc == 4 && 167 - shdr.ascq == 1)) { 168 - SAS_DPRINTK("device %016llx LUN: %016llx " 169 - "powering up or not ready yet, " 170 - "sleeping...\n", 171 - SAS_ADDR(task->dev->sas_addr), 172 - SAS_ADDR(task->ssp_task.LUN)); 173 - 174 - schedule_timeout_interruptible(5*HZ); 175 - } else if (shdr.sense_key == 1) { 176 - res = 0; 177 - break; 178 - } else if (shdr.sense_key == 5) { 179 - break; 180 - } else { 181 - SAS_DPRINTK("dev %016llx LUN: %016llx " 182 - "sense key:0x%x ASC:0x%x ASCQ:0x%x" 183 - "\n", 184 - SAS_ADDR(task->dev->sas_addr), 185 - SAS_ADDR(task->ssp_task.LUN), 186 - shdr.sense_key, 187 - shdr.asc, shdr.ascq); 188 - } 189 - } else if (task->task_status.resp != SAS_TASK_COMPLETE || 190 - task->task_status.stat != SAM_GOOD) { 191 - SAS_DPRINTK("task finished with resp:0x%x, " 192 - "stat:0x%x\n", 193 - task->task_status.resp, 194 - task->task_status.stat); 195 - goto ex_err; 196 - } else { 197 - res = 0; 198 - break; 199 - } 200 - } 201 - ex_err: 202 - if (pci_dma_dir != PCI_DMA_NONE) { 203 - if (sas_protocol_ata(task->task_proto)) 204 - pci_unmap_sg(task->dev->port->ha->pcidev, 205 - task->scatter, task->num_scatter, 206 - task->data_dir); 207 - kfree(scatter); 208 - } 209 - out: 210 - return res; 211 - } 212 - 213 /* ---------- Domain device discovery ---------- */ 214 215 /** ··· 158 159 /* ---------- Discover and Revalidate ---------- */ 160 161 - /* ---------- SATA ---------- */ 162 - 163 - static void sas_get_ata_command_set(struct domain_device *dev) 164 - { 165 - struct dev_to_host_fis *fis = 166 - (struct dev_to_host_fis *) dev->frame_rcvd; 167 - 168 - if ((fis->sector_count == 1 && /* ATA */ 169 - fis->lbal == 1 && 170 - fis->lbam == 0 && 171 - fis->lbah == 0 && 172 - fis->device == 0) 173 - || 174 - (fis->sector_count == 0 && /* CE-ATA (mATA) */ 175 - fis->lbal == 0 && 176 - fis->lbam == 0xCE && 177 - fis->lbah == 0xAA && 178 - (fis->device & ~0x10) == 0)) 179 - 180 - dev->sata_dev.command_set = ATA_COMMAND_SET; 181 - 182 - else if ((fis->interrupt_reason == 1 && /* ATAPI */ 183 - fis->lbal == 1 && 184 - fis->byte_count_low == 0x14 && 185 - fis->byte_count_high == 0xEB && 186 - (fis->device & ~0x10) == 0)) 187 - 188 - dev->sata_dev.command_set = ATAPI_COMMAND_SET; 189 - 190 - else if ((fis->sector_count == 1 && /* SEMB */ 191 - fis->lbal == 1 && 192 - fis->lbam == 0x3C && 193 - fis->lbah == 0xC3 && 194 - fis->device == 0) 195 - || 196 - (fis->interrupt_reason == 1 && /* SATA PM */ 197 - fis->lbal == 1 && 198 - fis->byte_count_low == 0x69 && 199 - fis->byte_count_high == 0x96 && 200 - (fis->device & ~0x10) == 0)) 201 - 202 - /* Treat it as a superset? */ 203 - dev->sata_dev.command_set = ATAPI_COMMAND_SET; 204 - } 205 - 206 - /** 207 - * sas_issue_ata_cmd -- Basic SATA command processing for discovery 208 - * @dev: the device to send the command to 209 - * @command: the command register 210 - * @features: the features register 211 - * @buffer: pointer to buffer to do I/O 212 - * @size: size of @buffer 213 - * @pci_dma_dir: PCI_DMA_... 214 - */ 215 - static int sas_issue_ata_cmd(struct domain_device *dev, u8 command, 216 - u8 features, void *buffer, int size, 217 - int pci_dma_dir) 218 - { 219 - int res = 0; 220 - struct sas_task *task; 221 - struct dev_to_host_fis *d2h_fis = (struct dev_to_host_fis *) 222 - &dev->frame_rcvd[0]; 223 - 224 - res = -ENOMEM; 225 - task = sas_alloc_task(GFP_KERNEL); 226 - if (!task) 227 - goto out; 228 - 229 - task->dev = dev; 230 - 231 - task->ata_task.fis.fis_type = 0x27; 232 - task->ata_task.fis.command = command; 233 - task->ata_task.fis.features = features; 234 - task->ata_task.fis.device = d2h_fis->device; 235 - task->ata_task.retry_count = 1; 236 - 237 - res = sas_execute_task(task, buffer, size, pci_dma_dir); 238 - 239 - sas_free_task(task); 240 - out: 241 - return res; 242 - } 243 - 244 - static void sas_sata_propagate_sas_addr(struct domain_device *dev) 245 - { 246 - unsigned long flags; 247 - struct asd_sas_port *port = dev->port; 248 - struct asd_sas_phy *phy; 249 - 250 - BUG_ON(dev->parent); 251 - 252 - memcpy(port->attached_sas_addr, dev->sas_addr, SAS_ADDR_SIZE); 253 - spin_lock_irqsave(&port->phy_list_lock, flags); 254 - list_for_each_entry(phy, &port->phy_list, port_phy_el) 255 - memcpy(phy->attached_sas_addr, dev->sas_addr, SAS_ADDR_SIZE); 256 - spin_unlock_irqrestore(&port->phy_list_lock, flags); 257 - } 258 - 259 - #define ATA_IDENTIFY_DEV 0xEC 260 - #define ATA_IDENTIFY_PACKET_DEV 0xA1 261 - #define ATA_SET_FEATURES 0xEF 262 - #define ATA_FEATURE_PUP_STBY_SPIN_UP 0x07 263 - 264 - /** 265 - * sas_discover_sata_dev -- discover a STP/SATA device (SATA_DEV) 266 - * @dev: STP/SATA device of interest (ATA/ATAPI) 267 - * 268 - * The LLDD has already been notified of this device, so that we can 269 - * send FISes to it. Here we try to get IDENTIFY DEVICE or IDENTIFY 270 - * PACKET DEVICE, if ATAPI device, so that the LLDD can fine-tune its 271 - * performance for this device. 272 - */ 273 - static int sas_discover_sata_dev(struct domain_device *dev) 274 - { 275 - int res; 276 - __le16 *identify_x; 277 - u8 command; 278 - 279 - identify_x = kzalloc(512, GFP_KERNEL); 280 - if (!identify_x) 281 - return -ENOMEM; 282 - 283 - if (dev->sata_dev.command_set == ATA_COMMAND_SET) { 284 - dev->sata_dev.identify_device = identify_x; 285 - command = ATA_IDENTIFY_DEV; 286 - } else { 287 - dev->sata_dev.identify_packet_device = identify_x; 288 - command = ATA_IDENTIFY_PACKET_DEV; 289 - } 290 - 291 - res = sas_issue_ata_cmd(dev, command, 0, identify_x, 512, 292 - PCI_DMA_FROMDEVICE); 293 - if (res) 294 - goto out_err; 295 - 296 - /* lives on the media? */ 297 - if (le16_to_cpu(identify_x[0]) & 4) { 298 - /* incomplete response */ 299 - SAS_DPRINTK("sending SET FEATURE/PUP_STBY_SPIN_UP to " 300 - "dev %llx\n", SAS_ADDR(dev->sas_addr)); 301 - if (!le16_to_cpu(identify_x[83] & (1<<6))) 302 - goto cont1; 303 - res = sas_issue_ata_cmd(dev, ATA_SET_FEATURES, 304 - ATA_FEATURE_PUP_STBY_SPIN_UP, 305 - NULL, 0, PCI_DMA_NONE); 306 - if (res) 307 - goto cont1; 308 - 309 - schedule_timeout_interruptible(5*HZ); /* More time? */ 310 - res = sas_issue_ata_cmd(dev, command, 0, identify_x, 512, 311 - PCI_DMA_FROMDEVICE); 312 - if (res) 313 - goto out_err; 314 - } 315 - cont1: 316 - /* Get WWN */ 317 - if (dev->port->oob_mode != SATA_OOB_MODE) { 318 - memcpy(dev->sas_addr, dev->sata_dev.rps_resp.rps.stp_sas_addr, 319 - SAS_ADDR_SIZE); 320 - } else if (dev->sata_dev.command_set == ATA_COMMAND_SET && 321 - (le16_to_cpu(dev->sata_dev.identify_device[108]) & 0xF000) 322 - == 0x5000) { 323 - int i; 324 - 325 - for (i = 0; i < 4; i++) { 326 - dev->sas_addr[2*i] = 327 - (le16_to_cpu(dev->sata_dev.identify_device[108+i]) & 0xFF00) >> 8; 328 - dev->sas_addr[2*i+1] = 329 - le16_to_cpu(dev->sata_dev.identify_device[108+i]) & 0x00FF; 330 - } 331 - } 332 - sas_hash_addr(dev->hashed_sas_addr, dev->sas_addr); 333 - if (!dev->parent) 334 - sas_sata_propagate_sas_addr(dev); 335 - 336 - /* XXX Hint: register this SATA device with SATL. 337 - When this returns, dev->sata_dev->lu is alive and 338 - present. 339 - sas_satl_register_dev(dev); 340 - */ 341 - 342 - sas_fill_in_rphy(dev, dev->rphy); 343 - 344 - return 0; 345 - out_err: 346 - dev->sata_dev.identify_packet_device = NULL; 347 - dev->sata_dev.identify_device = NULL; 348 - kfree(identify_x); 349 - return res; 350 - } 351 - 352 - static int sas_discover_sata_pm(struct domain_device *dev) 353 - { 354 - return -ENODEV; 355 - } 356 - 357 int sas_notify_lldd_dev_found(struct domain_device *dev) 358 { 359 int res = 0; ··· 190 191 /* ---------- Common/dispatchers ---------- */ 192 193 - /** 194 - * sas_discover_sata -- discover an STP/SATA domain device 195 - * @dev: pointer to struct domain_device of interest 196 - * 197 - * First we notify the LLDD of this device, so we can send frames to 198 - * it. Then depending on the type of device we call the appropriate 199 - * discover functions. Once device discover is done, we notify the 200 - * LLDD so that it can fine-tune its parameters for the device, by 201 - * removing it and then adding it. That is, the second time around, 202 - * the driver would have certain fields, that it is looking at, set. 203 - * Finally we initialize the kobj so that the device can be added to 204 - * the system at registration time. Devices directly attached to a HA 205 - * port, have no parents. All other devices do, and should have their 206 - * "parent" pointer set appropriately before calling this function. 207 - */ 208 - int sas_discover_sata(struct domain_device *dev) 209 - { 210 - int res; 211 - 212 - sas_get_ata_command_set(dev); 213 - 214 - res = sas_notify_lldd_dev_found(dev); 215 - if (res) 216 - return res; 217 - 218 - switch (dev->dev_type) { 219 - case SATA_DEV: 220 - res = sas_discover_sata_dev(dev); 221 - break; 222 - case SATA_PM: 223 - res = sas_discover_sata_pm(dev); 224 - break; 225 - default: 226 - break; 227 - } 228 - sas_notify_lldd_dev_gone(dev); 229 - if (!res) { 230 - sas_notify_lldd_dev_found(dev); 231 - res = sas_rphy_add(dev->rphy); 232 - } 233 - 234 - return res; 235 - } 236 237 /** 238 * sas_discover_end_dev -- discover an end device (SSP, etc) ··· 296 case FANOUT_DEV: 297 error = sas_discover_root_expander(dev); 298 break; 299 case SATA_DEV: 300 case SATA_PM: 301 error = sas_discover_sata(dev); 302 break; 303 default: 304 SAS_DPRINTK("unhandled device %d\n", dev->dev_type); 305 break; 306 }
··· 55 } 56 } 57 58 /* ---------- Domain device discovery ---------- */ 59 60 /** ··· 313 314 /* ---------- Discover and Revalidate ---------- */ 315 316 int sas_notify_lldd_dev_found(struct domain_device *dev) 317 { 318 int res = 0; ··· 541 542 /* ---------- Common/dispatchers ---------- */ 543 544 545 /** 546 * sas_discover_end_dev -- discover an end device (SSP, etc) ··· 690 case FANOUT_DEV: 691 error = sas_discover_root_expander(dev); 692 break; 693 + #ifdef CONFIG_SCSI_SAS_ATA 694 case SATA_DEV: 695 case SATA_PM: 696 error = sas_discover_sata(dev); 697 break; 698 + #endif 699 default: 700 + error = -ENXIO; 701 SAS_DPRINTK("unhandled device %d\n", dev->dev_type); 702 break; 703 }
+8 -1
drivers/scsi/libsas/sas_expander.c
··· 535 536 } 537 538 #define RPS_REQ_SIZE 16 539 #define RPS_RESP_SIZE 60 540 ··· 580 kfree(rps_req); 581 return res; 582 } 583 584 static void sas_ex_get_linkrate(struct domain_device *parent, 585 struct domain_device *child, ··· 648 } 649 sas_ex_get_linkrate(parent, child, phy); 650 651 if ((phy->attached_tproto & SAS_PROTO_STP) || phy->attached_sata_dev) { 652 child->dev_type = SATA_DEV; 653 if (phy->attached_tproto & SAS_PROTO_STP) ··· 686 SAS_ADDR(parent->sas_addr), phy_id, res); 687 goto out_list_del; 688 } 689 - } else if (phy->attached_tproto & SAS_PROTO_SSP) { 690 child->dev_type = SAS_END_DEV; 691 rphy = sas_end_device_alloc(phy->port); 692 /* FIXME: error handling */ ··· 716 SAS_DPRINTK("target proto 0x%x at %016llx:0x%x not handled\n", 717 phy->attached_tproto, SAS_ADDR(parent->sas_addr), 718 phy_id); 719 } 720 721 list_add_tail(&child->siblings, &parent_ex->children);
··· 535 536 } 537 538 + #ifdef CONFIG_SCSI_SAS_ATA 539 + 540 #define RPS_REQ_SIZE 16 541 #define RPS_RESP_SIZE 60 542 ··· 578 kfree(rps_req); 579 return res; 580 } 581 + #endif 582 583 static void sas_ex_get_linkrate(struct domain_device *parent, 584 struct domain_device *child, ··· 645 } 646 sas_ex_get_linkrate(parent, child, phy); 647 648 + #ifdef CONFIG_SCSI_SAS_ATA 649 if ((phy->attached_tproto & SAS_PROTO_STP) || phy->attached_sata_dev) { 650 child->dev_type = SATA_DEV; 651 if (phy->attached_tproto & SAS_PROTO_STP) ··· 682 SAS_ADDR(parent->sas_addr), phy_id, res); 683 goto out_list_del; 684 } 685 + } else 686 + #endif 687 + if (phy->attached_tproto & SAS_PROTO_SSP) { 688 child->dev_type = SAS_END_DEV; 689 rphy = sas_end_device_alloc(phy->port); 690 /* FIXME: error handling */ ··· 710 SAS_DPRINTK("target proto 0x%x at %016llx:0x%x not handled\n", 711 phy->attached_tproto, SAS_ADDR(parent->sas_addr), 712 phy_id); 713 + goto out_free; 714 } 715 716 list_add_tail(&child->siblings, &parent_ex->children);
+19
include/scsi/sas_ata.h
··· 28 #include <linux/libata.h> 29 #include <scsi/libsas.h> 30 31 static inline int dev_is_sata(struct domain_device *dev) 32 { 33 return (dev->rphy->identify.target_port_protocols & SAS_PROTOCOL_SATA); ··· 39 struct scsi_target *starget); 40 41 void sas_ata_task_abort(struct sas_task *task); 42 43 #endif /* _SAS_ATA_H_ */
··· 28 #include <linux/libata.h> 29 #include <scsi/libsas.h> 30 31 + #ifdef CONFIG_SCSI_SAS_ATA 32 + 33 static inline int dev_is_sata(struct domain_device *dev) 34 { 35 return (dev->rphy->identify.target_port_protocols & SAS_PROTOCOL_SATA); ··· 37 struct scsi_target *starget); 38 39 void sas_ata_task_abort(struct sas_task *task); 40 + 41 + #else 42 + 43 + 44 + static inline int dev_is_sata(struct domain_device *dev) 45 + { 46 + return 0; 47 + } 48 + int sas_ata_init_host_and_port(struct domain_device *found_dev, 49 + struct scsi_target *starget) 50 + { 51 + return 0; 52 + } 53 + void sas_ata_task_abort(struct sas_task *task) 54 + { 55 + } 56 + #endif 57 58 #endif /* _SAS_ATA_H_ */