diff options
| author | James Bottomley <JBottomley@Odin.com> | 2015-11-12 07:06:18 -0500 |
|---|---|---|
| committer | James Bottomley <JBottomley@Odin.com> | 2015-11-12 07:06:18 -0500 |
| commit | febdfbd2137a5727f70dfbf920105c07e6c2a21e (patch) | |
| tree | 9483a5493ad3e08626e1f53ded594f88a6f4e710 | |
| parent | 0da39687a15403251bdfd1c6fb18025c0607326b (diff) | |
| parent | 2c5d16d6a9e7218e57b716e4fd9d77c776d21471 (diff) | |
Merge tag '4.4-scsi-mkp' into misc
SCSI queue for 4.4.
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
68 files changed, 5848 insertions, 31761 deletions
diff --git a/Documentation/devicetree/bindings/ufs/ufs-qcom.txt b/Documentation/devicetree/bindings/ufs/ufs-qcom.txt new file mode 100644 index 000000000000..070baf4d7d97 --- /dev/null +++ b/Documentation/devicetree/bindings/ufs/ufs-qcom.txt | |||
| @@ -0,0 +1,58 @@ | |||
| 1 | * Qualcomm Technologies Inc Universal Flash Storage (UFS) PHY | ||
| 2 | |||
| 3 | UFSPHY nodes are defined to describe on-chip UFS PHY hardware macro. | ||
| 4 | Each UFS PHY node should have its own node. | ||
| 5 | |||
| 6 | To bind UFS PHY with UFS host controller, the controller node should | ||
| 7 | contain a phandle reference to UFS PHY node. | ||
| 8 | |||
| 9 | Required properties: | ||
| 10 | - compatible : compatible list, contains "qcom,ufs-phy-qmp-20nm" | ||
| 11 | or "qcom,ufs-phy-qmp-14nm" according to the relevant phy in use. | ||
| 12 | - reg : should contain PHY register address space (mandatory), | ||
| 13 | - reg-names : indicates various resources passed to driver (via reg proptery) by name. | ||
| 14 | Required "reg-names" is "phy_mem". | ||
| 15 | - #phy-cells : This property shall be set to 0 | ||
| 16 | - vdda-phy-supply : phandle to main PHY supply for analog domain | ||
| 17 | - vdda-pll-supply : phandle to PHY PLL and Power-Gen block power supply | ||
| 18 | - clocks : List of phandle and clock specifier pairs | ||
| 19 | - clock-names : List of clock input name strings sorted in the same | ||
| 20 | order as the clocks property. "ref_clk_src", "ref_clk", | ||
| 21 | "tx_iface_clk" & "rx_iface_clk" are mandatory but | ||
| 22 | "ref_clk_parent" is optional | ||
| 23 | |||
| 24 | Optional properties: | ||
| 25 | - vdda-phy-max-microamp : specifies max. load that can be drawn from phy supply | ||
| 26 | - vdda-pll-max-microamp : specifies max. load that can be drawn from pll supply | ||
| 27 | - vddp-ref-clk-supply : phandle to UFS device ref_clk pad power supply | ||
| 28 | - vddp-ref-clk-max-microamp : specifies max. load that can be drawn from this supply | ||
| 29 | - vddp-ref-clk-always-on : specifies if this supply needs to be kept always on | ||
| 30 | |||
| 31 | Example: | ||
| 32 | |||
| 33 | ufsphy1: ufsphy@0xfc597000 { | ||
| 34 | compatible = "qcom,ufs-phy-qmp-20nm"; | ||
| 35 | reg = <0xfc597000 0x800>; | ||
| 36 | reg-names = "phy_mem"; | ||
| 37 | #phy-cells = <0>; | ||
| 38 | vdda-phy-supply = <&pma8084_l4>; | ||
| 39 | vdda-pll-supply = <&pma8084_l12>; | ||
| 40 | vdda-phy-max-microamp = <50000>; | ||
| 41 | vdda-pll-max-microamp = <1000>; | ||
| 42 | clock-names = "ref_clk_src", | ||
| 43 | "ref_clk_parent", | ||
| 44 | "ref_clk", | ||
| 45 | "tx_iface_clk", | ||
| 46 | "rx_iface_clk"; | ||
| 47 | clocks = <&clock_rpm clk_ln_bb_clk>, | ||
| 48 | <&clock_gcc clk_pcie_1_phy_ldo >, | ||
| 49 | <&clock_gcc clk_ufs_phy_ldo>, | ||
| 50 | <&clock_gcc clk_gcc_ufs_tx_cfg_clk>, | ||
| 51 | <&clock_gcc clk_gcc_ufs_rx_cfg_clk>; | ||
| 52 | }; | ||
| 53 | |||
| 54 | ufshc@0xfc598000 { | ||
| 55 | ... | ||
| 56 | phys = <&ufsphy1>; | ||
| 57 | phy-names = "ufsphy"; | ||
| 58 | }; | ||
diff --git a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt index 53579197eca2..03c0e989e020 100644 --- a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt +++ b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt | |||
| @@ -4,11 +4,18 @@ UFSHC nodes are defined to describe on-chip UFS host controllers. | |||
| 4 | Each UFS controller instance should have its own node. | 4 | Each UFS controller instance should have its own node. |
| 5 | 5 | ||
| 6 | Required properties: | 6 | Required properties: |
| 7 | - compatible : compatible list, contains "jedec,ufs-1.1" | 7 | - compatible : must contain "jedec,ufs-1.1", may also list one or more |
| 8 | of the following: | ||
| 9 | "qcom,msm8994-ufshc" | ||
| 10 | "qcom,msm8996-ufshc" | ||
| 11 | "qcom,ufshc" | ||
| 8 | - interrupts : <interrupt mapping for UFS host controller IRQ> | 12 | - interrupts : <interrupt mapping for UFS host controller IRQ> |
| 9 | - reg : <registers mapping> | 13 | - reg : <registers mapping> |
| 10 | 14 | ||
| 11 | Optional properties: | 15 | Optional properties: |
| 16 | - phys : phandle to UFS PHY node | ||
| 17 | - phy-names : the string "ufsphy" when is found in a node, along | ||
| 18 | with "phys" attribute, provides phandle to UFS PHY node | ||
| 12 | - vdd-hba-supply : phandle to UFS host controller supply regulator node | 19 | - vdd-hba-supply : phandle to UFS host controller supply regulator node |
| 13 | - vcc-supply : phandle to VCC supply regulator node | 20 | - vcc-supply : phandle to VCC supply regulator node |
| 14 | - vccq-supply : phandle to VCCQ supply regulator node | 21 | - vccq-supply : phandle to VCCQ supply regulator node |
| @@ -54,4 +61,6 @@ Example: | |||
| 54 | clocks = <&core 0>, <&ref 0>, <&iface 0>; | 61 | clocks = <&core 0>, <&ref 0>, <&iface 0>; |
| 55 | clock-names = "core_clk", "ref_clk", "iface_clk"; | 62 | clock-names = "core_clk", "ref_clk", "iface_clk"; |
| 56 | freq-table-hz = <100000000 200000000>, <0 0>, <0 0>; | 63 | freq-table-hz = <100000000 200000000>, <0 0>, <0 0>; |
| 64 | phys = <&ufsphy1>; | ||
| 65 | phy-names = "ufsphy"; | ||
| 57 | }; | 66 | }; |
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index fc7393729081..02b5f69e1a42 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c | |||
| @@ -1038,6 +1038,10 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, int sge_offset, int *frags, | |||
| 1038 | int i, buflist_ent; | 1038 | int i, buflist_ent; |
| 1039 | int sg_spill = MAX_FRAGS_SPILL1; | 1039 | int sg_spill = MAX_FRAGS_SPILL1; |
| 1040 | int dir; | 1040 | int dir; |
| 1041 | |||
| 1042 | if (bytes < 0) | ||
| 1043 | return NULL; | ||
| 1044 | |||
| 1041 | /* initialization */ | 1045 | /* initialization */ |
| 1042 | *frags = 0; | 1046 | *frags = 0; |
| 1043 | *blp = NULL; | 1047 | *blp = NULL; |
diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/phy-qcom-ufs.c index 49a1ed0cef56..107cb57c3513 100644 --- a/drivers/phy/phy-qcom-ufs.c +++ b/drivers/phy/phy-qcom-ufs.c | |||
| @@ -432,6 +432,7 @@ out_disable_src: | |||
| 432 | out: | 432 | out: |
| 433 | return ret; | 433 | return ret; |
| 434 | } | 434 | } |
| 435 | EXPORT_SYMBOL_GPL(ufs_qcom_phy_enable_ref_clk); | ||
| 435 | 436 | ||
| 436 | static | 437 | static |
| 437 | int ufs_qcom_phy_disable_vreg(struct phy *phy, | 438 | int ufs_qcom_phy_disable_vreg(struct phy *phy, |
| @@ -474,6 +475,7 @@ void ufs_qcom_phy_disable_ref_clk(struct phy *generic_phy) | |||
| 474 | phy->is_ref_clk_enabled = false; | 475 | phy->is_ref_clk_enabled = false; |
| 475 | } | 476 | } |
| 476 | } | 477 | } |
| 478 | EXPORT_SYMBOL_GPL(ufs_qcom_phy_disable_ref_clk); | ||
| 477 | 479 | ||
| 478 | #define UFS_REF_CLK_EN (1 << 5) | 480 | #define UFS_REF_CLK_EN (1 << 5) |
| 479 | 481 | ||
| @@ -517,11 +519,13 @@ void ufs_qcom_phy_enable_dev_ref_clk(struct phy *generic_phy) | |||
| 517 | { | 519 | { |
| 518 | ufs_qcom_phy_dev_ref_clk_ctrl(generic_phy, true); | 520 | ufs_qcom_phy_dev_ref_clk_ctrl(generic_phy, true); |
| 519 | } | 521 | } |
| 522 | EXPORT_SYMBOL_GPL(ufs_qcom_phy_enable_dev_ref_clk); | ||
| 520 | 523 | ||
| 521 | void ufs_qcom_phy_disable_dev_ref_clk(struct phy *generic_phy) | 524 | void ufs_qcom_phy_disable_dev_ref_clk(struct phy *generic_phy) |
| 522 | { | 525 | { |
| 523 | ufs_qcom_phy_dev_ref_clk_ctrl(generic_phy, false); | 526 | ufs_qcom_phy_dev_ref_clk_ctrl(generic_phy, false); |
| 524 | } | 527 | } |
| 528 | EXPORT_SYMBOL_GPL(ufs_qcom_phy_disable_dev_ref_clk); | ||
| 525 | 529 | ||
| 526 | /* Turn ON M-PHY RMMI interface clocks */ | 530 | /* Turn ON M-PHY RMMI interface clocks */ |
| 527 | int ufs_qcom_phy_enable_iface_clk(struct phy *generic_phy) | 531 | int ufs_qcom_phy_enable_iface_clk(struct phy *generic_phy) |
| @@ -550,6 +554,7 @@ int ufs_qcom_phy_enable_iface_clk(struct phy *generic_phy) | |||
| 550 | out: | 554 | out: |
| 551 | return ret; | 555 | return ret; |
| 552 | } | 556 | } |
| 557 | EXPORT_SYMBOL_GPL(ufs_qcom_phy_enable_iface_clk); | ||
| 553 | 558 | ||
| 554 | /* Turn OFF M-PHY RMMI interface clocks */ | 559 | /* Turn OFF M-PHY RMMI interface clocks */ |
| 555 | void ufs_qcom_phy_disable_iface_clk(struct phy *generic_phy) | 560 | void ufs_qcom_phy_disable_iface_clk(struct phy *generic_phy) |
| @@ -562,6 +567,7 @@ void ufs_qcom_phy_disable_iface_clk(struct phy *generic_phy) | |||
| 562 | phy->is_iface_clk_enabled = false; | 567 | phy->is_iface_clk_enabled = false; |
| 563 | } | 568 | } |
| 564 | } | 569 | } |
| 570 | EXPORT_SYMBOL_GPL(ufs_qcom_phy_disable_iface_clk); | ||
| 565 | 571 | ||
| 566 | int ufs_qcom_phy_start_serdes(struct phy *generic_phy) | 572 | int ufs_qcom_phy_start_serdes(struct phy *generic_phy) |
| 567 | { | 573 | { |
| @@ -578,6 +584,7 @@ int ufs_qcom_phy_start_serdes(struct phy *generic_phy) | |||
| 578 | 584 | ||
| 579 | return ret; | 585 | return ret; |
| 580 | } | 586 | } |
| 587 | EXPORT_SYMBOL_GPL(ufs_qcom_phy_start_serdes); | ||
| 581 | 588 | ||
| 582 | int ufs_qcom_phy_set_tx_lane_enable(struct phy *generic_phy, u32 tx_lanes) | 589 | int ufs_qcom_phy_set_tx_lane_enable(struct phy *generic_phy, u32 tx_lanes) |
| 583 | { | 590 | { |
| @@ -595,6 +602,7 @@ int ufs_qcom_phy_set_tx_lane_enable(struct phy *generic_phy, u32 tx_lanes) | |||
| 595 | 602 | ||
| 596 | return ret; | 603 | return ret; |
| 597 | } | 604 | } |
| 605 | EXPORT_SYMBOL_GPL(ufs_qcom_phy_set_tx_lane_enable); | ||
| 598 | 606 | ||
| 599 | void ufs_qcom_phy_save_controller_version(struct phy *generic_phy, | 607 | void ufs_qcom_phy_save_controller_version(struct phy *generic_phy, |
| 600 | u8 major, u16 minor, u16 step) | 608 | u8 major, u16 minor, u16 step) |
| @@ -605,6 +613,7 @@ void ufs_qcom_phy_save_controller_version(struct phy *generic_phy, | |||
| 605 | ufs_qcom_phy->host_ctrl_rev_minor = minor; | 613 | ufs_qcom_phy->host_ctrl_rev_minor = minor; |
| 606 | ufs_qcom_phy->host_ctrl_rev_step = step; | 614 | ufs_qcom_phy->host_ctrl_rev_step = step; |
| 607 | } | 615 | } |
| 616 | EXPORT_SYMBOL_GPL(ufs_qcom_phy_save_controller_version); | ||
| 608 | 617 | ||
| 609 | int ufs_qcom_phy_calibrate_phy(struct phy *generic_phy, bool is_rate_B) | 618 | int ufs_qcom_phy_calibrate_phy(struct phy *generic_phy, bool is_rate_B) |
| 610 | { | 619 | { |
| @@ -625,6 +634,7 @@ int ufs_qcom_phy_calibrate_phy(struct phy *generic_phy, bool is_rate_B) | |||
| 625 | 634 | ||
| 626 | return ret; | 635 | return ret; |
| 627 | } | 636 | } |
| 637 | EXPORT_SYMBOL_GPL(ufs_qcom_phy_calibrate_phy); | ||
| 628 | 638 | ||
| 629 | int ufs_qcom_phy_remove(struct phy *generic_phy, | 639 | int ufs_qcom_phy_remove(struct phy *generic_phy, |
| 630 | struct ufs_qcom_phy *ufs_qcom_phy) | 640 | struct ufs_qcom_phy *ufs_qcom_phy) |
| @@ -662,6 +672,7 @@ int ufs_qcom_phy_is_pcs_ready(struct phy *generic_phy) | |||
| 662 | return ufs_qcom_phy->phy_spec_ops-> | 672 | return ufs_qcom_phy->phy_spec_ops-> |
| 663 | is_physical_coding_sublayer_ready(ufs_qcom_phy); | 673 | is_physical_coding_sublayer_ready(ufs_qcom_phy); |
| 664 | } | 674 | } |
| 675 | EXPORT_SYMBOL_GPL(ufs_qcom_phy_is_pcs_ready); | ||
| 665 | 676 | ||
| 666 | int ufs_qcom_phy_power_on(struct phy *generic_phy) | 677 | int ufs_qcom_phy_power_on(struct phy *generic_phy) |
| 667 | { | 678 | { |
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 95f7a76cfafc..8aed855dd391 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig | |||
| @@ -541,7 +541,6 @@ config SCSI_ARCMSR | |||
| 541 | 541 | ||
| 542 | source "drivers/scsi/esas2r/Kconfig" | 542 | source "drivers/scsi/esas2r/Kconfig" |
| 543 | source "drivers/scsi/megaraid/Kconfig.megaraid" | 543 | source "drivers/scsi/megaraid/Kconfig.megaraid" |
| 544 | source "drivers/scsi/mpt2sas/Kconfig" | ||
| 545 | source "drivers/scsi/mpt3sas/Kconfig" | 544 | source "drivers/scsi/mpt3sas/Kconfig" |
| 546 | source "drivers/scsi/ufs/Kconfig" | 545 | source "drivers/scsi/ufs/Kconfig" |
| 547 | 546 | ||
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 1a8c9b53fafa..c14bca4a9675 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile | |||
| @@ -106,7 +106,6 @@ obj-$(CONFIG_CXLFLASH) += cxlflash/ | |||
| 106 | obj-$(CONFIG_MEGARAID_LEGACY) += megaraid.o | 106 | obj-$(CONFIG_MEGARAID_LEGACY) += megaraid.o |
| 107 | obj-$(CONFIG_MEGARAID_NEWGEN) += megaraid/ | 107 | obj-$(CONFIG_MEGARAID_NEWGEN) += megaraid/ |
| 108 | obj-$(CONFIG_MEGARAID_SAS) += megaraid/ | 108 | obj-$(CONFIG_MEGARAID_SAS) += megaraid/ |
| 109 | obj-$(CONFIG_SCSI_MPT2SAS) += mpt2sas/ | ||
| 110 | obj-$(CONFIG_SCSI_MPT3SAS) += mpt3sas/ | 109 | obj-$(CONFIG_SCSI_MPT3SAS) += mpt3sas/ |
| 111 | obj-$(CONFIG_SCSI_UFSHCD) += ufs/ | 110 | obj-$(CONFIG_SCSI_UFSHCD) += ufs/ |
| 112 | obj-$(CONFIG_SCSI_ACARD) += atp870u.o | 111 | obj-$(CONFIG_SCSI_ACARD) += atp870u.o |
diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c index cd094bf82a77..662b2321d1b0 100644 --- a/drivers/scsi/aic94xx/aic94xx_init.c +++ b/drivers/scsi/aic94xx/aic94xx_init.c | |||
| @@ -703,10 +703,10 @@ static int asd_unregister_sas_ha(struct asd_ha_struct *asd_ha) | |||
| 703 | { | 703 | { |
| 704 | int err; | 704 | int err; |
| 705 | 705 | ||
| 706 | scsi_remove_host(asd_ha->sas_ha.core.shost); | ||
| 706 | err = sas_unregister_ha(&asd_ha->sas_ha); | 707 | err = sas_unregister_ha(&asd_ha->sas_ha); |
| 707 | 708 | ||
| 708 | sas_remove_host(asd_ha->sas_ha.core.shost); | 709 | sas_remove_host(asd_ha->sas_ha.core.shost); |
| 709 | scsi_remove_host(asd_ha->sas_ha.core.shost); | ||
| 710 | scsi_host_put(asd_ha->sas_ha.core.shost); | 710 | scsi_host_put(asd_ha->sas_ha.core.shost); |
| 711 | 711 | ||
| 712 | kfree(asd_ha->sas_ha.sas_phy); | 712 | kfree(asd_ha->sas_ha.sas_phy); |
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 864d978b7ae0..fe0c5143f8e6 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c | |||
| @@ -3186,7 +3186,7 @@ be_sgl_create_contiguous(void *virtual_address, | |||
| 3186 | { | 3186 | { |
| 3187 | WARN_ON(!virtual_address); | 3187 | WARN_ON(!virtual_address); |
| 3188 | WARN_ON(!physical_address); | 3188 | WARN_ON(!physical_address); |
| 3189 | WARN_ON(!length > 0); | 3189 | WARN_ON(!length); |
| 3190 | WARN_ON(!sgl); | 3190 | WARN_ON(!sgl); |
| 3191 | 3191 | ||
| 3192 | sgl->va = virtual_address; | 3192 | sgl->va = virtual_address; |
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 7506b65d8e6c..6a8f95808ee0 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c | |||
| @@ -41,6 +41,7 @@ | |||
| 41 | #include <scsi/scsi_host.h> | 41 | #include <scsi/scsi_host.h> |
| 42 | #include <scsi/scsi_tcq.h> | 42 | #include <scsi/scsi_tcq.h> |
| 43 | #include <scsi/scsi_eh.h> | 43 | #include <scsi/scsi_eh.h> |
| 44 | #include <scsi/scsi_transport_sas.h> | ||
| 44 | #include <scsi/scsi_dbg.h> | 45 | #include <scsi/scsi_dbg.h> |
| 45 | #include <linux/cciss_ioctl.h> | 46 | #include <linux/cciss_ioctl.h> |
| 46 | #include <linux/string.h> | 47 | #include <linux/string.h> |
| @@ -54,8 +55,11 @@ | |||
| 54 | #include "hpsa_cmd.h" | 55 | #include "hpsa_cmd.h" |
| 55 | #include "hpsa.h" | 56 | #include "hpsa.h" |
| 56 | 57 | ||
| 57 | /* HPSA_DRIVER_VERSION must be 3 byte values (0-255) separated by '.' */ | 58 | /* |
| 58 | #define HPSA_DRIVER_VERSION "3.4.10-0" | 59 | * HPSA_DRIVER_VERSION must be 3 byte values (0-255) separated by '.' |
| 60 | * with an optional trailing '-' followed by a byte value (0-255). | ||
| 61 | */ | ||
| 62 | #define HPSA_DRIVER_VERSION "3.4.14-0" | ||
| 59 | #define DRIVER_NAME "HP HPSA Driver (v " HPSA_DRIVER_VERSION ")" | 63 | #define DRIVER_NAME "HP HPSA Driver (v " HPSA_DRIVER_VERSION ")" |
| 60 | #define HPSA "hpsa" | 64 | #define HPSA "hpsa" |
| 61 | 65 | ||
| @@ -205,6 +209,16 @@ static struct board_type products[] = { | |||
| 205 | {0xFFFF103C, "Unknown Smart Array", &SA5_access}, | 209 | {0xFFFF103C, "Unknown Smart Array", &SA5_access}, |
| 206 | }; | 210 | }; |
| 207 | 211 | ||
| 212 | static struct scsi_transport_template *hpsa_sas_transport_template; | ||
| 213 | static int hpsa_add_sas_host(struct ctlr_info *h); | ||
| 214 | static void hpsa_delete_sas_host(struct ctlr_info *h); | ||
| 215 | static int hpsa_add_sas_device(struct hpsa_sas_node *hpsa_sas_node, | ||
| 216 | struct hpsa_scsi_dev_t *device); | ||
| 217 | static void hpsa_remove_sas_device(struct hpsa_scsi_dev_t *device); | ||
| 218 | static struct hpsa_scsi_dev_t | ||
| 219 | *hpsa_find_device_by_sas_rphy(struct ctlr_info *h, | ||
| 220 | struct sas_rphy *rphy); | ||
| 221 | |||
| 208 | #define SCSI_CMD_BUSY ((struct scsi_cmnd *)&hpsa_cmd_busy) | 222 | #define SCSI_CMD_BUSY ((struct scsi_cmnd *)&hpsa_cmd_busy) |
| 209 | static const struct scsi_cmnd hpsa_cmd_busy; | 223 | static const struct scsi_cmnd hpsa_cmd_busy; |
| 210 | #define SCSI_CMD_IDLE ((struct scsi_cmnd *)&hpsa_cmd_idle) | 224 | #define SCSI_CMD_IDLE ((struct scsi_cmnd *)&hpsa_cmd_idle) |
| @@ -230,6 +244,7 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h, | |||
| 230 | int cmd_type); | 244 | int cmd_type); |
| 231 | static void hpsa_free_cmd_pool(struct ctlr_info *h); | 245 | static void hpsa_free_cmd_pool(struct ctlr_info *h); |
| 232 | #define VPD_PAGE (1 << 8) | 246 | #define VPD_PAGE (1 << 8) |
| 247 | #define HPSA_SIMPLE_ERROR_BITS 0x03 | ||
| 233 | 248 | ||
| 234 | static int hpsa_scsi_queue_command(struct Scsi_Host *h, struct scsi_cmnd *cmd); | 249 | static int hpsa_scsi_queue_command(struct Scsi_Host *h, struct scsi_cmnd *cmd); |
| 235 | static void hpsa_scan_start(struct Scsi_Host *); | 250 | static void hpsa_scan_start(struct Scsi_Host *); |
| @@ -243,7 +258,7 @@ static int hpsa_slave_alloc(struct scsi_device *sdev); | |||
| 243 | static int hpsa_slave_configure(struct scsi_device *sdev); | 258 | static int hpsa_slave_configure(struct scsi_device *sdev); |
| 244 | static void hpsa_slave_destroy(struct scsi_device *sdev); | 259 | static void hpsa_slave_destroy(struct scsi_device *sdev); |
| 245 | 260 | ||
| 246 | static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno); | 261 | static void hpsa_update_scsi_devices(struct ctlr_info *h); |
| 247 | static int check_for_unit_attention(struct ctlr_info *h, | 262 | static int check_for_unit_attention(struct ctlr_info *h, |
| 248 | struct CommandList *c); | 263 | struct CommandList *c); |
| 249 | static void check_ioctl_unit_attention(struct ctlr_info *h, | 264 | static void check_ioctl_unit_attention(struct ctlr_info *h, |
| @@ -274,7 +289,10 @@ static int hpsa_scsi_ioaccel_queue_command(struct ctlr_info *h, | |||
| 274 | static void hpsa_command_resubmit_worker(struct work_struct *work); | 289 | static void hpsa_command_resubmit_worker(struct work_struct *work); |
| 275 | static u32 lockup_detected(struct ctlr_info *h); | 290 | static u32 lockup_detected(struct ctlr_info *h); |
| 276 | static int detect_controller_lockup(struct ctlr_info *h); | 291 | static int detect_controller_lockup(struct ctlr_info *h); |
| 277 | static int is_ext_target(struct ctlr_info *h, struct hpsa_scsi_dev_t *device); | 292 | static void hpsa_disable_rld_caching(struct ctlr_info *h); |
| 293 | static inline int hpsa_scsi_do_report_phys_luns(struct ctlr_info *h, | ||
| 294 | struct ReportExtendedLUNdata *buf, int bufsize); | ||
| 295 | static int hpsa_luns_changed(struct ctlr_info *h); | ||
| 278 | 296 | ||
| 279 | static inline struct ctlr_info *sdev_to_hba(struct scsi_device *sdev) | 297 | static inline struct ctlr_info *sdev_to_hba(struct scsi_device *sdev) |
| 280 | { | 298 | { |
| @@ -606,7 +624,7 @@ static inline int is_logical_dev_addr_mode(unsigned char scsi3addr[]) | |||
| 606 | } | 624 | } |
| 607 | 625 | ||
| 608 | static const char * const raid_label[] = { "0", "4", "1(+0)", "5", "5+1", "6", | 626 | static const char * const raid_label[] = { "0", "4", "1(+0)", "5", "5+1", "6", |
| 609 | "1(+0)ADM", "UNKNOWN" | 627 | "1(+0)ADM", "UNKNOWN", "PHYS DRV" |
| 610 | }; | 628 | }; |
| 611 | #define HPSA_RAID_0 0 | 629 | #define HPSA_RAID_0 0 |
| 612 | #define HPSA_RAID_4 1 | 630 | #define HPSA_RAID_4 1 |
| @@ -615,7 +633,13 @@ static const char * const raid_label[] = { "0", "4", "1(+0)", "5", "5+1", "6", | |||
| 615 | #define HPSA_RAID_51 4 | 633 | #define HPSA_RAID_51 4 |
| 616 | #define HPSA_RAID_6 5 /* also used for RAID 60 */ | 634 | #define HPSA_RAID_6 5 /* also used for RAID 60 */ |
| 617 | #define HPSA_RAID_ADM 6 /* also used for RAID 1+0 ADM */ | 635 | #define HPSA_RAID_ADM 6 /* also used for RAID 1+0 ADM */ |
| 618 | #define RAID_UNKNOWN (ARRAY_SIZE(raid_label) - 1) | 636 | #define RAID_UNKNOWN (ARRAY_SIZE(raid_label) - 2) |
| 637 | #define PHYSICAL_DRIVE (ARRAY_SIZE(raid_label) - 1) | ||
| 638 | |||
| 639 | static inline bool is_logical_device(struct hpsa_scsi_dev_t *device) | ||
| 640 | { | ||
| 641 | return !device->physical_device; | ||
| 642 | } | ||
| 619 | 643 | ||
| 620 | static ssize_t raid_level_show(struct device *dev, | 644 | static ssize_t raid_level_show(struct device *dev, |
| 621 | struct device_attribute *attr, char *buf) | 645 | struct device_attribute *attr, char *buf) |
| @@ -637,7 +661,7 @@ static ssize_t raid_level_show(struct device *dev, | |||
| 637 | } | 661 | } |
| 638 | 662 | ||
| 639 | /* Is this even a logical drive? */ | 663 | /* Is this even a logical drive? */ |
| 640 | if (!is_logical_dev_addr_mode(hdev->scsi3addr)) { | 664 | if (!is_logical_device(hdev)) { |
| 641 | spin_unlock_irqrestore(&h->lock, flags); | 665 | spin_unlock_irqrestore(&h->lock, flags); |
| 642 | l = snprintf(buf, PAGE_SIZE, "N/A\n"); | 666 | l = snprintf(buf, PAGE_SIZE, "N/A\n"); |
| 643 | return l; | 667 | return l; |
| @@ -726,7 +750,6 @@ static ssize_t host_show_hp_ssd_smart_path_enabled(struct device *dev, | |||
| 726 | } | 750 | } |
| 727 | 751 | ||
| 728 | #define MAX_PATHS 8 | 752 | #define MAX_PATHS 8 |
| 729 | #define PATH_STRING_LEN 50 | ||
| 730 | 753 | ||
| 731 | static ssize_t path_info_show(struct device *dev, | 754 | static ssize_t path_info_show(struct device *dev, |
| 732 | struct device_attribute *attr, char *buf) | 755 | struct device_attribute *attr, char *buf) |
| @@ -742,9 +765,7 @@ static ssize_t path_info_show(struct device *dev, | |||
| 742 | u8 path_map_index = 0; | 765 | u8 path_map_index = 0; |
| 743 | char *active; | 766 | char *active; |
| 744 | unsigned char phys_connector[2]; | 767 | unsigned char phys_connector[2]; |
| 745 | unsigned char path[MAX_PATHS][PATH_STRING_LEN]; | ||
| 746 | 768 | ||
| 747 | memset(path, 0, MAX_PATHS * PATH_STRING_LEN); | ||
| 748 | sdev = to_scsi_device(dev); | 769 | sdev = to_scsi_device(dev); |
| 749 | h = sdev_to_hba(sdev); | 770 | h = sdev_to_hba(sdev); |
| 750 | spin_lock_irqsave(&h->devlock, flags); | 771 | spin_lock_irqsave(&h->devlock, flags); |
| @@ -764,18 +785,19 @@ static ssize_t path_info_show(struct device *dev, | |||
| 764 | else | 785 | else |
| 765 | continue; | 786 | continue; |
| 766 | 787 | ||
| 767 | output_len = snprintf(path[i], | 788 | output_len += scnprintf(buf + output_len, |
| 768 | PATH_STRING_LEN, "[%d:%d:%d:%d] %20.20s ", | 789 | PAGE_SIZE - output_len, |
| 790 | "[%d:%d:%d:%d] %20.20s ", | ||
| 769 | h->scsi_host->host_no, | 791 | h->scsi_host->host_no, |
| 770 | hdev->bus, hdev->target, hdev->lun, | 792 | hdev->bus, hdev->target, hdev->lun, |
| 771 | scsi_device_type(hdev->devtype)); | 793 | scsi_device_type(hdev->devtype)); |
| 772 | 794 | ||
| 773 | if (is_ext_target(h, hdev) || | 795 | if (hdev->external || |
| 774 | (hdev->devtype == TYPE_RAID) || | 796 | hdev->devtype == TYPE_RAID || |
| 775 | is_logical_dev_addr_mode(hdev->scsi3addr)) { | 797 | is_logical_device(hdev)) { |
| 776 | output_len += snprintf(path[i] + output_len, | 798 | output_len += snprintf(buf + output_len, |
| 777 | PATH_STRING_LEN, "%s\n", | 799 | PAGE_SIZE - output_len, |
| 778 | active); | 800 | "%s\n", active); |
| 779 | continue; | 801 | continue; |
| 780 | } | 802 | } |
| 781 | 803 | ||
| @@ -787,36 +809,33 @@ static ssize_t path_info_show(struct device *dev, | |||
| 787 | if (phys_connector[1] < '0') | 809 | if (phys_connector[1] < '0') |
| 788 | phys_connector[1] = '0'; | 810 | phys_connector[1] = '0'; |
| 789 | if (hdev->phys_connector[i] > 0) | 811 | if (hdev->phys_connector[i] > 0) |
| 790 | output_len += snprintf(path[i] + output_len, | 812 | output_len += snprintf(buf + output_len, |
| 791 | PATH_STRING_LEN, | 813 | PAGE_SIZE - output_len, |
| 792 | "PORT: %.2s ", | 814 | "PORT: %.2s ", |
| 793 | phys_connector); | 815 | phys_connector); |
| 794 | if (hdev->devtype == TYPE_DISK && | 816 | if (hdev->devtype == TYPE_DISK && hdev->expose_device) { |
| 795 | hdev->expose_state != HPSA_DO_NOT_EXPOSE) { | ||
| 796 | if (box == 0 || box == 0xFF) { | 817 | if (box == 0 || box == 0xFF) { |
| 797 | output_len += snprintf(path[i] + output_len, | 818 | output_len += snprintf(buf + output_len, |
| 798 | PATH_STRING_LEN, | 819 | PAGE_SIZE - output_len, |
| 799 | "BAY: %hhu %s\n", | 820 | "BAY: %hhu %s\n", |
| 800 | bay, active); | 821 | bay, active); |
| 801 | } else { | 822 | } else { |
| 802 | output_len += snprintf(path[i] + output_len, | 823 | output_len += snprintf(buf + output_len, |
| 803 | PATH_STRING_LEN, | 824 | PAGE_SIZE - output_len, |
| 804 | "BOX: %hhu BAY: %hhu %s\n", | 825 | "BOX: %hhu BAY: %hhu %s\n", |
| 805 | box, bay, active); | 826 | box, bay, active); |
| 806 | } | 827 | } |
| 807 | } else if (box != 0 && box != 0xFF) { | 828 | } else if (box != 0 && box != 0xFF) { |
| 808 | output_len += snprintf(path[i] + output_len, | 829 | output_len += snprintf(buf + output_len, |
| 809 | PATH_STRING_LEN, "BOX: %hhu %s\n", | 830 | PAGE_SIZE - output_len, "BOX: %hhu %s\n", |
| 810 | box, active); | 831 | box, active); |
| 811 | } else | 832 | } else |
| 812 | output_len += snprintf(path[i] + output_len, | 833 | output_len += snprintf(buf + output_len, |
| 813 | PATH_STRING_LEN, "%s\n", active); | 834 | PAGE_SIZE - output_len, "%s\n", active); |
| 814 | } | 835 | } |
| 815 | 836 | ||
| 816 | spin_unlock_irqrestore(&h->devlock, flags); | 837 | spin_unlock_irqrestore(&h->devlock, flags); |
| 817 | return snprintf(buf, output_len+1, "%s%s%s%s%s%s%s%s", | 838 | return output_len; |
| 818 | path[0], path[1], path[2], path[3], | ||
| 819 | path[4], path[5], path[6], path[7]); | ||
| 820 | } | 839 | } |
| 821 | 840 | ||
| 822 | static DEVICE_ATTR(raid_level, S_IRUGO, raid_level_show, NULL); | 841 | static DEVICE_ATTR(raid_level, S_IRUGO, raid_level_show, NULL); |
| @@ -848,7 +867,6 @@ static struct device_attribute *hpsa_sdev_attrs[] = { | |||
| 848 | &dev_attr_unique_id, | 867 | &dev_attr_unique_id, |
| 849 | &dev_attr_hp_ssd_smart_path_enabled, | 868 | &dev_attr_hp_ssd_smart_path_enabled, |
| 850 | &dev_attr_path_info, | 869 | &dev_attr_path_info, |
| 851 | &dev_attr_lockup_detected, | ||
| 852 | NULL, | 870 | NULL, |
| 853 | }; | 871 | }; |
| 854 | 872 | ||
| @@ -860,6 +878,7 @@ static struct device_attribute *hpsa_shost_attrs[] = { | |||
| 860 | &dev_attr_resettable, | 878 | &dev_attr_resettable, |
| 861 | &dev_attr_hp_ssd_smart_path_status, | 879 | &dev_attr_hp_ssd_smart_path_status, |
| 862 | &dev_attr_raid_offload_debug, | 880 | &dev_attr_raid_offload_debug, |
| 881 | &dev_attr_lockup_detected, | ||
| 863 | NULL, | 882 | NULL, |
| 864 | }; | 883 | }; |
| 865 | 884 | ||
| @@ -1134,25 +1153,62 @@ static int hpsa_find_target_lun(struct ctlr_info *h, | |||
| 1134 | return !found; | 1153 | return !found; |
| 1135 | } | 1154 | } |
| 1136 | 1155 | ||
| 1137 | static inline void hpsa_show_dev_msg(const char *level, struct ctlr_info *h, | 1156 | static void hpsa_show_dev_msg(const char *level, struct ctlr_info *h, |
| 1138 | struct hpsa_scsi_dev_t *dev, char *description) | 1157 | struct hpsa_scsi_dev_t *dev, char *description) |
| 1139 | { | 1158 | { |
| 1159 | #define LABEL_SIZE 25 | ||
| 1160 | char label[LABEL_SIZE]; | ||
| 1161 | |||
| 1162 | if (h == NULL || h->pdev == NULL || h->scsi_host == NULL) | ||
| 1163 | return; | ||
| 1164 | |||
| 1165 | switch (dev->devtype) { | ||
| 1166 | case TYPE_RAID: | ||
| 1167 | snprintf(label, LABEL_SIZE, "controller"); | ||
| 1168 | break; | ||
| 1169 | case TYPE_ENCLOSURE: | ||
| 1170 | snprintf(label, LABEL_SIZE, "enclosure"); | ||
| 1171 | break; | ||
| 1172 | case TYPE_DISK: | ||
| 1173 | if (dev->external) | ||
| 1174 | snprintf(label, LABEL_SIZE, "external"); | ||
| 1175 | else if (!is_logical_dev_addr_mode(dev->scsi3addr)) | ||
| 1176 | snprintf(label, LABEL_SIZE, "%s", | ||
| 1177 | raid_label[PHYSICAL_DRIVE]); | ||
| 1178 | else | ||
| 1179 | snprintf(label, LABEL_SIZE, "RAID-%s", | ||
| 1180 | dev->raid_level > RAID_UNKNOWN ? "?" : | ||
| 1181 | raid_label[dev->raid_level]); | ||
| 1182 | break; | ||
| 1183 | case TYPE_ROM: | ||
| 1184 | snprintf(label, LABEL_SIZE, "rom"); | ||
| 1185 | break; | ||
| 1186 | case TYPE_TAPE: | ||
| 1187 | snprintf(label, LABEL_SIZE, "tape"); | ||
| 1188 | break; | ||
| 1189 | case TYPE_MEDIUM_CHANGER: | ||
| 1190 | snprintf(label, LABEL_SIZE, "changer"); | ||
| 1191 | break; | ||
| 1192 | default: | ||
| 1193 | snprintf(label, LABEL_SIZE, "UNKNOWN"); | ||
| 1194 | break; | ||
| 1195 | } | ||
| 1196 | |||
| 1140 | dev_printk(level, &h->pdev->dev, | 1197 | dev_printk(level, &h->pdev->dev, |
| 1141 | "scsi %d:%d:%d:%d: %s %s %.8s %.16s RAID-%s SSDSmartPathCap%c En%c Exp=%d\n", | 1198 | "scsi %d:%d:%d:%d: %s %s %.8s %.16s %s SSDSmartPathCap%c En%c Exp=%d\n", |
| 1142 | h->scsi_host->host_no, dev->bus, dev->target, dev->lun, | 1199 | h->scsi_host->host_no, dev->bus, dev->target, dev->lun, |
| 1143 | description, | 1200 | description, |
| 1144 | scsi_device_type(dev->devtype), | 1201 | scsi_device_type(dev->devtype), |
| 1145 | dev->vendor, | 1202 | dev->vendor, |
| 1146 | dev->model, | 1203 | dev->model, |
| 1147 | dev->raid_level > RAID_UNKNOWN ? | 1204 | label, |
| 1148 | "RAID-?" : raid_label[dev->raid_level], | ||
| 1149 | dev->offload_config ? '+' : '-', | 1205 | dev->offload_config ? '+' : '-', |
| 1150 | dev->offload_enabled ? '+' : '-', | 1206 | dev->offload_enabled ? '+' : '-', |
| 1151 | dev->expose_state); | 1207 | dev->expose_device); |
| 1152 | } | 1208 | } |
| 1153 | 1209 | ||
| 1154 | /* Add an entry into h->dev[] array. */ | 1210 | /* Add an entry into h->dev[] array. */ |
| 1155 | static int hpsa_scsi_add_entry(struct ctlr_info *h, int hostno, | 1211 | static int hpsa_scsi_add_entry(struct ctlr_info *h, |
| 1156 | struct hpsa_scsi_dev_t *device, | 1212 | struct hpsa_scsi_dev_t *device, |
| 1157 | struct hpsa_scsi_dev_t *added[], int *nadded) | 1213 | struct hpsa_scsi_dev_t *added[], int *nadded) |
| 1158 | { | 1214 | { |
| @@ -1221,14 +1277,14 @@ lun_assigned: | |||
| 1221 | added[*nadded] = device; | 1277 | added[*nadded] = device; |
| 1222 | (*nadded)++; | 1278 | (*nadded)++; |
| 1223 | hpsa_show_dev_msg(KERN_INFO, h, device, | 1279 | hpsa_show_dev_msg(KERN_INFO, h, device, |
| 1224 | device->expose_state & HPSA_SCSI_ADD ? "added" : "masked"); | 1280 | device->expose_device ? "added" : "masked"); |
| 1225 | device->offload_to_be_enabled = device->offload_enabled; | 1281 | device->offload_to_be_enabled = device->offload_enabled; |
| 1226 | device->offload_enabled = 0; | 1282 | device->offload_enabled = 0; |
| 1227 | return 0; | 1283 | return 0; |
| 1228 | } | 1284 | } |
| 1229 | 1285 | ||
| 1230 | /* Update an entry in h->dev[] array. */ | 1286 | /* Update an entry in h->dev[] array. */ |
| 1231 | static void hpsa_scsi_update_entry(struct ctlr_info *h, int hostno, | 1287 | static void hpsa_scsi_update_entry(struct ctlr_info *h, |
| 1232 | int entry, struct hpsa_scsi_dev_t *new_entry) | 1288 | int entry, struct hpsa_scsi_dev_t *new_entry) |
| 1233 | { | 1289 | { |
| 1234 | int offload_enabled; | 1290 | int offload_enabled; |
| @@ -1276,7 +1332,7 @@ static void hpsa_scsi_update_entry(struct ctlr_info *h, int hostno, | |||
| 1276 | } | 1332 | } |
| 1277 | 1333 | ||
| 1278 | /* Replace an entry from h->dev[] array. */ | 1334 | /* Replace an entry from h->dev[] array. */ |
| 1279 | static void hpsa_scsi_replace_entry(struct ctlr_info *h, int hostno, | 1335 | static void hpsa_scsi_replace_entry(struct ctlr_info *h, |
| 1280 | int entry, struct hpsa_scsi_dev_t *new_entry, | 1336 | int entry, struct hpsa_scsi_dev_t *new_entry, |
| 1281 | struct hpsa_scsi_dev_t *added[], int *nadded, | 1337 | struct hpsa_scsi_dev_t *added[], int *nadded, |
| 1282 | struct hpsa_scsi_dev_t *removed[], int *nremoved) | 1338 | struct hpsa_scsi_dev_t *removed[], int *nremoved) |
| @@ -1304,7 +1360,7 @@ static void hpsa_scsi_replace_entry(struct ctlr_info *h, int hostno, | |||
| 1304 | } | 1360 | } |
| 1305 | 1361 | ||
| 1306 | /* Remove an entry from h->dev[] array. */ | 1362 | /* Remove an entry from h->dev[] array. */ |
| 1307 | static void hpsa_scsi_remove_entry(struct ctlr_info *h, int hostno, int entry, | 1363 | static void hpsa_scsi_remove_entry(struct ctlr_info *h, int entry, |
| 1308 | struct hpsa_scsi_dev_t *removed[], int *nremoved) | 1364 | struct hpsa_scsi_dev_t *removed[], int *nremoved) |
| 1309 | { | 1365 | { |
| 1310 | /* assumes h->devlock is held */ | 1366 | /* assumes h->devlock is held */ |
| @@ -1415,6 +1471,9 @@ static int hpsa_scsi_find_entry(struct hpsa_scsi_dev_t *needle, | |||
| 1415 | #define DEVICE_CHANGED 1 | 1471 | #define DEVICE_CHANGED 1 |
| 1416 | #define DEVICE_SAME 2 | 1472 | #define DEVICE_SAME 2 |
| 1417 | #define DEVICE_UPDATED 3 | 1473 | #define DEVICE_UPDATED 3 |
| 1474 | if (needle == NULL) | ||
| 1475 | return DEVICE_NOT_FOUND; | ||
| 1476 | |||
| 1418 | for (i = 0; i < haystack_size; i++) { | 1477 | for (i = 0; i < haystack_size; i++) { |
| 1419 | if (haystack[i] == NULL) /* previously removed. */ | 1478 | if (haystack[i] == NULL) /* previously removed. */ |
| 1420 | continue; | 1479 | continue; |
| @@ -1577,9 +1636,11 @@ static void hpsa_figure_phys_disk_ptrs(struct ctlr_info *h, | |||
| 1577 | if (!logical_drive->offload_config) | 1636 | if (!logical_drive->offload_config) |
| 1578 | continue; | 1637 | continue; |
| 1579 | for (j = 0; j < ndevices; j++) { | 1638 | for (j = 0; j < ndevices; j++) { |
| 1639 | if (dev[j] == NULL) | ||
| 1640 | continue; | ||
| 1580 | if (dev[j]->devtype != TYPE_DISK) | 1641 | if (dev[j]->devtype != TYPE_DISK) |
| 1581 | continue; | 1642 | continue; |
| 1582 | if (is_logical_dev_addr_mode(dev[j]->scsi3addr)) | 1643 | if (is_logical_device(dev[j])) |
| 1583 | continue; | 1644 | continue; |
| 1584 | if (dev[j]->ioaccel_handle != dd[i].ioaccel_handle) | 1645 | if (dev[j]->ioaccel_handle != dd[i].ioaccel_handle) |
| 1585 | continue; | 1646 | continue; |
| @@ -1620,9 +1681,11 @@ static void hpsa_update_log_drive_phys_drive_ptrs(struct ctlr_info *h, | |||
| 1620 | int i; | 1681 | int i; |
| 1621 | 1682 | ||
| 1622 | for (i = 0; i < ndevices; i++) { | 1683 | for (i = 0; i < ndevices; i++) { |
| 1684 | if (dev[i] == NULL) | ||
| 1685 | continue; | ||
| 1623 | if (dev[i]->devtype != TYPE_DISK) | 1686 | if (dev[i]->devtype != TYPE_DISK) |
| 1624 | continue; | 1687 | continue; |
| 1625 | if (!is_logical_dev_addr_mode(dev[i]->scsi3addr)) | 1688 | if (!is_logical_device(dev[i])) |
| 1626 | continue; | 1689 | continue; |
| 1627 | 1690 | ||
| 1628 | /* | 1691 | /* |
| @@ -1638,7 +1701,50 @@ static void hpsa_update_log_drive_phys_drive_ptrs(struct ctlr_info *h, | |||
| 1638 | } | 1701 | } |
| 1639 | } | 1702 | } |
| 1640 | 1703 | ||
| 1641 | static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno, | 1704 | static int hpsa_add_device(struct ctlr_info *h, struct hpsa_scsi_dev_t *device) |
| 1705 | { | ||
| 1706 | int rc = 0; | ||
| 1707 | |||
| 1708 | if (!h->scsi_host) | ||
| 1709 | return 1; | ||
| 1710 | |||
| 1711 | if (is_logical_device(device)) /* RAID */ | ||
| 1712 | rc = scsi_add_device(h->scsi_host, device->bus, | ||
| 1713 | device->target, device->lun); | ||
| 1714 | else /* HBA */ | ||
| 1715 | rc = hpsa_add_sas_device(h->sas_host, device); | ||
| 1716 | |||
| 1717 | return rc; | ||
| 1718 | } | ||
| 1719 | |||
| 1720 | static void hpsa_remove_device(struct ctlr_info *h, | ||
| 1721 | struct hpsa_scsi_dev_t *device) | ||
| 1722 | { | ||
| 1723 | struct scsi_device *sdev = NULL; | ||
| 1724 | |||
| 1725 | if (!h->scsi_host) | ||
| 1726 | return; | ||
| 1727 | |||
| 1728 | if (is_logical_device(device)) { /* RAID */ | ||
| 1729 | sdev = scsi_device_lookup(h->scsi_host, device->bus, | ||
| 1730 | device->target, device->lun); | ||
| 1731 | if (sdev) { | ||
| 1732 | scsi_remove_device(sdev); | ||
| 1733 | scsi_device_put(sdev); | ||
| 1734 | } else { | ||
| 1735 | /* | ||
| 1736 | * We don't expect to get here. Future commands | ||
| 1737 | * to this device will get a selection timeout as | ||
| 1738 | * if the device were gone. | ||
| 1739 | */ | ||
| 1740 | hpsa_show_dev_msg(KERN_WARNING, h, device, | ||
| 1741 | "didn't find device for removal."); | ||
| 1742 | } | ||
| 1743 | } else /* HBA */ | ||
| 1744 | hpsa_remove_sas_device(device); | ||
| 1745 | } | ||
| 1746 | |||
| 1747 | static void adjust_hpsa_scsi_table(struct ctlr_info *h, | ||
| 1642 | struct hpsa_scsi_dev_t *sd[], int nsds) | 1748 | struct hpsa_scsi_dev_t *sd[], int nsds) |
| 1643 | { | 1749 | { |
| 1644 | /* sd contains scsi3 addresses and devtypes, and inquiry | 1750 | /* sd contains scsi3 addresses and devtypes, and inquiry |
| @@ -1650,7 +1756,15 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno, | |||
| 1650 | unsigned long flags; | 1756 | unsigned long flags; |
| 1651 | struct hpsa_scsi_dev_t **added, **removed; | 1757 | struct hpsa_scsi_dev_t **added, **removed; |
| 1652 | int nadded, nremoved; | 1758 | int nadded, nremoved; |
| 1653 | struct Scsi_Host *sh = NULL; | 1759 | |
| 1760 | /* | ||
| 1761 | * A reset can cause a device status to change | ||
| 1762 | * re-schedule the scan to see what happened. | ||
| 1763 | */ | ||
| 1764 | if (h->reset_in_progress) { | ||
| 1765 | h->drv_req_rescan = 1; | ||
| 1766 | return; | ||
| 1767 | } | ||
| 1654 | 1768 | ||
| 1655 | added = kzalloc(sizeof(*added) * HPSA_MAX_DEVICES, GFP_KERNEL); | 1769 | added = kzalloc(sizeof(*added) * HPSA_MAX_DEVICES, GFP_KERNEL); |
| 1656 | removed = kzalloc(sizeof(*removed) * HPSA_MAX_DEVICES, GFP_KERNEL); | 1770 | removed = kzalloc(sizeof(*removed) * HPSA_MAX_DEVICES, GFP_KERNEL); |
| @@ -1678,19 +1792,18 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno, | |||
| 1678 | device_change = hpsa_scsi_find_entry(csd, sd, nsds, &entry); | 1792 | device_change = hpsa_scsi_find_entry(csd, sd, nsds, &entry); |
| 1679 | if (device_change == DEVICE_NOT_FOUND) { | 1793 | if (device_change == DEVICE_NOT_FOUND) { |
| 1680 | changes++; | 1794 | changes++; |
| 1681 | hpsa_scsi_remove_entry(h, hostno, i, | 1795 | hpsa_scsi_remove_entry(h, i, removed, &nremoved); |
| 1682 | removed, &nremoved); | ||
| 1683 | continue; /* remove ^^^, hence i not incremented */ | 1796 | continue; /* remove ^^^, hence i not incremented */ |
| 1684 | } else if (device_change == DEVICE_CHANGED) { | 1797 | } else if (device_change == DEVICE_CHANGED) { |
| 1685 | changes++; | 1798 | changes++; |
| 1686 | hpsa_scsi_replace_entry(h, hostno, i, sd[entry], | 1799 | hpsa_scsi_replace_entry(h, i, sd[entry], |
| 1687 | added, &nadded, removed, &nremoved); | 1800 | added, &nadded, removed, &nremoved); |
| 1688 | /* Set it to NULL to prevent it from being freed | 1801 | /* Set it to NULL to prevent it from being freed |
| 1689 | * at the bottom of hpsa_update_scsi_devices() | 1802 | * at the bottom of hpsa_update_scsi_devices() |
| 1690 | */ | 1803 | */ |
| 1691 | sd[entry] = NULL; | 1804 | sd[entry] = NULL; |
| 1692 | } else if (device_change == DEVICE_UPDATED) { | 1805 | } else if (device_change == DEVICE_UPDATED) { |
| 1693 | hpsa_scsi_update_entry(h, hostno, i, sd[entry]); | 1806 | hpsa_scsi_update_entry(h, i, sd[entry]); |
| 1694 | } | 1807 | } |
| 1695 | i++; | 1808 | i++; |
| 1696 | } | 1809 | } |
| @@ -1718,8 +1831,7 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno, | |||
| 1718 | h->ndevices, &entry); | 1831 | h->ndevices, &entry); |
| 1719 | if (device_change == DEVICE_NOT_FOUND) { | 1832 | if (device_change == DEVICE_NOT_FOUND) { |
| 1720 | changes++; | 1833 | changes++; |
| 1721 | if (hpsa_scsi_add_entry(h, hostno, sd[i], | 1834 | if (hpsa_scsi_add_entry(h, sd[i], added, &nadded) != 0) |
| 1722 | added, &nadded) != 0) | ||
| 1723 | break; | 1835 | break; |
| 1724 | sd[i] = NULL; /* prevent from being freed later. */ | 1836 | sd[i] = NULL; /* prevent from being freed later. */ |
| 1725 | } else if (device_change == DEVICE_CHANGED) { | 1837 | } else if (device_change == DEVICE_CHANGED) { |
| @@ -1735,8 +1847,11 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno, | |||
| 1735 | /* Now that h->dev[]->phys_disk[] is coherent, we can enable | 1847 | /* Now that h->dev[]->phys_disk[] is coherent, we can enable |
| 1736 | * any logical drives that need it enabled. | 1848 | * any logical drives that need it enabled. |
| 1737 | */ | 1849 | */ |
| 1738 | for (i = 0; i < h->ndevices; i++) | 1850 | for (i = 0; i < h->ndevices; i++) { |
| 1851 | if (h->dev[i] == NULL) | ||
| 1852 | continue; | ||
| 1739 | h->dev[i]->offload_enabled = h->dev[i]->offload_to_be_enabled; | 1853 | h->dev[i]->offload_enabled = h->dev[i]->offload_to_be_enabled; |
| 1854 | } | ||
| 1740 | 1855 | ||
| 1741 | spin_unlock_irqrestore(&h->devlock, flags); | 1856 | spin_unlock_irqrestore(&h->devlock, flags); |
| 1742 | 1857 | ||
| @@ -1755,47 +1870,37 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno, | |||
| 1755 | * (or if there are no changes) scsi_scan_host will do it later the | 1870 | * (or if there are no changes) scsi_scan_host will do it later the |
| 1756 | * first time through. | 1871 | * first time through. |
| 1757 | */ | 1872 | */ |
| 1758 | if (hostno == -1 || !changes) | 1873 | if (!changes) |
| 1759 | goto free_and_out; | 1874 | goto free_and_out; |
| 1760 | 1875 | ||
| 1761 | sh = h->scsi_host; | ||
| 1762 | /* Notify scsi mid layer of any removed devices */ | 1876 | /* Notify scsi mid layer of any removed devices */ |
| 1763 | for (i = 0; i < nremoved; i++) { | 1877 | for (i = 0; i < nremoved; i++) { |
| 1764 | if (removed[i]->expose_state & HPSA_SCSI_ADD) { | 1878 | if (removed[i] == NULL) |
| 1765 | struct scsi_device *sdev = | 1879 | continue; |
| 1766 | scsi_device_lookup(sh, removed[i]->bus, | 1880 | if (removed[i]->expose_device) |
| 1767 | removed[i]->target, removed[i]->lun); | 1881 | hpsa_remove_device(h, removed[i]); |
| 1768 | if (sdev != NULL) { | ||
| 1769 | scsi_remove_device(sdev); | ||
| 1770 | scsi_device_put(sdev); | ||
| 1771 | } else { | ||
| 1772 | /* | ||
| 1773 | * We don't expect to get here. | ||
| 1774 | * future cmds to this device will get selection | ||
| 1775 | * timeout as if the device was gone. | ||
| 1776 | */ | ||
| 1777 | hpsa_show_dev_msg(KERN_WARNING, h, removed[i], | ||
| 1778 | "didn't find device for removal."); | ||
| 1779 | } | ||
| 1780 | } | ||
| 1781 | kfree(removed[i]); | 1882 | kfree(removed[i]); |
| 1782 | removed[i] = NULL; | 1883 | removed[i] = NULL; |
| 1783 | } | 1884 | } |
| 1784 | 1885 | ||
| 1785 | /* Notify scsi mid layer of any added devices */ | 1886 | /* Notify scsi mid layer of any added devices */ |
| 1786 | for (i = 0; i < nadded; i++) { | 1887 | for (i = 0; i < nadded; i++) { |
| 1787 | if (!(added[i]->expose_state & HPSA_SCSI_ADD)) | 1888 | int rc = 0; |
| 1889 | |||
| 1890 | if (added[i] == NULL) | ||
| 1788 | continue; | 1891 | continue; |
| 1789 | if (scsi_add_device(sh, added[i]->bus, | 1892 | if (!(added[i]->expose_device)) |
| 1790 | added[i]->target, added[i]->lun) == 0) | 1893 | continue; |
| 1894 | rc = hpsa_add_device(h, added[i]); | ||
| 1895 | if (!rc) | ||
| 1791 | continue; | 1896 | continue; |
| 1792 | hpsa_show_dev_msg(KERN_WARNING, h, added[i], | 1897 | dev_warn(&h->pdev->dev, |
| 1793 | "addition failed, device not added."); | 1898 | "addition failed %d, device not added.", rc); |
| 1794 | /* now we have to remove it from h->dev, | 1899 | /* now we have to remove it from h->dev, |
| 1795 | * since it didn't get added to scsi mid layer | 1900 | * since it didn't get added to scsi mid layer |
| 1796 | */ | 1901 | */ |
| 1797 | fixup_botched_add(h, added[i]); | 1902 | fixup_botched_add(h, added[i]); |
| 1798 | added[i] = NULL; | 1903 | h->drv_req_rescan = 1; |
| 1799 | } | 1904 | } |
| 1800 | 1905 | ||
| 1801 | free_and_out: | 1906 | free_and_out: |
| @@ -1829,11 +1934,24 @@ static int hpsa_slave_alloc(struct scsi_device *sdev) | |||
| 1829 | 1934 | ||
| 1830 | h = sdev_to_hba(sdev); | 1935 | h = sdev_to_hba(sdev); |
| 1831 | spin_lock_irqsave(&h->devlock, flags); | 1936 | spin_lock_irqsave(&h->devlock, flags); |
| 1832 | sd = lookup_hpsa_scsi_dev(h, sdev_channel(sdev), | 1937 | if (sdev_channel(sdev) == HPSA_PHYSICAL_DEVICE_BUS) { |
| 1833 | sdev_id(sdev), sdev->lun); | 1938 | struct scsi_target *starget; |
| 1834 | if (likely(sd)) { | 1939 | struct sas_rphy *rphy; |
| 1940 | |||
| 1941 | starget = scsi_target(sdev); | ||
| 1942 | rphy = target_to_rphy(starget); | ||
| 1943 | sd = hpsa_find_device_by_sas_rphy(h, rphy); | ||
| 1944 | if (sd) { | ||
| 1945 | sd->target = sdev_id(sdev); | ||
| 1946 | sd->lun = sdev->lun; | ||
| 1947 | } | ||
| 1948 | } else | ||
| 1949 | sd = lookup_hpsa_scsi_dev(h, sdev_channel(sdev), | ||
| 1950 | sdev_id(sdev), sdev->lun); | ||
| 1951 | |||
| 1952 | if (sd && sd->expose_device) { | ||
| 1835 | atomic_set(&sd->ioaccel_cmds_out, 0); | 1953 | atomic_set(&sd->ioaccel_cmds_out, 0); |
| 1836 | sdev->hostdata = (sd->expose_state & HPSA_SCSI_ADD) ? sd : NULL; | 1954 | sdev->hostdata = sd; |
| 1837 | } else | 1955 | } else |
| 1838 | sdev->hostdata = NULL; | 1956 | sdev->hostdata = NULL; |
| 1839 | spin_unlock_irqrestore(&h->devlock, flags); | 1957 | spin_unlock_irqrestore(&h->devlock, flags); |
| @@ -1847,7 +1965,7 @@ static int hpsa_slave_configure(struct scsi_device *sdev) | |||
| 1847 | int queue_depth; | 1965 | int queue_depth; |
| 1848 | 1966 | ||
| 1849 | sd = sdev->hostdata; | 1967 | sd = sdev->hostdata; |
| 1850 | sdev->no_uld_attach = !sd || !(sd->expose_state & HPSA_ULD_ATTACH); | 1968 | sdev->no_uld_attach = !sd || !sd->expose_device; |
| 1851 | 1969 | ||
| 1852 | if (sd) | 1970 | if (sd) |
| 1853 | queue_depth = sd->queue_depth != 0 ? | 1971 | queue_depth = sd->queue_depth != 0 ? |
| @@ -1955,7 +2073,7 @@ static int hpsa_map_ioaccel2_sg_chain_block(struct ctlr_info *h, | |||
| 1955 | u32 chain_size; | 2073 | u32 chain_size; |
| 1956 | 2074 | ||
| 1957 | chain_block = h->ioaccel2_cmd_sg_list[c->cmdindex]; | 2075 | chain_block = h->ioaccel2_cmd_sg_list[c->cmdindex]; |
| 1958 | chain_size = le32_to_cpu(cp->data_len); | 2076 | chain_size = le32_to_cpu(cp->sg[0].length); |
| 1959 | temp64 = pci_map_single(h->pdev, chain_block, chain_size, | 2077 | temp64 = pci_map_single(h->pdev, chain_block, chain_size, |
| 1960 | PCI_DMA_TODEVICE); | 2078 | PCI_DMA_TODEVICE); |
| 1961 | if (dma_mapping_error(&h->pdev->dev, temp64)) { | 2079 | if (dma_mapping_error(&h->pdev->dev, temp64)) { |
| @@ -1976,7 +2094,7 @@ static void hpsa_unmap_ioaccel2_sg_chain_block(struct ctlr_info *h, | |||
| 1976 | 2094 | ||
| 1977 | chain_sg = cp->sg; | 2095 | chain_sg = cp->sg; |
| 1978 | temp64 = le64_to_cpu(chain_sg->address); | 2096 | temp64 = le64_to_cpu(chain_sg->address); |
| 1979 | chain_size = le32_to_cpu(cp->data_len); | 2097 | chain_size = le32_to_cpu(cp->sg[0].length); |
| 1980 | pci_unmap_single(h->pdev, temp64, chain_size, PCI_DMA_TODEVICE); | 2098 | pci_unmap_single(h->pdev, temp64, chain_size, PCI_DMA_TODEVICE); |
| 1981 | } | 2099 | } |
| 1982 | 2100 | ||
| @@ -2210,7 +2328,7 @@ static void process_ioaccel2_completion(struct ctlr_info *h, | |||
| 2210 | * the normal I/O path so the controller can handle whatever's | 2328 | * the normal I/O path so the controller can handle whatever's |
| 2211 | * wrong. | 2329 | * wrong. |
| 2212 | */ | 2330 | */ |
| 2213 | if (is_logical_dev_addr_mode(dev->scsi3addr) && | 2331 | if (is_logical_device(dev) && |
| 2214 | c2->error_data.serv_response == | 2332 | c2->error_data.serv_response == |
| 2215 | IOACCEL2_SERV_RESPONSE_FAILURE) { | 2333 | IOACCEL2_SERV_RESPONSE_FAILURE) { |
| 2216 | if (c2->error_data.status == | 2334 | if (c2->error_data.status == |
| @@ -2330,7 +2448,7 @@ static void complete_scsi_command(struct CommandList *cp) | |||
| 2330 | * the normal I/O path so the controller can handle whatever's | 2448 | * the normal I/O path so the controller can handle whatever's |
| 2331 | * wrong. | 2449 | * wrong. |
| 2332 | */ | 2450 | */ |
| 2333 | if (is_logical_dev_addr_mode(dev->scsi3addr)) { | 2451 | if (is_logical_device(dev)) { |
| 2334 | if (ei->CommandStatus == CMD_IOACCEL_DISABLED) | 2452 | if (ei->CommandStatus == CMD_IOACCEL_DISABLED) |
| 2335 | dev->offload_enabled = 0; | 2453 | dev->offload_enabled = 0; |
| 2336 | return hpsa_retry_cmd(h, cp); | 2454 | return hpsa_retry_cmd(h, cp); |
| @@ -2709,9 +2827,8 @@ static int hpsa_send_reset(struct ctlr_info *h, unsigned char *scsi3addr, | |||
| 2709 | 2827 | ||
| 2710 | 2828 | ||
| 2711 | /* fill_cmd can't fail here, no data buffer to map. */ | 2829 | /* fill_cmd can't fail here, no data buffer to map. */ |
| 2712 | (void) fill_cmd(c, HPSA_DEVICE_RESET_MSG, h, NULL, 0, 0, | 2830 | (void) fill_cmd(c, reset_type, h, NULL, 0, 0, |
| 2713 | scsi3addr, TYPE_MSG); | 2831 | scsi3addr, TYPE_MSG); |
| 2714 | c->Request.CDB[1] = reset_type; /* fill_cmd defaults to LUN reset */ | ||
| 2715 | rc = hpsa_scsi_do_simple_cmd(h, c, reply_queue, NO_TIMEOUT); | 2832 | rc = hpsa_scsi_do_simple_cmd(h, c, reply_queue, NO_TIMEOUT); |
| 2716 | if (rc) { | 2833 | if (rc) { |
| 2717 | dev_warn(&h->pdev->dev, "Failed to send reset command\n"); | 2834 | dev_warn(&h->pdev->dev, "Failed to send reset command\n"); |
| @@ -2984,6 +3101,66 @@ out: | |||
| 2984 | return rc; | 3101 | return rc; |
| 2985 | } | 3102 | } |
| 2986 | 3103 | ||
| 3104 | static int hpsa_bmic_sense_subsystem_information(struct ctlr_info *h, | ||
| 3105 | unsigned char scsi3addr[], u16 bmic_device_index, | ||
| 3106 | struct bmic_sense_subsystem_info *buf, size_t bufsize) | ||
| 3107 | { | ||
| 3108 | int rc = IO_OK; | ||
| 3109 | struct CommandList *c; | ||
| 3110 | struct ErrorInfo *ei; | ||
| 3111 | |||
| 3112 | c = cmd_alloc(h); | ||
| 3113 | |||
| 3114 | rc = fill_cmd(c, BMIC_SENSE_SUBSYSTEM_INFORMATION, h, buf, bufsize, | ||
| 3115 | 0, RAID_CTLR_LUNID, TYPE_CMD); | ||
| 3116 | if (rc) | ||
| 3117 | goto out; | ||
| 3118 | |||
| 3119 | c->Request.CDB[2] = bmic_device_index & 0xff; | ||
| 3120 | c->Request.CDB[9] = (bmic_device_index >> 8) & 0xff; | ||
| 3121 | |||
| 3122 | rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, | ||
| 3123 | PCI_DMA_FROMDEVICE, NO_TIMEOUT); | ||
| 3124 | if (rc) | ||
| 3125 | goto out; | ||
| 3126 | ei = c->err_info; | ||
| 3127 | if (ei->CommandStatus != 0 && ei->CommandStatus != CMD_DATA_UNDERRUN) { | ||
| 3128 | hpsa_scsi_interpret_error(h, c); | ||
| 3129 | rc = -1; | ||
| 3130 | } | ||
| 3131 | out: | ||
| 3132 | cmd_free(h, c); | ||
| 3133 | return rc; | ||
| 3134 | } | ||
| 3135 | |||
| 3136 | static int hpsa_bmic_id_controller(struct ctlr_info *h, | ||
| 3137 | struct bmic_identify_controller *buf, size_t bufsize) | ||
| 3138 | { | ||
| 3139 | int rc = IO_OK; | ||
| 3140 | struct CommandList *c; | ||
| 3141 | struct ErrorInfo *ei; | ||
| 3142 | |||
| 3143 | c = cmd_alloc(h); | ||
| 3144 | |||
| 3145 | rc = fill_cmd(c, BMIC_IDENTIFY_CONTROLLER, h, buf, bufsize, | ||
| 3146 | 0, RAID_CTLR_LUNID, TYPE_CMD); | ||
| 3147 | if (rc) | ||
| 3148 | goto out; | ||
| 3149 | |||
| 3150 | rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, | ||
| 3151 | PCI_DMA_FROMDEVICE, NO_TIMEOUT); | ||
| 3152 | if (rc) | ||
| 3153 | goto out; | ||
| 3154 | ei = c->err_info; | ||
| 3155 | if (ei->CommandStatus != 0 && ei->CommandStatus != CMD_DATA_UNDERRUN) { | ||
| 3156 | hpsa_scsi_interpret_error(h, c); | ||
| 3157 | rc = -1; | ||
| 3158 | } | ||
| 3159 | out: | ||
| 3160 | cmd_free(h, c); | ||
| 3161 | return rc; | ||
| 3162 | } | ||
| 3163 | |||
| 2987 | static int hpsa_bmic_id_physical_device(struct ctlr_info *h, | 3164 | static int hpsa_bmic_id_physical_device(struct ctlr_info *h, |
| 2988 | unsigned char scsi3addr[], u16 bmic_device_index, | 3165 | unsigned char scsi3addr[], u16 bmic_device_index, |
| 2989 | struct bmic_identify_physical_device *buf, size_t bufsize) | 3166 | struct bmic_identify_physical_device *buf, size_t bufsize) |
| @@ -3010,9 +3187,71 @@ static int hpsa_bmic_id_physical_device(struct ctlr_info *h, | |||
| 3010 | } | 3187 | } |
| 3011 | out: | 3188 | out: |
| 3012 | cmd_free(h, c); | 3189 | cmd_free(h, c); |
| 3190 | |||
| 3013 | return rc; | 3191 | return rc; |
| 3014 | } | 3192 | } |
| 3015 | 3193 | ||
| 3194 | static u64 hpsa_get_sas_address_from_report_physical(struct ctlr_info *h, | ||
| 3195 | unsigned char *scsi3addr) | ||
| 3196 | { | ||
| 3197 | struct ReportExtendedLUNdata *physdev; | ||
| 3198 | u32 nphysicals; | ||
| 3199 | u64 sa = 0; | ||
| 3200 | int i; | ||
| 3201 | |||
| 3202 | physdev = kzalloc(sizeof(*physdev), GFP_KERNEL); | ||
| 3203 | if (!physdev) | ||
| 3204 | return 0; | ||
| 3205 | |||
| 3206 | if (hpsa_scsi_do_report_phys_luns(h, physdev, sizeof(*physdev))) { | ||
| 3207 | dev_err(&h->pdev->dev, "report physical LUNs failed.\n"); | ||
| 3208 | kfree(physdev); | ||
| 3209 | return 0; | ||
| 3210 | } | ||
| 3211 | nphysicals = get_unaligned_be32(physdev->LUNListLength) / 24; | ||
| 3212 | |||
| 3213 | for (i = 0; i < nphysicals; i++) | ||
| 3214 | if (!memcmp(&physdev->LUN[i].lunid[0], scsi3addr, 8)) { | ||
| 3215 | sa = get_unaligned_be64(&physdev->LUN[i].wwid[0]); | ||
| 3216 | break; | ||
| 3217 | } | ||
| 3218 | |||
| 3219 | kfree(physdev); | ||
| 3220 | |||
| 3221 | return sa; | ||
| 3222 | } | ||
| 3223 | |||
| 3224 | static void hpsa_get_sas_address(struct ctlr_info *h, unsigned char *scsi3addr, | ||
| 3225 | struct hpsa_scsi_dev_t *dev) | ||
| 3226 | { | ||
| 3227 | int rc; | ||
| 3228 | u64 sa = 0; | ||
| 3229 | |||
| 3230 | if (is_hba_lunid(scsi3addr)) { | ||
| 3231 | struct bmic_sense_subsystem_info *ssi; | ||
| 3232 | |||
| 3233 | ssi = kzalloc(sizeof(*ssi), GFP_KERNEL); | ||
| 3234 | if (ssi == NULL) { | ||
| 3235 | dev_warn(&h->pdev->dev, | ||
| 3236 | "%s: out of memory\n", __func__); | ||
| 3237 | return; | ||
| 3238 | } | ||
| 3239 | |||
| 3240 | rc = hpsa_bmic_sense_subsystem_information(h, | ||
| 3241 | scsi3addr, 0, ssi, sizeof(*ssi)); | ||
| 3242 | if (rc == 0) { | ||
| 3243 | sa = get_unaligned_be64(ssi->primary_world_wide_id); | ||
| 3244 | h->sas_address = sa; | ||
| 3245 | } | ||
| 3246 | |||
| 3247 | kfree(ssi); | ||
| 3248 | } else | ||
| 3249 | sa = hpsa_get_sas_address_from_report_physical(h, scsi3addr); | ||
| 3250 | |||
| 3251 | dev->sas_address = sa; | ||
| 3252 | } | ||
| 3253 | |||
| 3254 | /* Get a device id from inquiry page 0x83 */ | ||
| 3016 | static int hpsa_vpd_page_supported(struct ctlr_info *h, | 3255 | static int hpsa_vpd_page_supported(struct ctlr_info *h, |
| 3017 | unsigned char scsi3addr[], u8 page) | 3256 | unsigned char scsi3addr[], u8 page) |
| 3018 | { | 3257 | { |
| @@ -3097,7 +3336,7 @@ out: | |||
| 3097 | 3336 | ||
| 3098 | /* Get the device id from inquiry page 0x83 */ | 3337 | /* Get the device id from inquiry page 0x83 */ |
| 3099 | static int hpsa_get_device_id(struct ctlr_info *h, unsigned char *scsi3addr, | 3338 | static int hpsa_get_device_id(struct ctlr_info *h, unsigned char *scsi3addr, |
| 3100 | unsigned char *device_id, int buflen) | 3339 | unsigned char *device_id, int index, int buflen) |
| 3101 | { | 3340 | { |
| 3102 | int rc; | 3341 | int rc; |
| 3103 | unsigned char *buf; | 3342 | unsigned char *buf; |
| @@ -3109,8 +3348,10 @@ static int hpsa_get_device_id(struct ctlr_info *h, unsigned char *scsi3addr, | |||
| 3109 | return -ENOMEM; | 3348 | return -ENOMEM; |
| 3110 | rc = hpsa_scsi_do_inquiry(h, scsi3addr, VPD_PAGE | 0x83, buf, 64); | 3349 | rc = hpsa_scsi_do_inquiry(h, scsi3addr, VPD_PAGE | 0x83, buf, 64); |
| 3111 | if (rc == 0) | 3350 | if (rc == 0) |
| 3112 | memcpy(device_id, &buf[8], buflen); | 3351 | memcpy(device_id, &buf[index], buflen); |
| 3352 | |||
| 3113 | kfree(buf); | 3353 | kfree(buf); |
| 3354 | |||
| 3114 | return rc != 0; | 3355 | return rc != 0; |
| 3115 | } | 3356 | } |
| 3116 | 3357 | ||
| @@ -3339,6 +3580,18 @@ static int hpsa_device_supports_aborts(struct ctlr_info *h, | |||
| 3339 | return rc; | 3580 | return rc; |
| 3340 | } | 3581 | } |
| 3341 | 3582 | ||
| 3583 | static void sanitize_inquiry_string(unsigned char *s, int len) | ||
| 3584 | { | ||
| 3585 | bool terminated = false; | ||
| 3586 | |||
| 3587 | for (; len > 0; (--len, ++s)) { | ||
| 3588 | if (*s == 0) | ||
| 3589 | terminated = true; | ||
| 3590 | if (terminated || *s < 0x20 || *s > 0x7e) | ||
| 3591 | *s = ' '; | ||
| 3592 | } | ||
| 3593 | } | ||
| 3594 | |||
| 3342 | static int hpsa_update_device_info(struct ctlr_info *h, | 3595 | static int hpsa_update_device_info(struct ctlr_info *h, |
| 3343 | unsigned char scsi3addr[], struct hpsa_scsi_dev_t *this_device, | 3596 | unsigned char scsi3addr[], struct hpsa_scsi_dev_t *this_device, |
| 3344 | unsigned char *is_OBDR_device) | 3597 | unsigned char *is_OBDR_device) |
| @@ -3351,10 +3604,13 @@ static int hpsa_update_device_info(struct ctlr_info *h, | |||
| 3351 | 3604 | ||
| 3352 | unsigned char *inq_buff; | 3605 | unsigned char *inq_buff; |
| 3353 | unsigned char *obdr_sig; | 3606 | unsigned char *obdr_sig; |
| 3607 | int rc = 0; | ||
| 3354 | 3608 | ||
| 3355 | inq_buff = kzalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL); | 3609 | inq_buff = kzalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL); |
| 3356 | if (!inq_buff) | 3610 | if (!inq_buff) { |
| 3611 | rc = -ENOMEM; | ||
| 3357 | goto bail_out; | 3612 | goto bail_out; |
| 3613 | } | ||
| 3358 | 3614 | ||
| 3359 | /* Do an inquiry to the device to see what it is. */ | 3615 | /* Do an inquiry to the device to see what it is. */ |
| 3360 | if (hpsa_scsi_do_inquiry(h, scsi3addr, 0, inq_buff, | 3616 | if (hpsa_scsi_do_inquiry(h, scsi3addr, 0, inq_buff, |
| @@ -3362,9 +3618,13 @@ static int hpsa_update_device_info(struct ctlr_info *h, | |||
| 3362 | /* Inquiry failed (msg printed already) */ | 3618 | /* Inquiry failed (msg printed already) */ |
| 3363 | dev_err(&h->pdev->dev, | 3619 | dev_err(&h->pdev->dev, |
| 3364 | "hpsa_update_device_info: inquiry failed\n"); | 3620 | "hpsa_update_device_info: inquiry failed\n"); |
| 3621 | rc = -EIO; | ||
| 3365 | goto bail_out; | 3622 | goto bail_out; |
| 3366 | } | 3623 | } |
| 3367 | 3624 | ||
| 3625 | sanitize_inquiry_string(&inq_buff[8], 8); | ||
| 3626 | sanitize_inquiry_string(&inq_buff[16], 16); | ||
| 3627 | |||
| 3368 | this_device->devtype = (inq_buff[0] & 0x1f); | 3628 | this_device->devtype = (inq_buff[0] & 0x1f); |
| 3369 | memcpy(this_device->scsi3addr, scsi3addr, 8); | 3629 | memcpy(this_device->scsi3addr, scsi3addr, 8); |
| 3370 | memcpy(this_device->vendor, &inq_buff[8], | 3630 | memcpy(this_device->vendor, &inq_buff[8], |
| @@ -3373,7 +3633,7 @@ static int hpsa_update_device_info(struct ctlr_info *h, | |||
| 3373 | sizeof(this_device->model)); | 3633 | sizeof(this_device->model)); |
| 3374 | memset(this_device->device_id, 0, | 3634 | memset(this_device->device_id, 0, |
| 3375 | sizeof(this_device->device_id)); | 3635 | sizeof(this_device->device_id)); |
| 3376 | hpsa_get_device_id(h, scsi3addr, this_device->device_id, | 3636 | hpsa_get_device_id(h, scsi3addr, this_device->device_id, 8, |
| 3377 | sizeof(this_device->device_id)); | 3637 | sizeof(this_device->device_id)); |
| 3378 | 3638 | ||
| 3379 | if (this_device->devtype == TYPE_DISK && | 3639 | if (this_device->devtype == TYPE_DISK && |
| @@ -3411,7 +3671,7 @@ static int hpsa_update_device_info(struct ctlr_info *h, | |||
| 3411 | 3671 | ||
| 3412 | bail_out: | 3672 | bail_out: |
| 3413 | kfree(inq_buff); | 3673 | kfree(inq_buff); |
| 3414 | return 1; | 3674 | return rc; |
| 3415 | } | 3675 | } |
| 3416 | 3676 | ||
| 3417 | static void hpsa_update_device_supports_aborts(struct ctlr_info *h, | 3677 | static void hpsa_update_device_supports_aborts(struct ctlr_info *h, |
| @@ -3439,115 +3699,39 @@ static void hpsa_update_device_supports_aborts(struct ctlr_info *h, | |||
| 3439 | } | 3699 | } |
| 3440 | } | 3700 | } |
| 3441 | 3701 | ||
| 3442 | static unsigned char *ext_target_model[] = { | 3702 | /* |
| 3443 | "MSA2012", | 3703 | * Helper function to assign bus, target, lun mapping of devices. |
| 3444 | "MSA2024", | ||
| 3445 | "MSA2312", | ||
| 3446 | "MSA2324", | ||
| 3447 | "P2000 G3 SAS", | ||
| 3448 | "MSA 2040 SAS", | ||
| 3449 | NULL, | ||
| 3450 | }; | ||
| 3451 | |||
| 3452 | static int is_ext_target(struct ctlr_info *h, struct hpsa_scsi_dev_t *device) | ||
| 3453 | { | ||
| 3454 | int i; | ||
| 3455 | |||
| 3456 | for (i = 0; ext_target_model[i]; i++) | ||
| 3457 | if (strncmp(device->model, ext_target_model[i], | ||
| 3458 | strlen(ext_target_model[i])) == 0) | ||
| 3459 | return 1; | ||
| 3460 | return 0; | ||
| 3461 | } | ||
| 3462 | |||
| 3463 | /* Helper function to assign bus, target, lun mapping of devices. | ||
| 3464 | * Puts non-external target logical volumes on bus 0, external target logical | ||
| 3465 | * volumes on bus 1, physical devices on bus 2. and the hba on bus 3. | ||
| 3466 | * Logical drive target and lun are assigned at this time, but | 3704 | * Logical drive target and lun are assigned at this time, but |
| 3467 | * physical device lun and target assignment are deferred (assigned | 3705 | * physical device lun and target assignment are deferred (assigned |
| 3468 | * in hpsa_find_target_lun, called by hpsa_scsi_add_entry.) | 3706 | * in hpsa_find_target_lun, called by hpsa_scsi_add_entry.) |
| 3469 | */ | 3707 | */ |
| 3470 | static void figure_bus_target_lun(struct ctlr_info *h, | 3708 | static void figure_bus_target_lun(struct ctlr_info *h, |
| 3471 | u8 *lunaddrbytes, struct hpsa_scsi_dev_t *device) | 3709 | u8 *lunaddrbytes, struct hpsa_scsi_dev_t *device) |
| 3472 | { | 3710 | { |
| 3473 | u32 lunid = le32_to_cpu(*((__le32 *) lunaddrbytes)); | 3711 | u32 lunid = get_unaligned_le32(lunaddrbytes); |
| 3474 | 3712 | ||
| 3475 | if (!is_logical_dev_addr_mode(lunaddrbytes)) { | 3713 | if (!is_logical_dev_addr_mode(lunaddrbytes)) { |
| 3476 | /* physical device, target and lun filled in later */ | 3714 | /* physical device, target and lun filled in later */ |
| 3477 | if (is_hba_lunid(lunaddrbytes)) | 3715 | if (is_hba_lunid(lunaddrbytes)) |
| 3478 | hpsa_set_bus_target_lun(device, 3, 0, lunid & 0x3fff); | 3716 | hpsa_set_bus_target_lun(device, |
| 3717 | HPSA_HBA_BUS, 0, lunid & 0x3fff); | ||
| 3479 | else | 3718 | else |
| 3480 | /* defer target, lun assignment for physical devices */ | 3719 | /* defer target, lun assignment for physical devices */ |
| 3481 | hpsa_set_bus_target_lun(device, 2, -1, -1); | 3720 | hpsa_set_bus_target_lun(device, |
| 3721 | HPSA_PHYSICAL_DEVICE_BUS, -1, -1); | ||
| 3482 | return; | 3722 | return; |
| 3483 | } | 3723 | } |
| 3484 | /* It's a logical device */ | 3724 | /* It's a logical device */ |
| 3485 | if (is_ext_target(h, device)) { | 3725 | if (device->external) { |
| 3486 | /* external target way, put logicals on bus 1 | ||
| 3487 | * and match target/lun numbers box | ||
| 3488 | * reports, other smart array, bus 0, target 0, match lunid | ||
| 3489 | */ | ||
| 3490 | hpsa_set_bus_target_lun(device, | 3726 | hpsa_set_bus_target_lun(device, |
| 3491 | 1, (lunid >> 16) & 0x3fff, lunid & 0x00ff); | 3727 | HPSA_EXTERNAL_RAID_VOLUME_BUS, (lunid >> 16) & 0x3fff, |
| 3728 | lunid & 0x00ff); | ||
| 3492 | return; | 3729 | return; |
| 3493 | } | 3730 | } |
| 3494 | hpsa_set_bus_target_lun(device, 0, 0, lunid & 0x3fff); | 3731 | hpsa_set_bus_target_lun(device, HPSA_RAID_VOLUME_BUS, |
| 3732 | 0, lunid & 0x3fff); | ||
| 3495 | } | 3733 | } |
| 3496 | 3734 | ||
| 3497 | /* | ||
| 3498 | * If there is no lun 0 on a target, linux won't find any devices. | ||
| 3499 | * For the external targets (arrays), we have to manually detect the enclosure | ||
| 3500 | * which is at lun zero, as CCISS_REPORT_PHYSICAL_LUNS doesn't report | ||
| 3501 | * it for some reason. *tmpdevice is the target we're adding, | ||
| 3502 | * this_device is a pointer into the current element of currentsd[] | ||
| 3503 | * that we're building up in update_scsi_devices(), below. | ||
| 3504 | * lunzerobits is a bitmap that tracks which targets already have a | ||
| 3505 | * lun 0 assigned. | ||
| 3506 | * Returns 1 if an enclosure was added, 0 if not. | ||
| 3507 | */ | ||
| 3508 | static int add_ext_target_dev(struct ctlr_info *h, | ||
| 3509 | struct hpsa_scsi_dev_t *tmpdevice, | ||
| 3510 | struct hpsa_scsi_dev_t *this_device, u8 *lunaddrbytes, | ||
| 3511 | unsigned long lunzerobits[], int *n_ext_target_devs) | ||
| 3512 | { | ||
| 3513 | unsigned char scsi3addr[8]; | ||
| 3514 | |||
| 3515 | if (test_bit(tmpdevice->target, lunzerobits)) | ||
| 3516 | return 0; /* There is already a lun 0 on this target. */ | ||
| 3517 | |||
| 3518 | if (!is_logical_dev_addr_mode(lunaddrbytes)) | ||
| 3519 | return 0; /* It's the logical targets that may lack lun 0. */ | ||
| 3520 | |||
| 3521 | if (!is_ext_target(h, tmpdevice)) | ||
| 3522 | return 0; /* Only external target devices have this problem. */ | ||
| 3523 | |||
| 3524 | if (tmpdevice->lun == 0) /* if lun is 0, then we have a lun 0. */ | ||
| 3525 | return 0; | ||
| 3526 | |||
| 3527 | memset(scsi3addr, 0, 8); | ||
| 3528 | scsi3addr[3] = tmpdevice->target; | ||
| 3529 | if (is_hba_lunid(scsi3addr)) | ||
| 3530 | return 0; /* Don't add the RAID controller here. */ | ||
| 3531 | |||
| 3532 | if (is_scsi_rev_5(h)) | ||
| 3533 | return 0; /* p1210m doesn't need to do this. */ | ||
| 3534 | |||
| 3535 | if (*n_ext_target_devs >= MAX_EXT_TARGETS) { | ||
| 3536 | dev_warn(&h->pdev->dev, "Maximum number of external " | ||
| 3537 | "target devices exceeded. Check your hardware " | ||
| 3538 | "configuration."); | ||
| 3539 | return 0; | ||
| 3540 | } | ||
| 3541 | |||
| 3542 | if (hpsa_update_device_info(h, scsi3addr, this_device, NULL)) | ||
| 3543 | return 0; | ||
| 3544 | (*n_ext_target_devs)++; | ||
| 3545 | hpsa_set_bus_target_lun(this_device, | ||
| 3546 | tmpdevice->bus, tmpdevice->target, 0); | ||
| 3547 | hpsa_update_device_supports_aborts(h, this_device, scsi3addr); | ||
| 3548 | set_bit(tmpdevice->target, lunzerobits); | ||
| 3549 | return 1; | ||
| 3550 | } | ||
| 3551 | 3735 | ||
| 3552 | /* | 3736 | /* |
| 3553 | * Get address of physical disk used for an ioaccel2 mode command: | 3737 | * Get address of physical disk used for an ioaccel2 mode command: |
| @@ -3577,6 +3761,27 @@ static int hpsa_get_pdisk_of_ioaccel2(struct ctlr_info *h, | |||
| 3577 | return 0; | 3761 | return 0; |
| 3578 | } | 3762 | } |
| 3579 | 3763 | ||
| 3764 | static int figure_external_status(struct ctlr_info *h, int raid_ctlr_position, | ||
| 3765 | int i, int nphysicals, int nlocal_logicals) | ||
| 3766 | { | ||
| 3767 | /* In report logicals, local logicals are listed first, | ||
| 3768 | * then any externals. | ||
| 3769 | */ | ||
| 3770 | int logicals_start = nphysicals + (raid_ctlr_position == 0); | ||
| 3771 | |||
| 3772 | if (i == raid_ctlr_position) | ||
| 3773 | return 0; | ||
| 3774 | |||
| 3775 | if (i < logicals_start) | ||
| 3776 | return 0; | ||
| 3777 | |||
| 3778 | /* i is in logicals range, but still within local logicals */ | ||
| 3779 | if ((i - nphysicals - (raid_ctlr_position == 0)) < nlocal_logicals) | ||
| 3780 | return 0; | ||
| 3781 | |||
| 3782 | return 1; /* it's an external lun */ | ||
| 3783 | } | ||
| 3784 | |||
| 3580 | /* | 3785 | /* |
| 3581 | * Do CISS_REPORT_PHYS and CISS_REPORT_LOG. Data is returned in physdev, | 3786 | * Do CISS_REPORT_PHYS and CISS_REPORT_LOG. Data is returned in physdev, |
| 3582 | * logdev. The number of luns in physdev and logdev are returned in | 3787 | * logdev. The number of luns in physdev and logdev are returned in |
| @@ -3650,19 +3855,18 @@ static u8 *figure_lunaddrbytes(struct ctlr_info *h, int raid_ctlr_position, | |||
| 3650 | /* get physical drive ioaccel handle and queue depth */ | 3855 | /* get physical drive ioaccel handle and queue depth */ |
| 3651 | static void hpsa_get_ioaccel_drive_info(struct ctlr_info *h, | 3856 | static void hpsa_get_ioaccel_drive_info(struct ctlr_info *h, |
| 3652 | struct hpsa_scsi_dev_t *dev, | 3857 | struct hpsa_scsi_dev_t *dev, |
| 3653 | u8 *lunaddrbytes, | 3858 | struct ReportExtendedLUNdata *rlep, int rle_index, |
| 3654 | struct bmic_identify_physical_device *id_phys) | 3859 | struct bmic_identify_physical_device *id_phys) |
| 3655 | { | 3860 | { |
| 3656 | int rc; | 3861 | int rc; |
| 3657 | struct ext_report_lun_entry *rle = | 3862 | struct ext_report_lun_entry *rle = &rlep->LUN[rle_index]; |
| 3658 | (struct ext_report_lun_entry *) lunaddrbytes; | ||
| 3659 | 3863 | ||
| 3660 | dev->ioaccel_handle = rle->ioaccel_handle; | 3864 | dev->ioaccel_handle = rle->ioaccel_handle; |
| 3661 | if (PHYS_IOACCEL(lunaddrbytes) && dev->ioaccel_handle) | 3865 | if ((rle->device_flags & 0x08) && dev->ioaccel_handle) |
| 3662 | dev->hba_ioaccel_enabled = 1; | 3866 | dev->hba_ioaccel_enabled = 1; |
| 3663 | memset(id_phys, 0, sizeof(*id_phys)); | 3867 | memset(id_phys, 0, sizeof(*id_phys)); |
| 3664 | rc = hpsa_bmic_id_physical_device(h, lunaddrbytes, | 3868 | rc = hpsa_bmic_id_physical_device(h, &rle->lunid[0], |
| 3665 | GET_BMIC_DRIVE_NUMBER(lunaddrbytes), id_phys, | 3869 | GET_BMIC_DRIVE_NUMBER(&rle->lunid[0]), id_phys, |
| 3666 | sizeof(*id_phys)); | 3870 | sizeof(*id_phys)); |
| 3667 | if (!rc) | 3871 | if (!rc) |
| 3668 | /* Reserve space for FW operations */ | 3872 | /* Reserve space for FW operations */ |
| @@ -3673,16 +3877,15 @@ static void hpsa_get_ioaccel_drive_info(struct ctlr_info *h, | |||
| 3673 | DRIVE_CMDS_RESERVED_FOR_FW; | 3877 | DRIVE_CMDS_RESERVED_FOR_FW; |
| 3674 | else | 3878 | else |
| 3675 | dev->queue_depth = DRIVE_QUEUE_DEPTH; /* conservative */ | 3879 | dev->queue_depth = DRIVE_QUEUE_DEPTH; /* conservative */ |
| 3676 | atomic_set(&dev->ioaccel_cmds_out, 0); | ||
| 3677 | atomic_set(&dev->reset_cmds_out, 0); | ||
| 3678 | } | 3880 | } |
| 3679 | 3881 | ||
| 3680 | static void hpsa_get_path_info(struct hpsa_scsi_dev_t *this_device, | 3882 | static void hpsa_get_path_info(struct hpsa_scsi_dev_t *this_device, |
| 3681 | u8 *lunaddrbytes, | 3883 | struct ReportExtendedLUNdata *rlep, int rle_index, |
| 3682 | struct bmic_identify_physical_device *id_phys) | 3884 | struct bmic_identify_physical_device *id_phys) |
| 3683 | { | 3885 | { |
| 3684 | if (PHYS_IOACCEL(lunaddrbytes) | 3886 | struct ext_report_lun_entry *rle = &rlep->LUN[rle_index]; |
| 3685 | && this_device->ioaccel_handle) | 3887 | |
| 3888 | if ((rle->device_flags & 0x08) && this_device->ioaccel_handle) | ||
| 3686 | this_device->hba_ioaccel_enabled = 1; | 3889 | this_device->hba_ioaccel_enabled = 1; |
| 3687 | 3890 | ||
| 3688 | memcpy(&this_device->active_path_index, | 3891 | memcpy(&this_device->active_path_index, |
| @@ -3702,7 +3905,33 @@ static void hpsa_get_path_info(struct hpsa_scsi_dev_t *this_device, | |||
| 3702 | sizeof(this_device->bay)); | 3905 | sizeof(this_device->bay)); |
| 3703 | } | 3906 | } |
| 3704 | 3907 | ||
| 3705 | static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno) | 3908 | /* get number of local logical disks. */ |
| 3909 | static int hpsa_set_local_logical_count(struct ctlr_info *h, | ||
| 3910 | struct bmic_identify_controller *id_ctlr, | ||
| 3911 | u32 *nlocals) | ||
| 3912 | { | ||
| 3913 | int rc; | ||
| 3914 | |||
| 3915 | if (!id_ctlr) { | ||
| 3916 | dev_warn(&h->pdev->dev, "%s: id_ctlr buffer is NULL.\n", | ||
| 3917 | __func__); | ||
| 3918 | return -ENOMEM; | ||
| 3919 | } | ||
| 3920 | memset(id_ctlr, 0, sizeof(*id_ctlr)); | ||
| 3921 | rc = hpsa_bmic_id_controller(h, id_ctlr, sizeof(*id_ctlr)); | ||
| 3922 | if (!rc) | ||
| 3923 | if (id_ctlr->configured_logical_drive_count < 256) | ||
| 3924 | *nlocals = id_ctlr->configured_logical_drive_count; | ||
| 3925 | else | ||
| 3926 | *nlocals = le16_to_cpu( | ||
| 3927 | id_ctlr->extended_logical_unit_count); | ||
| 3928 | else | ||
| 3929 | *nlocals = -1; | ||
| 3930 | return rc; | ||
| 3931 | } | ||
| 3932 | |||
| 3933 | |||
| 3934 | static void hpsa_update_scsi_devices(struct ctlr_info *h) | ||
| 3706 | { | 3935 | { |
| 3707 | /* the idea here is we could get notified | 3936 | /* the idea here is we could get notified |
| 3708 | * that some devices have changed, so we do a report | 3937 | * that some devices have changed, so we do a report |
| @@ -3717,13 +3946,16 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno) | |||
| 3717 | struct ReportExtendedLUNdata *physdev_list = NULL; | 3946 | struct ReportExtendedLUNdata *physdev_list = NULL; |
| 3718 | struct ReportLUNdata *logdev_list = NULL; | 3947 | struct ReportLUNdata *logdev_list = NULL; |
| 3719 | struct bmic_identify_physical_device *id_phys = NULL; | 3948 | struct bmic_identify_physical_device *id_phys = NULL; |
| 3949 | struct bmic_identify_controller *id_ctlr = NULL; | ||
| 3720 | u32 nphysicals = 0; | 3950 | u32 nphysicals = 0; |
| 3721 | u32 nlogicals = 0; | 3951 | u32 nlogicals = 0; |
| 3952 | u32 nlocal_logicals = 0; | ||
| 3722 | u32 ndev_allocated = 0; | 3953 | u32 ndev_allocated = 0; |
| 3723 | struct hpsa_scsi_dev_t **currentsd, *this_device, *tmpdevice; | 3954 | struct hpsa_scsi_dev_t **currentsd, *this_device, *tmpdevice; |
| 3724 | int ncurrent = 0; | 3955 | int ncurrent = 0; |
| 3725 | int i, n_ext_target_devs, ndevs_to_allocate; | 3956 | int i, n_ext_target_devs, ndevs_to_allocate; |
| 3726 | int raid_ctlr_position; | 3957 | int raid_ctlr_position; |
| 3958 | bool physical_device; | ||
| 3727 | DECLARE_BITMAP(lunzerobits, MAX_EXT_TARGETS); | 3959 | DECLARE_BITMAP(lunzerobits, MAX_EXT_TARGETS); |
| 3728 | 3960 | ||
| 3729 | currentsd = kzalloc(sizeof(*currentsd) * HPSA_MAX_DEVICES, GFP_KERNEL); | 3961 | currentsd = kzalloc(sizeof(*currentsd) * HPSA_MAX_DEVICES, GFP_KERNEL); |
| @@ -3731,17 +3963,29 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno) | |||
| 3731 | logdev_list = kzalloc(sizeof(*logdev_list), GFP_KERNEL); | 3963 | logdev_list = kzalloc(sizeof(*logdev_list), GFP_KERNEL); |
| 3732 | tmpdevice = kzalloc(sizeof(*tmpdevice), GFP_KERNEL); | 3964 | tmpdevice = kzalloc(sizeof(*tmpdevice), GFP_KERNEL); |
| 3733 | id_phys = kzalloc(sizeof(*id_phys), GFP_KERNEL); | 3965 | id_phys = kzalloc(sizeof(*id_phys), GFP_KERNEL); |
| 3966 | id_ctlr = kzalloc(sizeof(*id_ctlr), GFP_KERNEL); | ||
| 3734 | 3967 | ||
| 3735 | if (!currentsd || !physdev_list || !logdev_list || | 3968 | if (!currentsd || !physdev_list || !logdev_list || |
| 3736 | !tmpdevice || !id_phys) { | 3969 | !tmpdevice || !id_phys || !id_ctlr) { |
| 3737 | dev_err(&h->pdev->dev, "out of memory\n"); | 3970 | dev_err(&h->pdev->dev, "out of memory\n"); |
| 3738 | goto out; | 3971 | goto out; |
| 3739 | } | 3972 | } |
| 3740 | memset(lunzerobits, 0, sizeof(lunzerobits)); | 3973 | memset(lunzerobits, 0, sizeof(lunzerobits)); |
| 3741 | 3974 | ||
| 3975 | h->drv_req_rescan = 0; /* cancel scheduled rescan - we're doing it. */ | ||
| 3976 | |||
| 3742 | if (hpsa_gather_lun_info(h, physdev_list, &nphysicals, | 3977 | if (hpsa_gather_lun_info(h, physdev_list, &nphysicals, |
| 3743 | logdev_list, &nlogicals)) | 3978 | logdev_list, &nlogicals)) { |
| 3979 | h->drv_req_rescan = 1; | ||
| 3744 | goto out; | 3980 | goto out; |
| 3981 | } | ||
| 3982 | |||
| 3983 | /* Set number of local logicals (non PTRAID) */ | ||
| 3984 | if (hpsa_set_local_logical_count(h, id_ctlr, &nlocal_logicals)) { | ||
| 3985 | dev_warn(&h->pdev->dev, | ||
| 3986 | "%s: Can't determine number of local logical devices.\n", | ||
| 3987 | __func__); | ||
| 3988 | } | ||
| 3745 | 3989 | ||
| 3746 | /* We might see up to the maximum number of logical and physical disks | 3990 | /* We might see up to the maximum number of logical and physical disks |
| 3747 | * plus external target devices, and a device for the local RAID | 3991 | * plus external target devices, and a device for the local RAID |
| @@ -3762,6 +4006,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno) | |||
| 3762 | if (!currentsd[i]) { | 4006 | if (!currentsd[i]) { |
| 3763 | dev_warn(&h->pdev->dev, "out of memory at %s:%d\n", | 4007 | dev_warn(&h->pdev->dev, "out of memory at %s:%d\n", |
| 3764 | __FILE__, __LINE__); | 4008 | __FILE__, __LINE__); |
| 4009 | h->drv_req_rescan = 1; | ||
| 3765 | goto out; | 4010 | goto out; |
| 3766 | } | 4011 | } |
| 3767 | ndev_allocated++; | 4012 | ndev_allocated++; |
| @@ -3776,49 +4021,74 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno) | |||
| 3776 | n_ext_target_devs = 0; | 4021 | n_ext_target_devs = 0; |
| 3777 | for (i = 0; i < nphysicals + nlogicals + 1; i++) { | 4022 | for (i = 0; i < nphysicals + nlogicals + 1; i++) { |
| 3778 | u8 *lunaddrbytes, is_OBDR = 0; | 4023 | u8 *lunaddrbytes, is_OBDR = 0; |
| 4024 | int rc = 0; | ||
| 4025 | int phys_dev_index = i - (raid_ctlr_position == 0); | ||
| 4026 | |||
| 4027 | physical_device = i < nphysicals + (raid_ctlr_position == 0); | ||
| 3779 | 4028 | ||
| 3780 | /* Figure out where the LUN ID info is coming from */ | 4029 | /* Figure out where the LUN ID info is coming from */ |
| 3781 | lunaddrbytes = figure_lunaddrbytes(h, raid_ctlr_position, | 4030 | lunaddrbytes = figure_lunaddrbytes(h, raid_ctlr_position, |
| 3782 | i, nphysicals, nlogicals, physdev_list, logdev_list); | 4031 | i, nphysicals, nlogicals, physdev_list, logdev_list); |
| 3783 | 4032 | ||
| 3784 | /* skip masked non-disk devices */ | 4033 | /* skip masked non-disk devices */ |
| 3785 | if (MASKED_DEVICE(lunaddrbytes)) | 4034 | if (MASKED_DEVICE(lunaddrbytes) && physical_device && |
| 3786 | if (i < nphysicals + (raid_ctlr_position == 0) && | 4035 | (physdev_list->LUN[phys_dev_index].device_flags & 0x01)) |
| 3787 | NON_DISK_PHYS_DEV(lunaddrbytes)) | 4036 | continue; |
| 3788 | continue; | ||
| 3789 | 4037 | ||
| 3790 | /* Get device type, vendor, model, device id */ | 4038 | /* Get device type, vendor, model, device id */ |
| 3791 | if (hpsa_update_device_info(h, lunaddrbytes, tmpdevice, | 4039 | rc = hpsa_update_device_info(h, lunaddrbytes, tmpdevice, |
| 3792 | &is_OBDR)) | 4040 | &is_OBDR); |
| 3793 | continue; /* skip it if we can't talk to it. */ | 4041 | if (rc == -ENOMEM) { |
| 4042 | dev_warn(&h->pdev->dev, | ||
| 4043 | "Out of memory, rescan deferred.\n"); | ||
| 4044 | h->drv_req_rescan = 1; | ||
| 4045 | goto out; | ||
| 4046 | } | ||
| 4047 | if (rc) { | ||
| 4048 | dev_warn(&h->pdev->dev, | ||
| 4049 | "Inquiry failed, skipping device.\n"); | ||
| 4050 | continue; | ||
| 4051 | } | ||
| 4052 | |||
| 4053 | /* Determine if this is a lun from an external target array */ | ||
| 4054 | tmpdevice->external = | ||
| 4055 | figure_external_status(h, raid_ctlr_position, i, | ||
| 4056 | nphysicals, nlocal_logicals); | ||
| 4057 | |||
| 3794 | figure_bus_target_lun(h, lunaddrbytes, tmpdevice); | 4058 | figure_bus_target_lun(h, lunaddrbytes, tmpdevice); |
| 3795 | hpsa_update_device_supports_aborts(h, tmpdevice, lunaddrbytes); | 4059 | hpsa_update_device_supports_aborts(h, tmpdevice, lunaddrbytes); |
| 3796 | this_device = currentsd[ncurrent]; | 4060 | this_device = currentsd[ncurrent]; |
| 3797 | 4061 | ||
| 3798 | /* | 4062 | /* Turn on discovery_polling if there are ext target devices. |
| 3799 | * For external target devices, we have to insert a LUN 0 which | 4063 | * Event-based change notification is unreliable for those. |
| 3800 | * doesn't show up in CCISS_REPORT_PHYSICAL data, but there | ||
| 3801 | * is nonetheless an enclosure device there. We have to | ||
| 3802 | * present that otherwise linux won't find anything if | ||
| 3803 | * there is no lun 0. | ||
| 3804 | */ | 4064 | */ |
| 3805 | if (add_ext_target_dev(h, tmpdevice, this_device, | 4065 | if (!h->discovery_polling) { |
| 3806 | lunaddrbytes, lunzerobits, | 4066 | if (tmpdevice->external) { |
| 3807 | &n_ext_target_devs)) { | 4067 | h->discovery_polling = 1; |
| 3808 | ncurrent++; | 4068 | dev_info(&h->pdev->dev, |
| 3809 | this_device = currentsd[ncurrent]; | 4069 | "External target, activate discovery polling.\n"); |
| 4070 | } | ||
| 3810 | } | 4071 | } |
| 3811 | 4072 | ||
| 4073 | |||
| 3812 | *this_device = *tmpdevice; | 4074 | *this_device = *tmpdevice; |
| 4075 | this_device->physical_device = physical_device; | ||
| 3813 | 4076 | ||
| 3814 | /* do not expose masked devices */ | 4077 | /* |
| 3815 | if (MASKED_DEVICE(lunaddrbytes) && | 4078 | * Expose all devices except for physical devices that |
| 3816 | i < nphysicals + (raid_ctlr_position == 0)) { | 4079 | * are masked. |
| 3817 | this_device->expose_state = HPSA_DO_NOT_EXPOSE; | 4080 | */ |
| 3818 | } else { | 4081 | if (MASKED_DEVICE(lunaddrbytes) && this_device->physical_device) |
| 3819 | this_device->expose_state = | 4082 | this_device->expose_device = 0; |
| 3820 | HPSA_SG_ATTACH | HPSA_ULD_ATTACH; | 4083 | else |
| 3821 | } | 4084 | this_device->expose_device = 1; |
| 4085 | |||
| 4086 | |||
| 4087 | /* | ||
| 4088 | * Get the SAS address for physical devices that are exposed. | ||
| 4089 | */ | ||
| 4090 | if (this_device->physical_device && this_device->expose_device) | ||
| 4091 | hpsa_get_sas_address(h, lunaddrbytes, this_device); | ||
| 3822 | 4092 | ||
| 3823 | switch (this_device->devtype) { | 4093 | switch (this_device->devtype) { |
| 3824 | case TYPE_ROM: | 4094 | case TYPE_ROM: |
| @@ -3833,14 +4103,14 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno) | |||
| 3833 | ncurrent++; | 4103 | ncurrent++; |
| 3834 | break; | 4104 | break; |
| 3835 | case TYPE_DISK: | 4105 | case TYPE_DISK: |
| 3836 | if (i < nphysicals + (raid_ctlr_position == 0)) { | 4106 | if (this_device->physical_device) { |
| 3837 | /* The disk is in HBA mode. */ | 4107 | /* The disk is in HBA mode. */ |
| 3838 | /* Never use RAID mapper in HBA mode. */ | 4108 | /* Never use RAID mapper in HBA mode. */ |
| 3839 | this_device->offload_enabled = 0; | 4109 | this_device->offload_enabled = 0; |
| 3840 | hpsa_get_ioaccel_drive_info(h, this_device, | 4110 | hpsa_get_ioaccel_drive_info(h, this_device, |
| 3841 | lunaddrbytes, id_phys); | 4111 | physdev_list, phys_dev_index, id_phys); |
| 3842 | hpsa_get_path_info(this_device, lunaddrbytes, | 4112 | hpsa_get_path_info(this_device, |
| 3843 | id_phys); | 4113 | physdev_list, phys_dev_index, id_phys); |
| 3844 | } | 4114 | } |
| 3845 | ncurrent++; | 4115 | ncurrent++; |
| 3846 | break; | 4116 | break; |
| @@ -3865,7 +4135,19 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno) | |||
| 3865 | if (ncurrent >= HPSA_MAX_DEVICES) | 4135 | if (ncurrent >= HPSA_MAX_DEVICES) |
| 3866 | break; | 4136 | break; |
| 3867 | } | 4137 | } |
| 3868 | adjust_hpsa_scsi_table(h, hostno, currentsd, ncurrent); | 4138 | |
| 4139 | if (h->sas_host == NULL) { | ||
| 4140 | int rc = 0; | ||
| 4141 | |||
| 4142 | rc = hpsa_add_sas_host(h); | ||
| 4143 | if (rc) { | ||
| 4144 | dev_warn(&h->pdev->dev, | ||
| 4145 | "Could not add sas host %d\n", rc); | ||
| 4146 | goto out; | ||
| 4147 | } | ||
| 4148 | } | ||
| 4149 | |||
| 4150 | adjust_hpsa_scsi_table(h, currentsd, ncurrent); | ||
| 3869 | out: | 4151 | out: |
| 3870 | kfree(tmpdevice); | 4152 | kfree(tmpdevice); |
| 3871 | for (i = 0; i < ndev_allocated; i++) | 4153 | for (i = 0; i < ndev_allocated; i++) |
| @@ -3873,6 +4155,7 @@ out: | |||
| 3873 | kfree(currentsd); | 4155 | kfree(currentsd); |
| 3874 | kfree(physdev_list); | 4156 | kfree(physdev_list); |
| 3875 | kfree(logdev_list); | 4157 | kfree(logdev_list); |
| 4158 | kfree(id_ctlr); | ||
| 3876 | kfree(id_phys); | 4159 | kfree(id_phys); |
| 3877 | } | 4160 | } |
| 3878 | 4161 | ||
| @@ -3978,19 +4261,14 @@ static int fixup_ioaccel_cdb(u8 *cdb, int *cdb_len) | |||
| 3978 | case READ_6: | 4261 | case READ_6: |
| 3979 | case READ_12: | 4262 | case READ_12: |
| 3980 | if (*cdb_len == 6) { | 4263 | if (*cdb_len == 6) { |
| 3981 | block = (((u32) cdb[2]) << 8) | cdb[3]; | 4264 | block = get_unaligned_be16(&cdb[2]); |
| 3982 | block_cnt = cdb[4]; | 4265 | block_cnt = cdb[4]; |
| 4266 | if (block_cnt == 0) | ||
| 4267 | block_cnt = 256; | ||
| 3983 | } else { | 4268 | } else { |
| 3984 | BUG_ON(*cdb_len != 12); | 4269 | BUG_ON(*cdb_len != 12); |
| 3985 | block = (((u32) cdb[2]) << 24) | | 4270 | block = get_unaligned_be32(&cdb[2]); |
| 3986 | (((u32) cdb[3]) << 16) | | 4271 | block_cnt = get_unaligned_be32(&cdb[6]); |
| 3987 | (((u32) cdb[4]) << 8) | | ||
| 3988 | cdb[5]; | ||
| 3989 | block_cnt = | ||
| 3990 | (((u32) cdb[6]) << 24) | | ||
| 3991 | (((u32) cdb[7]) << 16) | | ||
| 3992 | (((u32) cdb[8]) << 8) | | ||
| 3993 | cdb[9]; | ||
| 3994 | } | 4272 | } |
| 3995 | if (block_cnt > 0xffff) | 4273 | if (block_cnt > 0xffff) |
| 3996 | return IO_ACCEL_INELIGIBLE; | 4274 | return IO_ACCEL_INELIGIBLE; |
| @@ -4272,6 +4550,7 @@ static int hpsa_scsi_ioaccel2_queue_command(struct ctlr_info *h, | |||
| 4272 | /* fill in sg elements */ | 4550 | /* fill in sg elements */ |
| 4273 | if (use_sg > h->ioaccel_maxsg) { | 4551 | if (use_sg > h->ioaccel_maxsg) { |
| 4274 | cp->sg_count = 1; | 4552 | cp->sg_count = 1; |
| 4553 | cp->sg[0].length = cpu_to_le32(use_sg * sizeof(cp->sg[0])); | ||
| 4275 | if (hpsa_map_ioaccel2_sg_chain_block(h, cp, c)) { | 4554 | if (hpsa_map_ioaccel2_sg_chain_block(h, cp, c)) { |
| 4276 | atomic_dec(&phys_disk->ioaccel_cmds_out); | 4555 | atomic_dec(&phys_disk->ioaccel_cmds_out); |
| 4277 | scsi_dma_unmap(cmd); | 4556 | scsi_dma_unmap(cmd); |
| @@ -4376,9 +4655,7 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h, | |||
| 4376 | case WRITE_6: | 4655 | case WRITE_6: |
| 4377 | is_write = 1; | 4656 | is_write = 1; |
| 4378 | case READ_6: | 4657 | case READ_6: |
| 4379 | first_block = | 4658 | first_block = get_unaligned_be16(&cmd->cmnd[2]); |
| 4380 | (((u64) cmd->cmnd[2]) << 8) | | ||
| 4381 | cmd->cmnd[3]; | ||
| 4382 | block_cnt = cmd->cmnd[4]; | 4659 | block_cnt = cmd->cmnd[4]; |
| 4383 | if (block_cnt == 0) | 4660 | if (block_cnt == 0) |
| 4384 | block_cnt = 256; | 4661 | block_cnt = 256; |
| @@ -4947,7 +5224,7 @@ static void hpsa_scan_start(struct Scsi_Host *sh) | |||
| 4947 | if (unlikely(lockup_detected(h))) | 5224 | if (unlikely(lockup_detected(h))) |
| 4948 | return hpsa_scan_complete(h); | 5225 | return hpsa_scan_complete(h); |
| 4949 | 5226 | ||
| 4950 | hpsa_update_scsi_devices(h, h->scsi_host->host_no); | 5227 | hpsa_update_scsi_devices(h); |
| 4951 | 5228 | ||
| 4952 | hpsa_scan_complete(h); | 5229 | hpsa_scan_complete(h); |
| 4953 | } | 5230 | } |
| @@ -5000,6 +5277,7 @@ static int hpsa_scsi_host_alloc(struct ctlr_info *h) | |||
| 5000 | sh->can_queue = h->nr_cmds - HPSA_NRESERVED_CMDS; | 5277 | sh->can_queue = h->nr_cmds - HPSA_NRESERVED_CMDS; |
| 5001 | sh->cmd_per_lun = sh->can_queue; | 5278 | sh->cmd_per_lun = sh->can_queue; |
| 5002 | sh->sg_tablesize = h->maxsgentries; | 5279 | sh->sg_tablesize = h->maxsgentries; |
| 5280 | sh->transportt = hpsa_sas_transport_template; | ||
| 5003 | sh->hostdata[0] = (unsigned long) h; | 5281 | sh->hostdata[0] = (unsigned long) h; |
| 5004 | sh->irq = h->intr[h->intr_mode]; | 5282 | sh->irq = h->intr[h->intr_mode]; |
| 5005 | sh->unique_id = sh->irq; | 5283 | sh->unique_id = sh->irq; |
| @@ -5159,6 +5437,7 @@ static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd) | |||
| 5159 | int rc; | 5437 | int rc; |
| 5160 | struct ctlr_info *h; | 5438 | struct ctlr_info *h; |
| 5161 | struct hpsa_scsi_dev_t *dev; | 5439 | struct hpsa_scsi_dev_t *dev; |
| 5440 | u8 reset_type; | ||
| 5162 | char msg[48]; | 5441 | char msg[48]; |
| 5163 | 5442 | ||
| 5164 | /* find the controller to which the command to be aborted was sent */ | 5443 | /* find the controller to which the command to be aborted was sent */ |
| @@ -5197,14 +5476,25 @@ static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd) | |||
| 5197 | if (is_hba_lunid(dev->scsi3addr)) | 5476 | if (is_hba_lunid(dev->scsi3addr)) |
| 5198 | return SUCCESS; | 5477 | return SUCCESS; |
| 5199 | 5478 | ||
| 5200 | hpsa_show_dev_msg(KERN_WARNING, h, dev, "resetting"); | 5479 | if (is_logical_dev_addr_mode(dev->scsi3addr)) |
| 5480 | reset_type = HPSA_DEVICE_RESET_MSG; | ||
| 5481 | else | ||
| 5482 | reset_type = HPSA_PHYS_TARGET_RESET; | ||
| 5483 | |||
| 5484 | sprintf(msg, "resetting %s", | ||
| 5485 | reset_type == HPSA_DEVICE_RESET_MSG ? "logical " : "physical "); | ||
| 5486 | hpsa_show_dev_msg(KERN_WARNING, h, dev, msg); | ||
| 5487 | |||
| 5488 | h->reset_in_progress = 1; | ||
| 5201 | 5489 | ||
| 5202 | /* send a reset to the SCSI LUN which the command was sent to */ | 5490 | /* send a reset to the SCSI LUN which the command was sent to */ |
| 5203 | rc = hpsa_do_reset(h, dev, dev->scsi3addr, HPSA_RESET_TYPE_LUN, | 5491 | rc = hpsa_do_reset(h, dev, dev->scsi3addr, reset_type, |
| 5204 | DEFAULT_REPLY_QUEUE); | 5492 | DEFAULT_REPLY_QUEUE); |
| 5205 | snprintf(msg, sizeof(msg), "reset %s", | 5493 | sprintf(msg, "reset %s %s", |
| 5206 | rc == 0 ? "completed successfully" : "failed"); | 5494 | reset_type == HPSA_DEVICE_RESET_MSG ? "logical " : "physical ", |
| 5495 | rc == 0 ? "completed successfully" : "failed"); | ||
| 5207 | hpsa_show_dev_msg(KERN_WARNING, h, dev, msg); | 5496 | hpsa_show_dev_msg(KERN_WARNING, h, dev, msg); |
| 5497 | h->reset_in_progress = 0; | ||
| 5208 | return rc == 0 ? SUCCESS : FAILED; | 5498 | return rc == 0 ? SUCCESS : FAILED; |
| 5209 | } | 5499 | } |
| 5210 | 5500 | ||
| @@ -6262,6 +6552,24 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h, | |||
| 6262 | c->Request.CDB[8] = (size >> 8) & 0xFF; | 6552 | c->Request.CDB[8] = (size >> 8) & 0xFF; |
| 6263 | c->Request.CDB[9] = size & 0xFF; | 6553 | c->Request.CDB[9] = size & 0xFF; |
| 6264 | break; | 6554 | break; |
| 6555 | case BMIC_SENSE_DIAG_OPTIONS: | ||
| 6556 | c->Request.CDBLen = 16; | ||
| 6557 | c->Request.type_attr_dir = | ||
| 6558 | TYPE_ATTR_DIR(cmd_type, ATTR_SIMPLE, XFER_READ); | ||
| 6559 | c->Request.Timeout = 0; | ||
| 6560 | /* Spec says this should be BMIC_WRITE */ | ||
| 6561 | c->Request.CDB[0] = BMIC_READ; | ||
| 6562 | c->Request.CDB[6] = BMIC_SENSE_DIAG_OPTIONS; | ||
| 6563 | break; | ||
| 6564 | case BMIC_SET_DIAG_OPTIONS: | ||
| 6565 | c->Request.CDBLen = 16; | ||
| 6566 | c->Request.type_attr_dir = | ||
| 6567 | TYPE_ATTR_DIR(cmd_type, | ||
| 6568 | ATTR_SIMPLE, XFER_WRITE); | ||
| 6569 | c->Request.Timeout = 0; | ||
| 6570 | c->Request.CDB[0] = BMIC_WRITE; | ||
| 6571 | c->Request.CDB[6] = BMIC_SET_DIAG_OPTIONS; | ||
| 6572 | break; | ||
| 6265 | case HPSA_CACHE_FLUSH: | 6573 | case HPSA_CACHE_FLUSH: |
| 6266 | c->Request.CDBLen = 12; | 6574 | c->Request.CDBLen = 12; |
| 6267 | c->Request.type_attr_dir = | 6575 | c->Request.type_attr_dir = |
| @@ -6311,6 +6619,32 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h, | |||
| 6311 | c->Request.CDB[7] = (size >> 16) & 0xFF; | 6619 | c->Request.CDB[7] = (size >> 16) & 0xFF; |
| 6312 | c->Request.CDB[8] = (size >> 8) & 0XFF; | 6620 | c->Request.CDB[8] = (size >> 8) & 0XFF; |
| 6313 | break; | 6621 | break; |
| 6622 | case BMIC_SENSE_SUBSYSTEM_INFORMATION: | ||
| 6623 | c->Request.CDBLen = 10; | ||
| 6624 | c->Request.type_attr_dir = | ||
| 6625 | TYPE_ATTR_DIR(cmd_type, ATTR_SIMPLE, XFER_READ); | ||
| 6626 | c->Request.Timeout = 0; | ||
| 6627 | c->Request.CDB[0] = BMIC_READ; | ||
| 6628 | c->Request.CDB[6] = BMIC_SENSE_SUBSYSTEM_INFORMATION; | ||
| 6629 | c->Request.CDB[7] = (size >> 16) & 0xFF; | ||
| 6630 | c->Request.CDB[8] = (size >> 8) & 0XFF; | ||
| 6631 | break; | ||
| 6632 | case BMIC_IDENTIFY_CONTROLLER: | ||
| 6633 | c->Request.CDBLen = 10; | ||
| 6634 | c->Request.type_attr_dir = | ||
| 6635 | TYPE_ATTR_DIR(cmd_type, ATTR_SIMPLE, XFER_READ); | ||
| 6636 | c->Request.Timeout = 0; | ||
| 6637 | c->Request.CDB[0] = BMIC_READ; | ||
| 6638 | c->Request.CDB[1] = 0; | ||
| 6639 | c->Request.CDB[2] = 0; | ||
| 6640 | c->Request.CDB[3] = 0; | ||
| 6641 | c->Request.CDB[4] = 0; | ||
| 6642 | c->Request.CDB[5] = 0; | ||
| 6643 | c->Request.CDB[6] = BMIC_IDENTIFY_CONTROLLER; | ||
| 6644 | c->Request.CDB[7] = (size >> 16) & 0xFF; | ||
| 6645 | c->Request.CDB[8] = (size >> 8) & 0XFF; | ||
| 6646 | c->Request.CDB[9] = 0; | ||
| 6647 | break; | ||
| 6314 | default: | 6648 | default: |
| 6315 | dev_warn(&h->pdev->dev, "unknown command 0x%c\n", cmd); | 6649 | dev_warn(&h->pdev->dev, "unknown command 0x%c\n", cmd); |
| 6316 | BUG(); | 6650 | BUG(); |
| @@ -6319,6 +6653,20 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h, | |||
| 6319 | } else if (cmd_type == TYPE_MSG) { | 6653 | } else if (cmd_type == TYPE_MSG) { |
| 6320 | switch (cmd) { | 6654 | switch (cmd) { |
| 6321 | 6655 | ||
| 6656 | case HPSA_PHYS_TARGET_RESET: | ||
| 6657 | c->Request.CDBLen = 16; | ||
| 6658 | c->Request.type_attr_dir = | ||
| 6659 | TYPE_ATTR_DIR(cmd_type, ATTR_SIMPLE, XFER_NONE); | ||
| 6660 | c->Request.Timeout = 0; /* Don't time out */ | ||
| 6661 | memset(&c->Request.CDB[0], 0, sizeof(c->Request.CDB)); | ||
| 6662 | c->Request.CDB[0] = HPSA_RESET; | ||
| 6663 | c->Request.CDB[1] = HPSA_TARGET_RESET_TYPE; | ||
| 6664 | /* Physical target reset needs no control bytes 4-7*/ | ||
| 6665 | c->Request.CDB[4] = 0x00; | ||
| 6666 | c->Request.CDB[5] = 0x00; | ||
| 6667 | c->Request.CDB[6] = 0x00; | ||
| 6668 | c->Request.CDB[7] = 0x00; | ||
| 6669 | break; | ||
| 6322 | case HPSA_DEVICE_RESET_MSG: | 6670 | case HPSA_DEVICE_RESET_MSG: |
| 6323 | c->Request.CDBLen = 16; | 6671 | c->Request.CDBLen = 16; |
| 6324 | c->Request.type_attr_dir = | 6672 | c->Request.type_attr_dir = |
| @@ -6432,16 +6780,6 @@ static inline void finish_cmd(struct CommandList *c) | |||
| 6432 | complete(c->waiting); | 6780 | complete(c->waiting); |
| 6433 | } | 6781 | } |
| 6434 | 6782 | ||
| 6435 | |||
| 6436 | static inline u32 hpsa_tag_discard_error_bits(struct ctlr_info *h, u32 tag) | ||
| 6437 | { | ||
| 6438 | #define HPSA_PERF_ERROR_BITS ((1 << DIRECT_LOOKUP_SHIFT) - 1) | ||
| 6439 | #define HPSA_SIMPLE_ERROR_BITS 0x03 | ||
| 6440 | if (unlikely(!(h->transMethod & CFGTBL_Trans_Performant))) | ||
| 6441 | return tag & ~HPSA_SIMPLE_ERROR_BITS; | ||
| 6442 | return tag & ~HPSA_PERF_ERROR_BITS; | ||
| 6443 | } | ||
| 6444 | |||
| 6445 | /* process completion of an indexed ("direct lookup") command */ | 6783 | /* process completion of an indexed ("direct lookup") command */ |
| 6446 | static inline void process_indexed_cmd(struct ctlr_info *h, | 6784 | static inline void process_indexed_cmd(struct ctlr_info *h, |
| 6447 | u32 raw_tag) | 6785 | u32 raw_tag) |
| @@ -7852,6 +8190,11 @@ static void hpsa_ack_ctlr_events(struct ctlr_info *h) | |||
| 7852 | */ | 8190 | */ |
| 7853 | static int hpsa_ctlr_needs_rescan(struct ctlr_info *h) | 8191 | static int hpsa_ctlr_needs_rescan(struct ctlr_info *h) |
| 7854 | { | 8192 | { |
| 8193 | if (h->drv_req_rescan) { | ||
| 8194 | h->drv_req_rescan = 0; | ||
| 8195 | return 1; | ||
| 8196 | } | ||
| 8197 | |||
| 7855 | if (!(h->fw_support & MISC_FW_EVENT_NOTIFY)) | 8198 | if (!(h->fw_support & MISC_FW_EVENT_NOTIFY)) |
| 7856 | return 0; | 8199 | return 0; |
| 7857 | 8200 | ||
| @@ -7885,6 +8228,41 @@ static int hpsa_offline_devices_ready(struct ctlr_info *h) | |||
| 7885 | return 0; | 8228 | return 0; |
| 7886 | } | 8229 | } |
| 7887 | 8230 | ||
| 8231 | static int hpsa_luns_changed(struct ctlr_info *h) | ||
| 8232 | { | ||
| 8233 | int rc = 1; /* assume there are changes */ | ||
| 8234 | struct ReportLUNdata *logdev = NULL; | ||
| 8235 | |||
| 8236 | /* if we can't find out if lun data has changed, | ||
| 8237 | * assume that it has. | ||
| 8238 | */ | ||
| 8239 | |||
| 8240 | if (!h->lastlogicals) | ||
| 8241 | goto out; | ||
| 8242 | |||
| 8243 | logdev = kzalloc(sizeof(*logdev), GFP_KERNEL); | ||
| 8244 | if (!logdev) { | ||
| 8245 | dev_warn(&h->pdev->dev, | ||
| 8246 | "Out of memory, can't track lun changes.\n"); | ||
| 8247 | goto out; | ||
| 8248 | } | ||
| 8249 | if (hpsa_scsi_do_report_luns(h, 1, logdev, sizeof(*logdev), 0)) { | ||
| 8250 | dev_warn(&h->pdev->dev, | ||
| 8251 | "report luns failed, can't track lun changes.\n"); | ||
| 8252 | goto out; | ||
| 8253 | } | ||
| 8254 | if (memcmp(logdev, h->lastlogicals, sizeof(*logdev))) { | ||
| 8255 | dev_info(&h->pdev->dev, | ||
| 8256 | "Lun changes detected.\n"); | ||
| 8257 | memcpy(h->lastlogicals, logdev, sizeof(*logdev)); | ||
| 8258 | goto out; | ||
| 8259 | } else | ||
| 8260 | rc = 0; /* no changes detected. */ | ||
| 8261 | out: | ||
| 8262 | kfree(logdev); | ||
| 8263 | return rc; | ||
| 8264 | } | ||
| 8265 | |||
| 7888 | static void hpsa_rescan_ctlr_worker(struct work_struct *work) | 8266 | static void hpsa_rescan_ctlr_worker(struct work_struct *work) |
| 7889 | { | 8267 | { |
| 7890 | unsigned long flags; | 8268 | unsigned long flags; |
| @@ -7900,6 +8278,19 @@ static void hpsa_rescan_ctlr_worker(struct work_struct *work) | |||
| 7900 | hpsa_ack_ctlr_events(h); | 8278 | hpsa_ack_ctlr_events(h); |
| 7901 | hpsa_scan_start(h->scsi_host); | 8279 | hpsa_scan_start(h->scsi_host); |
| 7902 | scsi_host_put(h->scsi_host); | 8280 | scsi_host_put(h->scsi_host); |
| 8281 | } else if (h->discovery_polling) { | ||
| 8282 | hpsa_disable_rld_caching(h); | ||
| 8283 | if (hpsa_luns_changed(h)) { | ||
| 8284 | struct Scsi_Host *sh = NULL; | ||
| 8285 | |||
| 8286 | dev_info(&h->pdev->dev, | ||
| 8287 | "driver discovery polling rescan.\n"); | ||
| 8288 | sh = scsi_host_get(h->scsi_host); | ||
| 8289 | if (sh != NULL) { | ||
| 8290 | hpsa_scan_start(sh); | ||
| 8291 | scsi_host_put(sh); | ||
| 8292 | } | ||
| 8293 | } | ||
| 7903 | } | 8294 | } |
| 7904 | spin_lock_irqsave(&h->lock, flags); | 8295 | spin_lock_irqsave(&h->lock, flags); |
| 7905 | if (!h->remove_in_progress) | 8296 | if (!h->remove_in_progress) |
| @@ -8140,6 +8531,8 @@ reinit_after_soft_reset: | |||
| 8140 | 8531 | ||
| 8141 | /* Enable Accelerated IO path at driver layer */ | 8532 | /* Enable Accelerated IO path at driver layer */ |
| 8142 | h->acciopath_status = 1; | 8533 | h->acciopath_status = 1; |
| 8534 | /* Disable discovery polling.*/ | ||
| 8535 | h->discovery_polling = 0; | ||
| 8143 | 8536 | ||
| 8144 | 8537 | ||
| 8145 | /* Turn the interrupts on so we can service requests */ | 8538 | /* Turn the interrupts on so we can service requests */ |
| @@ -8147,6 +8540,11 @@ reinit_after_soft_reset: | |||
| 8147 | 8540 | ||
| 8148 | hpsa_hba_inquiry(h); | 8541 | hpsa_hba_inquiry(h); |
| 8149 | 8542 | ||
| 8543 | h->lastlogicals = kzalloc(sizeof(*(h->lastlogicals)), GFP_KERNEL); | ||
| 8544 | if (!h->lastlogicals) | ||
| 8545 | dev_info(&h->pdev->dev, | ||
| 8546 | "Can't track change to report lun data\n"); | ||
| 8547 | |||
| 8150 | /* Monitor the controller for firmware lockups */ | 8548 | /* Monitor the controller for firmware lockups */ |
| 8151 | h->heartbeat_sample_interval = HEARTBEAT_SAMPLE_INTERVAL; | 8549 | h->heartbeat_sample_interval = HEARTBEAT_SAMPLE_INTERVAL; |
| 8152 | INIT_DELAYED_WORK(&h->monitor_ctlr_work, hpsa_monitor_ctlr_worker); | 8550 | INIT_DELAYED_WORK(&h->monitor_ctlr_work, hpsa_monitor_ctlr_worker); |
| @@ -8219,6 +8617,71 @@ out: | |||
| 8219 | kfree(flush_buf); | 8617 | kfree(flush_buf); |
| 8220 | } | 8618 | } |
| 8221 | 8619 | ||
| 8620 | /* Make controller gather fresh report lun data each time we | ||
| 8621 | * send down a report luns request | ||
| 8622 | */ | ||
| 8623 | static void hpsa_disable_rld_caching(struct ctlr_info *h) | ||
| 8624 | { | ||
| 8625 | u32 *options; | ||
| 8626 | struct CommandList *c; | ||
| 8627 | int rc; | ||
| 8628 | |||
| 8629 | /* Don't bother trying to set diag options if locked up */ | ||
| 8630 | if (unlikely(h->lockup_detected)) | ||
| 8631 | return; | ||
| 8632 | |||
| 8633 | options = kzalloc(sizeof(*options), GFP_KERNEL); | ||
| 8634 | if (!options) { | ||
| 8635 | dev_err(&h->pdev->dev, | ||
| 8636 | "Error: failed to disable rld caching, during alloc.\n"); | ||
| 8637 | return; | ||
| 8638 | } | ||
| 8639 | |||
| 8640 | c = cmd_alloc(h); | ||
| 8641 | |||
| 8642 | /* first, get the current diag options settings */ | ||
| 8643 | if (fill_cmd(c, BMIC_SENSE_DIAG_OPTIONS, h, options, 4, 0, | ||
| 8644 | RAID_CTLR_LUNID, TYPE_CMD)) | ||
| 8645 | goto errout; | ||
| 8646 | |||
| 8647 | rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, | ||
| 8648 | PCI_DMA_FROMDEVICE, NO_TIMEOUT); | ||
| 8649 | if ((rc != 0) || (c->err_info->CommandStatus != 0)) | ||
| 8650 | goto errout; | ||
| 8651 | |||
| 8652 | /* Now, set the bit for disabling the RLD caching */ | ||
| 8653 | *options |= HPSA_DIAG_OPTS_DISABLE_RLD_CACHING; | ||
| 8654 | |||
| 8655 | if (fill_cmd(c, BMIC_SET_DIAG_OPTIONS, h, options, 4, 0, | ||
| 8656 | RAID_CTLR_LUNID, TYPE_CMD)) | ||
| 8657 | goto errout; | ||
| 8658 | |||
| 8659 | rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, | ||
| 8660 | PCI_DMA_TODEVICE, NO_TIMEOUT); | ||
| 8661 | if ((rc != 0) || (c->err_info->CommandStatus != 0)) | ||
| 8662 | goto errout; | ||
| 8663 | |||
| 8664 | /* Now verify that it got set: */ | ||
| 8665 | if (fill_cmd(c, BMIC_SENSE_DIAG_OPTIONS, h, options, 4, 0, | ||
| 8666 | RAID_CTLR_LUNID, TYPE_CMD)) | ||
| 8667 | goto errout; | ||
| 8668 | |||
| 8669 | rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, | ||
| 8670 | PCI_DMA_FROMDEVICE, NO_TIMEOUT); | ||
| 8671 | if ((rc != 0) || (c->err_info->CommandStatus != 0)) | ||
| 8672 | goto errout; | ||
| 8673 | |||
| 8674 | if (*options && HPSA_DIAG_OPTS_DISABLE_RLD_CACHING) | ||
| 8675 | goto out; | ||
| 8676 | |||
| 8677 | errout: | ||
| 8678 | dev_err(&h->pdev->dev, | ||
| 8679 | "Error: failed to disable report lun data caching.\n"); | ||
| 8680 | out: | ||
| 8681 | cmd_free(h, c); | ||
| 8682 | kfree(options); | ||
| 8683 | } | ||
| 8684 | |||
| 8222 | static void hpsa_shutdown(struct pci_dev *pdev) | 8685 | static void hpsa_shutdown(struct pci_dev *pdev) |
| 8223 | { | 8686 | { |
| 8224 | struct ctlr_info *h; | 8687 | struct ctlr_info *h; |
| @@ -8284,6 +8747,7 @@ static void hpsa_remove_one(struct pci_dev *pdev) | |||
| 8284 | hpsa_free_performant_mode(h); /* init_one 7 */ | 8747 | hpsa_free_performant_mode(h); /* init_one 7 */ |
| 8285 | hpsa_free_sg_chain_blocks(h); /* init_one 6 */ | 8748 | hpsa_free_sg_chain_blocks(h); /* init_one 6 */ |
| 8286 | hpsa_free_cmd_pool(h); /* init_one 5 */ | 8749 | hpsa_free_cmd_pool(h); /* init_one 5 */ |
| 8750 | kfree(h->lastlogicals); | ||
| 8287 | 8751 | ||
| 8288 | /* hpsa_free_irqs already called via hpsa_shutdown init_one 4 */ | 8752 | /* hpsa_free_irqs already called via hpsa_shutdown init_one 4 */ |
| 8289 | 8753 | ||
| @@ -8296,6 +8760,9 @@ static void hpsa_remove_one(struct pci_dev *pdev) | |||
| 8296 | free_percpu(h->lockup_detected); /* init_one 2 */ | 8760 | free_percpu(h->lockup_detected); /* init_one 2 */ |
| 8297 | h->lockup_detected = NULL; /* init_one 2 */ | 8761 | h->lockup_detected = NULL; /* init_one 2 */ |
| 8298 | /* (void) pci_disable_pcie_error_reporting(pdev); */ /* init_one 1 */ | 8762 | /* (void) pci_disable_pcie_error_reporting(pdev); */ /* init_one 1 */ |
| 8763 | |||
| 8764 | hpsa_delete_sas_host(h); | ||
| 8765 | |||
| 8299 | kfree(h); /* init_one 1 */ | 8766 | kfree(h); /* init_one 1 */ |
| 8300 | } | 8767 | } |
| 8301 | 8768 | ||
| @@ -8758,18 +9225,369 @@ static void hpsa_drain_accel_commands(struct ctlr_info *h) | |||
| 8758 | } while (1); | 9225 | } while (1); |
| 8759 | } | 9226 | } |
| 8760 | 9227 | ||
| 9228 | static struct hpsa_sas_phy *hpsa_alloc_sas_phy( | ||
| 9229 | struct hpsa_sas_port *hpsa_sas_port) | ||
| 9230 | { | ||
| 9231 | struct hpsa_sas_phy *hpsa_sas_phy; | ||
| 9232 | struct sas_phy *phy; | ||
| 9233 | |||
| 9234 | hpsa_sas_phy = kzalloc(sizeof(*hpsa_sas_phy), GFP_KERNEL); | ||
| 9235 | if (!hpsa_sas_phy) | ||
| 9236 | return NULL; | ||
| 9237 | |||
| 9238 | phy = sas_phy_alloc(hpsa_sas_port->parent_node->parent_dev, | ||
| 9239 | hpsa_sas_port->next_phy_index); | ||
| 9240 | if (!phy) { | ||
| 9241 | kfree(hpsa_sas_phy); | ||
| 9242 | return NULL; | ||
| 9243 | } | ||
| 9244 | |||
| 9245 | hpsa_sas_port->next_phy_index++; | ||
| 9246 | hpsa_sas_phy->phy = phy; | ||
| 9247 | hpsa_sas_phy->parent_port = hpsa_sas_port; | ||
| 9248 | |||
| 9249 | return hpsa_sas_phy; | ||
| 9250 | } | ||
| 9251 | |||
| 9252 | static void hpsa_free_sas_phy(struct hpsa_sas_phy *hpsa_sas_phy) | ||
| 9253 | { | ||
| 9254 | struct sas_phy *phy = hpsa_sas_phy->phy; | ||
| 9255 | |||
| 9256 | sas_port_delete_phy(hpsa_sas_phy->parent_port->port, phy); | ||
| 9257 | sas_phy_free(phy); | ||
| 9258 | if (hpsa_sas_phy->added_to_port) | ||
| 9259 | list_del(&hpsa_sas_phy->phy_list_entry); | ||
| 9260 | kfree(hpsa_sas_phy); | ||
| 9261 | } | ||
| 9262 | |||
| 9263 | static int hpsa_sas_port_add_phy(struct hpsa_sas_phy *hpsa_sas_phy) | ||
| 9264 | { | ||
| 9265 | int rc; | ||
| 9266 | struct hpsa_sas_port *hpsa_sas_port; | ||
| 9267 | struct sas_phy *phy; | ||
| 9268 | struct sas_identify *identify; | ||
| 9269 | |||
| 9270 | hpsa_sas_port = hpsa_sas_phy->parent_port; | ||
| 9271 | phy = hpsa_sas_phy->phy; | ||
| 9272 | |||
| 9273 | identify = &phy->identify; | ||
| 9274 | memset(identify, 0, sizeof(*identify)); | ||
| 9275 | identify->sas_address = hpsa_sas_port->sas_address; | ||
| 9276 | identify->device_type = SAS_END_DEVICE; | ||
| 9277 | identify->initiator_port_protocols = SAS_PROTOCOL_STP; | ||
| 9278 | identify->target_port_protocols = SAS_PROTOCOL_STP; | ||
| 9279 | phy->minimum_linkrate_hw = SAS_LINK_RATE_UNKNOWN; | ||
| 9280 | phy->maximum_linkrate_hw = SAS_LINK_RATE_UNKNOWN; | ||
| 9281 | phy->minimum_linkrate = SAS_LINK_RATE_UNKNOWN; | ||
| 9282 | phy->maximum_linkrate = SAS_LINK_RATE_UNKNOWN; | ||
| 9283 | phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN; | ||
| 9284 | |||
| 9285 | rc = sas_phy_add(hpsa_sas_phy->phy); | ||
| 9286 | if (rc) | ||
| 9287 | return rc; | ||
| 9288 | |||
| 9289 | sas_port_add_phy(hpsa_sas_port->port, hpsa_sas_phy->phy); | ||
| 9290 | list_add_tail(&hpsa_sas_phy->phy_list_entry, | ||
| 9291 | &hpsa_sas_port->phy_list_head); | ||
| 9292 | hpsa_sas_phy->added_to_port = true; | ||
| 9293 | |||
| 9294 | return 0; | ||
| 9295 | } | ||
| 9296 | |||
| 9297 | static int | ||
| 9298 | hpsa_sas_port_add_rphy(struct hpsa_sas_port *hpsa_sas_port, | ||
| 9299 | struct sas_rphy *rphy) | ||
| 9300 | { | ||
| 9301 | struct sas_identify *identify; | ||
| 9302 | |||
| 9303 | identify = &rphy->identify; | ||
| 9304 | identify->sas_address = hpsa_sas_port->sas_address; | ||
| 9305 | identify->initiator_port_protocols = SAS_PROTOCOL_STP; | ||
| 9306 | identify->target_port_protocols = SAS_PROTOCOL_STP; | ||
| 9307 | |||
| 9308 | return sas_rphy_add(rphy); | ||
| 9309 | } | ||
| 9310 | |||
| 9311 | static struct hpsa_sas_port | ||
| 9312 | *hpsa_alloc_sas_port(struct hpsa_sas_node *hpsa_sas_node, | ||
| 9313 | u64 sas_address) | ||
| 9314 | { | ||
| 9315 | int rc; | ||
| 9316 | struct hpsa_sas_port *hpsa_sas_port; | ||
| 9317 | struct sas_port *port; | ||
| 9318 | |||
| 9319 | hpsa_sas_port = kzalloc(sizeof(*hpsa_sas_port), GFP_KERNEL); | ||
| 9320 | if (!hpsa_sas_port) | ||
| 9321 | return NULL; | ||
| 9322 | |||
| 9323 | INIT_LIST_HEAD(&hpsa_sas_port->phy_list_head); | ||
| 9324 | hpsa_sas_port->parent_node = hpsa_sas_node; | ||
| 9325 | |||
| 9326 | port = sas_port_alloc_num(hpsa_sas_node->parent_dev); | ||
| 9327 | if (!port) | ||
| 9328 | goto free_hpsa_port; | ||
| 9329 | |||
| 9330 | rc = sas_port_add(port); | ||
| 9331 | if (rc) | ||
| 9332 | goto free_sas_port; | ||
| 9333 | |||
| 9334 | hpsa_sas_port->port = port; | ||
| 9335 | hpsa_sas_port->sas_address = sas_address; | ||
| 9336 | list_add_tail(&hpsa_sas_port->port_list_entry, | ||
| 9337 | &hpsa_sas_node->port_list_head); | ||
| 9338 | |||
| 9339 | return hpsa_sas_port; | ||
| 9340 | |||
| 9341 | free_sas_port: | ||
| 9342 | sas_port_free(port); | ||
| 9343 | free_hpsa_port: | ||
| 9344 | kfree(hpsa_sas_port); | ||
| 9345 | |||
| 9346 | return NULL; | ||
| 9347 | } | ||
| 9348 | |||
| 9349 | static void hpsa_free_sas_port(struct hpsa_sas_port *hpsa_sas_port) | ||
| 9350 | { | ||
| 9351 | struct hpsa_sas_phy *hpsa_sas_phy; | ||
| 9352 | struct hpsa_sas_phy *next; | ||
| 9353 | |||
| 9354 | list_for_each_entry_safe(hpsa_sas_phy, next, | ||
| 9355 | &hpsa_sas_port->phy_list_head, phy_list_entry) | ||
| 9356 | hpsa_free_sas_phy(hpsa_sas_phy); | ||
| 9357 | |||
| 9358 | sas_port_delete(hpsa_sas_port->port); | ||
| 9359 | list_del(&hpsa_sas_port->port_list_entry); | ||
| 9360 | kfree(hpsa_sas_port); | ||
| 9361 | } | ||
| 9362 | |||
| 9363 | static struct hpsa_sas_node *hpsa_alloc_sas_node(struct device *parent_dev) | ||
| 9364 | { | ||
| 9365 | struct hpsa_sas_node *hpsa_sas_node; | ||
| 9366 | |||
| 9367 | hpsa_sas_node = kzalloc(sizeof(*hpsa_sas_node), GFP_KERNEL); | ||
| 9368 | if (hpsa_sas_node) { | ||
| 9369 | hpsa_sas_node->parent_dev = parent_dev; | ||
| 9370 | INIT_LIST_HEAD(&hpsa_sas_node->port_list_head); | ||
| 9371 | } | ||
| 9372 | |||
| 9373 | return hpsa_sas_node; | ||
| 9374 | } | ||
| 9375 | |||
| 9376 | static void hpsa_free_sas_node(struct hpsa_sas_node *hpsa_sas_node) | ||
| 9377 | { | ||
| 9378 | struct hpsa_sas_port *hpsa_sas_port; | ||
| 9379 | struct hpsa_sas_port *next; | ||
| 9380 | |||
| 9381 | if (!hpsa_sas_node) | ||
| 9382 | return; | ||
| 9383 | |||
| 9384 | list_for_each_entry_safe(hpsa_sas_port, next, | ||
| 9385 | &hpsa_sas_node->port_list_head, port_list_entry) | ||
| 9386 | hpsa_free_sas_port(hpsa_sas_port); | ||
| 9387 | |||
| 9388 | kfree(hpsa_sas_node); | ||
| 9389 | } | ||
| 9390 | |||
| 9391 | static struct hpsa_scsi_dev_t | ||
| 9392 | *hpsa_find_device_by_sas_rphy(struct ctlr_info *h, | ||
| 9393 | struct sas_rphy *rphy) | ||
| 9394 | { | ||
| 9395 | int i; | ||
| 9396 | struct hpsa_scsi_dev_t *device; | ||
| 9397 | |||
| 9398 | for (i = 0; i < h->ndevices; i++) { | ||
| 9399 | device = h->dev[i]; | ||
| 9400 | if (!device->sas_port) | ||
| 9401 | continue; | ||
| 9402 | if (device->sas_port->rphy == rphy) | ||
| 9403 | return device; | ||
| 9404 | } | ||
| 9405 | |||
| 9406 | return NULL; | ||
| 9407 | } | ||
| 9408 | |||
| 9409 | static int hpsa_add_sas_host(struct ctlr_info *h) | ||
| 9410 | { | ||
| 9411 | int rc; | ||
| 9412 | struct device *parent_dev; | ||
| 9413 | struct hpsa_sas_node *hpsa_sas_node; | ||
| 9414 | struct hpsa_sas_port *hpsa_sas_port; | ||
| 9415 | struct hpsa_sas_phy *hpsa_sas_phy; | ||
| 9416 | |||
| 9417 | parent_dev = &h->scsi_host->shost_gendev; | ||
| 9418 | |||
| 9419 | hpsa_sas_node = hpsa_alloc_sas_node(parent_dev); | ||
| 9420 | if (!hpsa_sas_node) | ||
| 9421 | return -ENOMEM; | ||
| 9422 | |||
| 9423 | hpsa_sas_port = hpsa_alloc_sas_port(hpsa_sas_node, h->sas_address); | ||
| 9424 | if (!hpsa_sas_port) { | ||
| 9425 | rc = -ENODEV; | ||
| 9426 | goto free_sas_node; | ||
| 9427 | } | ||
| 9428 | |||
| 9429 | hpsa_sas_phy = hpsa_alloc_sas_phy(hpsa_sas_port); | ||
| 9430 | if (!hpsa_sas_phy) { | ||
| 9431 | rc = -ENODEV; | ||
| 9432 | goto free_sas_port; | ||
| 9433 | } | ||
| 9434 | |||
| 9435 | rc = hpsa_sas_port_add_phy(hpsa_sas_phy); | ||
| 9436 | if (rc) | ||
| 9437 | goto free_sas_phy; | ||
| 9438 | |||
| 9439 | h->sas_host = hpsa_sas_node; | ||
| 9440 | |||
| 9441 | return 0; | ||
| 9442 | |||
| 9443 | free_sas_phy: | ||
| 9444 | hpsa_free_sas_phy(hpsa_sas_phy); | ||
| 9445 | free_sas_port: | ||
| 9446 | hpsa_free_sas_port(hpsa_sas_port); | ||
| 9447 | free_sas_node: | ||
| 9448 | hpsa_free_sas_node(hpsa_sas_node); | ||
| 9449 | |||
| 9450 | return rc; | ||
| 9451 | } | ||
| 9452 | |||
| 9453 | static void hpsa_delete_sas_host(struct ctlr_info *h) | ||
| 9454 | { | ||
| 9455 | hpsa_free_sas_node(h->sas_host); | ||
| 9456 | } | ||
| 9457 | |||
| 9458 | static int hpsa_add_sas_device(struct hpsa_sas_node *hpsa_sas_node, | ||
| 9459 | struct hpsa_scsi_dev_t *device) | ||
| 9460 | { | ||
| 9461 | int rc; | ||
| 9462 | struct hpsa_sas_port *hpsa_sas_port; | ||
| 9463 | struct sas_rphy *rphy; | ||
| 9464 | |||
| 9465 | hpsa_sas_port = hpsa_alloc_sas_port(hpsa_sas_node, device->sas_address); | ||
| 9466 | if (!hpsa_sas_port) | ||
| 9467 | return -ENOMEM; | ||
| 9468 | |||
| 9469 | rphy = sas_end_device_alloc(hpsa_sas_port->port); | ||
| 9470 | if (!rphy) { | ||
| 9471 | rc = -ENODEV; | ||
| 9472 | goto free_sas_port; | ||
| 9473 | } | ||
| 9474 | |||
| 9475 | hpsa_sas_port->rphy = rphy; | ||
| 9476 | device->sas_port = hpsa_sas_port; | ||
| 9477 | |||
| 9478 | rc = hpsa_sas_port_add_rphy(hpsa_sas_port, rphy); | ||
| 9479 | if (rc) | ||
| 9480 | goto free_sas_port; | ||
| 9481 | |||
| 9482 | return 0; | ||
| 9483 | |||
| 9484 | free_sas_port: | ||
| 9485 | hpsa_free_sas_port(hpsa_sas_port); | ||
| 9486 | device->sas_port = NULL; | ||
| 9487 | |||
| 9488 | return rc; | ||
| 9489 | } | ||
| 9490 | |||
| 9491 | static void hpsa_remove_sas_device(struct hpsa_scsi_dev_t *device) | ||
| 9492 | { | ||
| 9493 | if (device->sas_port) { | ||
| 9494 | hpsa_free_sas_port(device->sas_port); | ||
| 9495 | device->sas_port = NULL; | ||
| 9496 | } | ||
| 9497 | } | ||
| 9498 | |||
| 9499 | static int | ||
| 9500 | hpsa_sas_get_linkerrors(struct sas_phy *phy) | ||
| 9501 | { | ||
| 9502 | return 0; | ||
| 9503 | } | ||
| 9504 | |||
| 9505 | static int | ||
| 9506 | hpsa_sas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier) | ||
| 9507 | { | ||
| 9508 | return 0; | ||
| 9509 | } | ||
| 9510 | |||
| 9511 | static int | ||
| 9512 | hpsa_sas_get_bay_identifier(struct sas_rphy *rphy) | ||
| 9513 | { | ||
| 9514 | return -ENXIO; | ||
| 9515 | } | ||
| 9516 | |||
| 9517 | static int | ||
| 9518 | hpsa_sas_phy_reset(struct sas_phy *phy, int hard_reset) | ||
| 9519 | { | ||
| 9520 | return 0; | ||
| 9521 | } | ||
| 9522 | |||
| 9523 | static int | ||
| 9524 | hpsa_sas_phy_enable(struct sas_phy *phy, int enable) | ||
| 9525 | { | ||
| 9526 | return 0; | ||
| 9527 | } | ||
| 9528 | |||
| 9529 | static int | ||
| 9530 | hpsa_sas_phy_setup(struct sas_phy *phy) | ||
| 9531 | { | ||
| 9532 | return 0; | ||
| 9533 | } | ||
| 9534 | |||
| 9535 | static void | ||
| 9536 | hpsa_sas_phy_release(struct sas_phy *phy) | ||
| 9537 | { | ||
| 9538 | } | ||
| 9539 | |||
| 9540 | static int | ||
| 9541 | hpsa_sas_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates) | ||
| 9542 | { | ||
| 9543 | return -EINVAL; | ||
| 9544 | } | ||
| 9545 | |||
| 9546 | /* SMP = Serial Management Protocol */ | ||
| 9547 | static int | ||
| 9548 | hpsa_sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, | ||
| 9549 | struct request *req) | ||
| 9550 | { | ||
| 9551 | return -EINVAL; | ||
| 9552 | } | ||
| 9553 | |||
| 9554 | static struct sas_function_template hpsa_sas_transport_functions = { | ||
| 9555 | .get_linkerrors = hpsa_sas_get_linkerrors, | ||
| 9556 | .get_enclosure_identifier = hpsa_sas_get_enclosure_identifier, | ||
| 9557 | .get_bay_identifier = hpsa_sas_get_bay_identifier, | ||
| 9558 | .phy_reset = hpsa_sas_phy_reset, | ||
| 9559 | .phy_enable = hpsa_sas_phy_enable, | ||
| 9560 | .phy_setup = hpsa_sas_phy_setup, | ||
| 9561 | .phy_release = hpsa_sas_phy_release, | ||
| 9562 | .set_phy_speed = hpsa_sas_phy_speed, | ||
| 9563 | .smp_handler = hpsa_sas_smp_handler, | ||
| 9564 | }; | ||
| 9565 | |||
| 8761 | /* | 9566 | /* |
| 8762 | * This is it. Register the PCI driver information for the cards we control | 9567 | * This is it. Register the PCI driver information for the cards we control |
| 8763 | * the OS will call our registered routines when it finds one of our cards. | 9568 | * the OS will call our registered routines when it finds one of our cards. |
| 8764 | */ | 9569 | */ |
| 8765 | static int __init hpsa_init(void) | 9570 | static int __init hpsa_init(void) |
| 8766 | { | 9571 | { |
| 8767 | return pci_register_driver(&hpsa_pci_driver); | 9572 | int rc; |
| 9573 | |||
| 9574 | hpsa_sas_transport_template = | ||
| 9575 | sas_attach_transport(&hpsa_sas_transport_functions); | ||
| 9576 | if (!hpsa_sas_transport_template) | ||
| 9577 | return -ENODEV; | ||
| 9578 | |||
| 9579 | rc = pci_register_driver(&hpsa_pci_driver); | ||
| 9580 | |||
| 9581 | if (rc) | ||
| 9582 | sas_release_transport(hpsa_sas_transport_template); | ||
| 9583 | |||
| 9584 | return rc; | ||
| 8768 | } | 9585 | } |
| 8769 | 9586 | ||
| 8770 | static void __exit hpsa_cleanup(void) | 9587 | static void __exit hpsa_cleanup(void) |
| 8771 | { | 9588 | { |
| 8772 | pci_unregister_driver(&hpsa_pci_driver); | 9589 | pci_unregister_driver(&hpsa_pci_driver); |
| 9590 | sas_release_transport(hpsa_sas_transport_template); | ||
| 8773 | } | 9591 | } |
| 8774 | 9592 | ||
| 8775 | static void __attribute__((unused)) verify_offsets(void) | 9593 | static void __attribute__((unused)) verify_offsets(void) |
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h index 27debb363529..ae5beda1bdb5 100644 --- a/drivers/scsi/hpsa.h +++ b/drivers/scsi/hpsa.h | |||
| @@ -33,12 +33,38 @@ struct access_method { | |||
| 33 | unsigned long (*command_completed)(struct ctlr_info *h, u8 q); | 33 | unsigned long (*command_completed)(struct ctlr_info *h, u8 q); |
| 34 | }; | 34 | }; |
| 35 | 35 | ||
| 36 | /* for SAS hosts and SAS expanders */ | ||
| 37 | struct hpsa_sas_node { | ||
| 38 | struct device *parent_dev; | ||
| 39 | struct list_head port_list_head; | ||
| 40 | }; | ||
| 41 | |||
| 42 | struct hpsa_sas_port { | ||
| 43 | struct list_head port_list_entry; | ||
| 44 | u64 sas_address; | ||
| 45 | struct sas_port *port; | ||
| 46 | int next_phy_index; | ||
| 47 | struct list_head phy_list_head; | ||
| 48 | struct hpsa_sas_node *parent_node; | ||
| 49 | struct sas_rphy *rphy; | ||
| 50 | }; | ||
| 51 | |||
| 52 | struct hpsa_sas_phy { | ||
| 53 | struct list_head phy_list_entry; | ||
| 54 | struct sas_phy *phy; | ||
| 55 | struct hpsa_sas_port *parent_port; | ||
| 56 | bool added_to_port; | ||
| 57 | }; | ||
| 58 | |||
| 36 | struct hpsa_scsi_dev_t { | 59 | struct hpsa_scsi_dev_t { |
| 37 | int devtype; | 60 | unsigned int devtype; |
| 38 | int bus, target, lun; /* as presented to the OS */ | 61 | int bus, target, lun; /* as presented to the OS */ |
| 39 | unsigned char scsi3addr[8]; /* as presented to the HW */ | 62 | unsigned char scsi3addr[8]; /* as presented to the HW */ |
| 63 | u8 physical_device : 1; | ||
| 64 | u8 expose_device; | ||
| 40 | #define RAID_CTLR_LUNID "\0\0\0\0\0\0\0\0" | 65 | #define RAID_CTLR_LUNID "\0\0\0\0\0\0\0\0" |
| 41 | unsigned char device_id[16]; /* from inquiry pg. 0x83 */ | 66 | unsigned char device_id[16]; /* from inquiry pg. 0x83 */ |
| 67 | u64 sas_address; | ||
| 42 | unsigned char vendor[8]; /* bytes 8-15 of inquiry data */ | 68 | unsigned char vendor[8]; /* bytes 8-15 of inquiry data */ |
| 43 | unsigned char model[16]; /* bytes 16-31 of inquiry data */ | 69 | unsigned char model[16]; /* bytes 16-31 of inquiry data */ |
| 44 | unsigned char raid_level; /* from inquiry page 0xC1 */ | 70 | unsigned char raid_level; /* from inquiry page 0xC1 */ |
| @@ -75,11 +101,8 @@ struct hpsa_scsi_dev_t { | |||
| 75 | struct hpsa_scsi_dev_t *phys_disk[RAID_MAP_MAX_ENTRIES]; | 101 | struct hpsa_scsi_dev_t *phys_disk[RAID_MAP_MAX_ENTRIES]; |
| 76 | int nphysical_disks; | 102 | int nphysical_disks; |
| 77 | int supports_aborts; | 103 | int supports_aborts; |
| 78 | #define HPSA_DO_NOT_EXPOSE 0x0 | 104 | struct hpsa_sas_port *sas_port; |
| 79 | #define HPSA_SG_ATTACH 0x1 | 105 | int external; /* 1-from external array 0-not <0-unknown */ |
| 80 | #define HPSA_ULD_ATTACH 0x2 | ||
| 81 | #define HPSA_SCSI_ADD (HPSA_SG_ATTACH | HPSA_ULD_ATTACH) | ||
| 82 | u8 expose_state; | ||
| 83 | }; | 106 | }; |
| 84 | 107 | ||
| 85 | struct reply_queue_buffer { | 108 | struct reply_queue_buffer { |
| @@ -136,6 +159,7 @@ struct ctlr_info { | |||
| 136 | char *product_name; | 159 | char *product_name; |
| 137 | struct pci_dev *pdev; | 160 | struct pci_dev *pdev; |
| 138 | u32 board_id; | 161 | u32 board_id; |
| 162 | u64 sas_address; | ||
| 139 | void __iomem *vaddr; | 163 | void __iomem *vaddr; |
| 140 | unsigned long paddr; | 164 | unsigned long paddr; |
| 141 | int nr_cmds; /* Number of commands allowed on this controller */ | 165 | int nr_cmds; /* Number of commands allowed on this controller */ |
| @@ -262,7 +286,10 @@ struct ctlr_info { | |||
| 262 | spinlock_t offline_device_lock; | 286 | spinlock_t offline_device_lock; |
| 263 | struct list_head offline_device_list; | 287 | struct list_head offline_device_list; |
| 264 | int acciopath_status; | 288 | int acciopath_status; |
| 289 | int drv_req_rescan; | ||
| 265 | int raid_offload_debug; | 290 | int raid_offload_debug; |
| 291 | int discovery_polling; | ||
| 292 | struct ReportLUNdata *lastlogicals; | ||
| 266 | int needs_abort_tags_swizzled; | 293 | int needs_abort_tags_swizzled; |
| 267 | struct workqueue_struct *resubmit_wq; | 294 | struct workqueue_struct *resubmit_wq; |
| 268 | struct workqueue_struct *rescan_ctlr_wq; | 295 | struct workqueue_struct *rescan_ctlr_wq; |
| @@ -270,6 +297,8 @@ struct ctlr_info { | |||
| 270 | wait_queue_head_t abort_cmd_wait_queue; | 297 | wait_queue_head_t abort_cmd_wait_queue; |
| 271 | wait_queue_head_t event_sync_wait_queue; | 298 | wait_queue_head_t event_sync_wait_queue; |
| 272 | struct mutex reset_mutex; | 299 | struct mutex reset_mutex; |
| 300 | u8 reset_in_progress; | ||
| 301 | struct hpsa_sas_node *sas_host; | ||
| 273 | }; | 302 | }; |
| 274 | 303 | ||
| 275 | struct offline_device_entry { | 304 | struct offline_device_entry { |
| @@ -283,6 +312,7 @@ struct offline_device_entry { | |||
| 283 | #define HPSA_RESET_TYPE_BUS 0x01 | 312 | #define HPSA_RESET_TYPE_BUS 0x01 |
| 284 | #define HPSA_RESET_TYPE_TARGET 0x03 | 313 | #define HPSA_RESET_TYPE_TARGET 0x03 |
| 285 | #define HPSA_RESET_TYPE_LUN 0x04 | 314 | #define HPSA_RESET_TYPE_LUN 0x04 |
| 315 | #define HPSA_PHYS_TARGET_RESET 0x99 /* not defined by cciss spec */ | ||
| 286 | #define HPSA_MSG_SEND_RETRY_LIMIT 10 | 316 | #define HPSA_MSG_SEND_RETRY_LIMIT 10 |
| 287 | #define HPSA_MSG_SEND_RETRY_INTERVAL_MSECS (10000) | 317 | #define HPSA_MSG_SEND_RETRY_INTERVAL_MSECS (10000) |
| 288 | 318 | ||
| @@ -367,6 +397,11 @@ struct offline_device_entry { | |||
| 367 | #define IOACCEL2_INBOUND_POSTQ_64_LOW 0xd0 | 397 | #define IOACCEL2_INBOUND_POSTQ_64_LOW 0xd0 |
| 368 | #define IOACCEL2_INBOUND_POSTQ_64_HI 0xd4 | 398 | #define IOACCEL2_INBOUND_POSTQ_64_HI 0xd4 |
| 369 | 399 | ||
| 400 | #define HPSA_PHYSICAL_DEVICE_BUS 0 | ||
| 401 | #define HPSA_RAID_VOLUME_BUS 1 | ||
| 402 | #define HPSA_EXTERNAL_RAID_VOLUME_BUS 2 | ||
| 403 | #define HPSA_HBA_BUS 3 | ||
| 404 | |||
| 370 | /* | 405 | /* |
| 371 | Send the command to the hardware | 406 | Send the command to the hardware |
| 372 | */ | 407 | */ |
diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h index 47c756ba8dce..d92ef0d352b5 100644 --- a/drivers/scsi/hpsa_cmd.h +++ b/drivers/scsi/hpsa_cmd.h | |||
| @@ -260,8 +260,6 @@ struct ext_report_lun_entry { | |||
| 260 | u8 wwid[8]; | 260 | u8 wwid[8]; |
| 261 | u8 device_type; | 261 | u8 device_type; |
| 262 | u8 device_flags; | 262 | u8 device_flags; |
| 263 | #define NON_DISK_PHYS_DEV(x) ((x)[17] & 0x01) | ||
| 264 | #define PHYS_IOACCEL(x) ((x)[17] & 0x08) | ||
| 265 | u8 lun_count; /* multi-lun device, how many luns */ | 263 | u8 lun_count; /* multi-lun device, how many luns */ |
| 266 | u8 redundant_paths; | 264 | u8 redundant_paths; |
| 267 | u32 ioaccel_handle; /* ioaccel1 only uses lower 16 bits */ | 265 | u32 ioaccel_handle; /* ioaccel1 only uses lower 16 bits */ |
| @@ -288,6 +286,11 @@ struct SenseSubsystem_info { | |||
| 288 | #define BMIC_FLASH_FIRMWARE 0xF7 | 286 | #define BMIC_FLASH_FIRMWARE 0xF7 |
| 289 | #define BMIC_SENSE_CONTROLLER_PARAMETERS 0x64 | 287 | #define BMIC_SENSE_CONTROLLER_PARAMETERS 0x64 |
| 290 | #define BMIC_IDENTIFY_PHYSICAL_DEVICE 0x15 | 288 | #define BMIC_IDENTIFY_PHYSICAL_DEVICE 0x15 |
| 289 | #define BMIC_IDENTIFY_CONTROLLER 0x11 | ||
| 290 | #define BMIC_SET_DIAG_OPTIONS 0xF4 | ||
| 291 | #define BMIC_SENSE_DIAG_OPTIONS 0xF5 | ||
| 292 | #define HPSA_DIAG_OPTS_DISABLE_RLD_CACHING 0x40000000 | ||
| 293 | #define BMIC_SENSE_SUBSYSTEM_INFORMATION 0x66 | ||
| 291 | 294 | ||
| 292 | /* Command List Structure */ | 295 | /* Command List Structure */ |
| 293 | union SCSI3Addr { | 296 | union SCSI3Addr { |
| @@ -684,6 +687,16 @@ struct hpsa_pci_info { | |||
| 684 | u32 board_id; | 687 | u32 board_id; |
| 685 | }; | 688 | }; |
| 686 | 689 | ||
| 690 | struct bmic_identify_controller { | ||
| 691 | u8 configured_logical_drive_count; /* offset 0 */ | ||
| 692 | u8 pad1[153]; | ||
| 693 | __le16 extended_logical_unit_count; /* offset 154 */ | ||
| 694 | u8 pad2[136]; | ||
| 695 | u8 controller_mode; /* offset 292 */ | ||
| 696 | u8 pad3[32]; | ||
| 697 | }; | ||
| 698 | |||
| 699 | |||
| 687 | struct bmic_identify_physical_device { | 700 | struct bmic_identify_physical_device { |
| 688 | u8 scsi_bus; /* SCSI Bus number on controller */ | 701 | u8 scsi_bus; /* SCSI Bus number on controller */ |
| 689 | u8 scsi_id; /* SCSI ID on this bus */ | 702 | u8 scsi_id; /* SCSI ID on this bus */ |
| @@ -816,5 +829,18 @@ struct bmic_identify_physical_device { | |||
| 816 | u8 padding[112]; | 829 | u8 padding[112]; |
| 817 | }; | 830 | }; |
| 818 | 831 | ||
| 832 | struct bmic_sense_subsystem_info { | ||
| 833 | u8 primary_slot_number; | ||
| 834 | u8 reserved[3]; | ||
| 835 | u8 chasis_serial_number[32]; | ||
| 836 | u8 primary_world_wide_id[8]; | ||
| 837 | u8 primary_array_serial_number[32]; /* NULL terminated */ | ||
| 838 | u8 primary_cache_serial_number[32]; /* NULL terminated */ | ||
| 839 | u8 reserved_2[8]; | ||
| 840 | u8 secondary_array_serial_number[32]; | ||
| 841 | u8 secondary_cache_serial_number[32]; | ||
| 842 | u8 pad[332]; | ||
| 843 | }; | ||
| 844 | |||
| 819 | #pragma pack() | 845 | #pragma pack() |
| 820 | #endif /* HPSA_CMD_H */ | 846 | #endif /* HPSA_CMD_H */ |
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 6a41c36b16b0..adfef9db6f1e 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c | |||
| @@ -106,9 +106,9 @@ MODULE_LICENSE("GPL"); | |||
| 106 | MODULE_VERSION(IBMVSCSI_VERSION); | 106 | MODULE_VERSION(IBMVSCSI_VERSION); |
| 107 | 107 | ||
| 108 | module_param_named(max_id, max_id, int, S_IRUGO | S_IWUSR); | 108 | module_param_named(max_id, max_id, int, S_IRUGO | S_IWUSR); |
| 109 | MODULE_PARM_DESC(max_id, "Largest ID value for each channel"); | 109 | MODULE_PARM_DESC(max_id, "Largest ID value for each channel [Default=64]"); |
| 110 | module_param_named(max_channel, max_channel, int, S_IRUGO | S_IWUSR); | 110 | module_param_named(max_channel, max_channel, int, S_IRUGO | S_IWUSR); |
| 111 | MODULE_PARM_DESC(max_channel, "Largest channel value"); | 111 | MODULE_PARM_DESC(max_channel, "Largest channel value [Default=3]"); |
| 112 | module_param_named(init_timeout, init_timeout, int, S_IRUGO | S_IWUSR); | 112 | module_param_named(init_timeout, init_timeout, int, S_IRUGO | S_IWUSR); |
| 113 | MODULE_PARM_DESC(init_timeout, "Initialization timeout in seconds"); | 113 | MODULE_PARM_DESC(init_timeout, "Initialization timeout in seconds"); |
| 114 | module_param_named(max_requests, max_requests, int, S_IRUGO); | 114 | module_param_named(max_requests, max_requests, int, S_IRUGO); |
| @@ -2289,11 +2289,15 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id) | |||
| 2289 | goto init_pool_failed; | 2289 | goto init_pool_failed; |
| 2290 | } | 2290 | } |
| 2291 | 2291 | ||
| 2292 | host->max_lun = 8; | 2292 | host->max_lun = IBMVSCSI_MAX_LUN; |
| 2293 | host->max_id = max_id; | 2293 | host->max_id = max_id; |
| 2294 | host->max_channel = max_channel; | 2294 | host->max_channel = max_channel; |
| 2295 | host->max_cmd_len = 16; | 2295 | host->max_cmd_len = 16; |
| 2296 | 2296 | ||
| 2297 | dev_info(dev, | ||
| 2298 | "Maximum ID: %d Maximum LUN: %llu Maximum Channel: %d\n", | ||
| 2299 | host->max_id, host->max_lun, host->max_channel); | ||
| 2300 | |||
| 2297 | if (scsi_add_host(hostdata->host, hostdata->dev)) | 2301 | if (scsi_add_host(hostdata->host, hostdata->dev)) |
| 2298 | goto add_host_failed; | 2302 | goto add_host_failed; |
| 2299 | 2303 | ||
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h index 7d64867c5dd1..1067367395cd 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.h +++ b/drivers/scsi/ibmvscsi/ibmvscsi.h | |||
| @@ -48,6 +48,7 @@ struct Scsi_Host; | |||
| 48 | #define IBMVSCSI_CMDS_PER_LUN_DEFAULT 16 | 48 | #define IBMVSCSI_CMDS_PER_LUN_DEFAULT 16 |
| 49 | #define IBMVSCSI_MAX_SECTORS_DEFAULT 256 /* 32 * 8 = default max I/O 32 pages */ | 49 | #define IBMVSCSI_MAX_SECTORS_DEFAULT 256 /* 32 * 8 = default max I/O 32 pages */ |
| 50 | #define IBMVSCSI_MAX_CMDS_PER_LUN 64 | 50 | #define IBMVSCSI_MAX_CMDS_PER_LUN 64 |
| 51 | #define IBMVSCSI_MAX_LUN 32 | ||
| 51 | 52 | ||
| 52 | /* ------------------------------------------------------------ | 53 | /* ------------------------------------------------------------ |
| 53 | * Data Structures | 54 | * Data Structures |
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 4f2c16778efa..536cd5a80422 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c | |||
| @@ -6363,15 +6363,19 @@ static int ipr_queuecommand(struct Scsi_Host *shost, | |||
| 6363 | ipr_cmd->scsi_cmd = scsi_cmd; | 6363 | ipr_cmd->scsi_cmd = scsi_cmd; |
| 6364 | ipr_cmd->done = ipr_scsi_eh_done; | 6364 | ipr_cmd->done = ipr_scsi_eh_done; |
| 6365 | 6365 | ||
| 6366 | if (ipr_is_gscsi(res) || ipr_is_vset_device(res)) { | 6366 | if (ipr_is_gscsi(res)) { |
| 6367 | if (scsi_cmd->underflow == 0) | 6367 | if (scsi_cmd->underflow == 0) |
| 6368 | ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_NO_ULEN_CHK; | 6368 | ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_NO_ULEN_CHK; |
| 6369 | 6369 | ||
| 6370 | ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_NO_LINK_DESC; | 6370 | if (res->reset_occurred) { |
| 6371 | if (ipr_is_gscsi(res) && res->reset_occurred) { | ||
| 6372 | res->reset_occurred = 0; | 6371 | res->reset_occurred = 0; |
| 6373 | ioarcb->cmd_pkt.flags_lo |= IPR_FLAGS_LO_DELAY_AFTER_RST; | 6372 | ioarcb->cmd_pkt.flags_lo |= IPR_FLAGS_LO_DELAY_AFTER_RST; |
| 6374 | } | 6373 | } |
| 6374 | } | ||
| 6375 | |||
| 6376 | if (ipr_is_gscsi(res) || ipr_is_vset_device(res)) { | ||
| 6377 | ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_NO_LINK_DESC; | ||
| 6378 | |||
| 6375 | ioarcb->cmd_pkt.flags_lo |= IPR_FLAGS_LO_ALIGNED_BFR; | 6379 | ioarcb->cmd_pkt.flags_lo |= IPR_FLAGS_LO_ALIGNED_BFR; |
| 6376 | if (scsi_cmd->flags & SCMD_TAGGED) | 6380 | if (scsi_cmd->flags & SCMD_TAGGED) |
| 6377 | ioarcb->cmd_pkt.flags_lo |= IPR_FLAGS_LO_SIMPLE_TASK; | 6381 | ioarcb->cmd_pkt.flags_lo |= IPR_FLAGS_LO_SIMPLE_TASK; |
| @@ -7670,6 +7674,63 @@ static int ipr_ioafp_query_ioa_cfg(struct ipr_cmnd *ipr_cmd) | |||
| 7670 | return IPR_RC_JOB_RETURN; | 7674 | return IPR_RC_JOB_RETURN; |
| 7671 | } | 7675 | } |
| 7672 | 7676 | ||
| 7677 | static int ipr_ioa_service_action_failed(struct ipr_cmnd *ipr_cmd) | ||
| 7678 | { | ||
| 7679 | u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); | ||
| 7680 | |||
| 7681 | if (ioasc == IPR_IOASC_IR_INVALID_REQ_TYPE_OR_PKT) | ||
| 7682 | return IPR_RC_JOB_CONTINUE; | ||
| 7683 | |||
| 7684 | return ipr_reset_cmd_failed(ipr_cmd); | ||
| 7685 | } | ||
| 7686 | |||
| 7687 | static void ipr_build_ioa_service_action(struct ipr_cmnd *ipr_cmd, | ||
| 7688 | __be32 res_handle, u8 sa_code) | ||
| 7689 | { | ||
| 7690 | struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb; | ||
| 7691 | |||
| 7692 | ioarcb->res_handle = res_handle; | ||
| 7693 | ioarcb->cmd_pkt.cdb[0] = IPR_IOA_SERVICE_ACTION; | ||
| 7694 | ioarcb->cmd_pkt.cdb[1] = sa_code; | ||
| 7695 | ioarcb->cmd_pkt.request_type = IPR_RQTYPE_IOACMD; | ||
| 7696 | } | ||
| 7697 | |||
| 7698 | /** | ||
| 7699 | * ipr_ioafp_set_caching_parameters - Issue Set Cache parameters service | ||
| 7700 | * action | ||
| 7701 | * | ||
| 7702 | * Return value: | ||
| 7703 | * none | ||
| 7704 | **/ | ||
| 7705 | static int ipr_ioafp_set_caching_parameters(struct ipr_cmnd *ipr_cmd) | ||
| 7706 | { | ||
| 7707 | struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb; | ||
| 7708 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; | ||
| 7709 | struct ipr_inquiry_pageC4 *pageC4 = &ioa_cfg->vpd_cbs->pageC4_data; | ||
| 7710 | |||
| 7711 | ENTER; | ||
| 7712 | |||
| 7713 | ipr_cmd->job_step = ipr_ioafp_query_ioa_cfg; | ||
| 7714 | |||
| 7715 | if (pageC4->cache_cap[0] & IPR_CAP_SYNC_CACHE) { | ||
| 7716 | ipr_build_ioa_service_action(ipr_cmd, | ||
| 7717 | cpu_to_be32(IPR_IOA_RES_HANDLE), | ||
| 7718 | IPR_IOA_SA_CHANGE_CACHE_PARAMS); | ||
| 7719 | |||
| 7720 | ioarcb->cmd_pkt.cdb[2] = 0x40; | ||
| 7721 | |||
| 7722 | ipr_cmd->job_step_failed = ipr_ioa_service_action_failed; | ||
| 7723 | ipr_do_req(ipr_cmd, ipr_reset_ioa_job, ipr_timeout, | ||
| 7724 | IPR_SET_SUP_DEVICE_TIMEOUT); | ||
| 7725 | |||
| 7726 | LEAVE; | ||
| 7727 | return IPR_RC_JOB_RETURN; | ||
| 7728 | } | ||
| 7729 | |||
| 7730 | LEAVE; | ||
| 7731 | return IPR_RC_JOB_CONTINUE; | ||
| 7732 | } | ||
| 7733 | |||
| 7673 | /** | 7734 | /** |
| 7674 | * ipr_ioafp_inquiry - Send an Inquiry to the adapter. | 7735 | * ipr_ioafp_inquiry - Send an Inquiry to the adapter. |
| 7675 | * @ipr_cmd: ipr command struct | 7736 | * @ipr_cmd: ipr command struct |
| @@ -7721,6 +7782,39 @@ static int ipr_inquiry_page_supported(struct ipr_inquiry_page0 *page0, u8 page) | |||
| 7721 | } | 7782 | } |
| 7722 | 7783 | ||
| 7723 | /** | 7784 | /** |
| 7785 | * ipr_ioafp_pageC4_inquiry - Send a Page 0xC4 Inquiry to the adapter. | ||
| 7786 | * @ipr_cmd: ipr command struct | ||
| 7787 | * | ||
| 7788 | * This function sends a Page 0xC4 inquiry to the adapter | ||
| 7789 | * to retrieve software VPD information. | ||
| 7790 | * | ||
| 7791 | * Return value: | ||
| 7792 | * IPR_RC_JOB_CONTINUE / IPR_RC_JOB_RETURN | ||
| 7793 | **/ | ||
| 7794 | static int ipr_ioafp_pageC4_inquiry(struct ipr_cmnd *ipr_cmd) | ||
| 7795 | { | ||
| 7796 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; | ||
| 7797 | struct ipr_inquiry_page0 *page0 = &ioa_cfg->vpd_cbs->page0_data; | ||
| 7798 | struct ipr_inquiry_pageC4 *pageC4 = &ioa_cfg->vpd_cbs->pageC4_data; | ||
| 7799 | |||
| 7800 | ENTER; | ||
| 7801 | ipr_cmd->job_step = ipr_ioafp_set_caching_parameters; | ||
| 7802 | memset(pageC4, 0, sizeof(*pageC4)); | ||
| 7803 | |||
| 7804 | if (ipr_inquiry_page_supported(page0, 0xC4)) { | ||
| 7805 | ipr_ioafp_inquiry(ipr_cmd, 1, 0xC4, | ||
| 7806 | (ioa_cfg->vpd_cbs_dma | ||
| 7807 | + offsetof(struct ipr_misc_cbs, | ||
| 7808 | pageC4_data)), | ||
| 7809 | sizeof(struct ipr_inquiry_pageC4)); | ||
| 7810 | return IPR_RC_JOB_RETURN; | ||
| 7811 | } | ||
| 7812 | |||
| 7813 | LEAVE; | ||
| 7814 | return IPR_RC_JOB_CONTINUE; | ||
| 7815 | } | ||
| 7816 | |||
| 7817 | /** | ||
| 7724 | * ipr_ioafp_cap_inquiry - Send a Page 0xD0 Inquiry to the adapter. | 7818 | * ipr_ioafp_cap_inquiry - Send a Page 0xD0 Inquiry to the adapter. |
| 7725 | * @ipr_cmd: ipr command struct | 7819 | * @ipr_cmd: ipr command struct |
| 7726 | * | 7820 | * |
| @@ -7737,7 +7831,7 @@ static int ipr_ioafp_cap_inquiry(struct ipr_cmnd *ipr_cmd) | |||
| 7737 | struct ipr_inquiry_cap *cap = &ioa_cfg->vpd_cbs->cap; | 7831 | struct ipr_inquiry_cap *cap = &ioa_cfg->vpd_cbs->cap; |
| 7738 | 7832 | ||
| 7739 | ENTER; | 7833 | ENTER; |
| 7740 | ipr_cmd->job_step = ipr_ioafp_query_ioa_cfg; | 7834 | ipr_cmd->job_step = ipr_ioafp_pageC4_inquiry; |
| 7741 | memset(cap, 0, sizeof(*cap)); | 7835 | memset(cap, 0, sizeof(*cap)); |
| 7742 | 7836 | ||
| 7743 | if (ipr_inquiry_page_supported(page0, 0xD0)) { | 7837 | if (ipr_inquiry_page_supported(page0, 0xD0)) { |
| @@ -8276,6 +8370,42 @@ static int ipr_reset_get_unit_check_job(struct ipr_cmnd *ipr_cmd) | |||
| 8276 | return IPR_RC_JOB_RETURN; | 8370 | return IPR_RC_JOB_RETURN; |
| 8277 | } | 8371 | } |
| 8278 | 8372 | ||
| 8373 | static int ipr_dump_mailbox_wait(struct ipr_cmnd *ipr_cmd) | ||
| 8374 | { | ||
| 8375 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; | ||
| 8376 | |||
| 8377 | ENTER; | ||
| 8378 | |||
| 8379 | if (ioa_cfg->sdt_state != GET_DUMP) | ||
| 8380 | return IPR_RC_JOB_RETURN; | ||
| 8381 | |||
| 8382 | if (!ioa_cfg->sis64 || !ipr_cmd->u.time_left || | ||
| 8383 | (readl(ioa_cfg->regs.sense_interrupt_reg) & | ||
| 8384 | IPR_PCII_MAILBOX_STABLE)) { | ||
| 8385 | |||
| 8386 | if (!ipr_cmd->u.time_left) | ||
| 8387 | dev_err(&ioa_cfg->pdev->dev, | ||
| 8388 | "Timed out waiting for Mailbox register.\n"); | ||
| 8389 | |||
| 8390 | ioa_cfg->sdt_state = READ_DUMP; | ||
| 8391 | ioa_cfg->dump_timeout = 0; | ||
| 8392 | if (ioa_cfg->sis64) | ||
| 8393 | ipr_reset_start_timer(ipr_cmd, IPR_SIS64_DUMP_TIMEOUT); | ||
| 8394 | else | ||
| 8395 | ipr_reset_start_timer(ipr_cmd, IPR_SIS32_DUMP_TIMEOUT); | ||
| 8396 | ipr_cmd->job_step = ipr_reset_wait_for_dump; | ||
| 8397 | schedule_work(&ioa_cfg->work_q); | ||
| 8398 | |||
| 8399 | } else { | ||
| 8400 | ipr_cmd->u.time_left -= IPR_CHECK_FOR_RESET_TIMEOUT; | ||
| 8401 | ipr_reset_start_timer(ipr_cmd, | ||
| 8402 | IPR_CHECK_FOR_RESET_TIMEOUT); | ||
| 8403 | } | ||
| 8404 | |||
| 8405 | LEAVE; | ||
| 8406 | return IPR_RC_JOB_RETURN; | ||
| 8407 | } | ||
| 8408 | |||
| 8279 | /** | 8409 | /** |
| 8280 | * ipr_reset_restore_cfg_space - Restore PCI config space. | 8410 | * ipr_reset_restore_cfg_space - Restore PCI config space. |
| 8281 | * @ipr_cmd: ipr command struct | 8411 | * @ipr_cmd: ipr command struct |
| @@ -8325,20 +8455,11 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd) | |||
| 8325 | 8455 | ||
| 8326 | if (ioa_cfg->in_ioa_bringdown) { | 8456 | if (ioa_cfg->in_ioa_bringdown) { |
| 8327 | ipr_cmd->job_step = ipr_ioa_bringdown_done; | 8457 | ipr_cmd->job_step = ipr_ioa_bringdown_done; |
| 8458 | } else if (ioa_cfg->sdt_state == GET_DUMP) { | ||
| 8459 | ipr_cmd->job_step = ipr_dump_mailbox_wait; | ||
| 8460 | ipr_cmd->u.time_left = IPR_WAIT_FOR_MAILBOX; | ||
| 8328 | } else { | 8461 | } else { |
| 8329 | ipr_cmd->job_step = ipr_reset_enable_ioa; | 8462 | ipr_cmd->job_step = ipr_reset_enable_ioa; |
| 8330 | |||
| 8331 | if (GET_DUMP == ioa_cfg->sdt_state) { | ||
| 8332 | ioa_cfg->sdt_state = READ_DUMP; | ||
| 8333 | ioa_cfg->dump_timeout = 0; | ||
| 8334 | if (ioa_cfg->sis64) | ||
| 8335 | ipr_reset_start_timer(ipr_cmd, IPR_SIS64_DUMP_TIMEOUT); | ||
| 8336 | else | ||
| 8337 | ipr_reset_start_timer(ipr_cmd, IPR_SIS32_DUMP_TIMEOUT); | ||
| 8338 | ipr_cmd->job_step = ipr_reset_wait_for_dump; | ||
| 8339 | schedule_work(&ioa_cfg->work_q); | ||
| 8340 | return IPR_RC_JOB_RETURN; | ||
| 8341 | } | ||
| 8342 | } | 8463 | } |
| 8343 | 8464 | ||
| 8344 | LEAVE; | 8465 | LEAVE; |
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index e4fb17a58649..a34c7a5a995e 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h | |||
| @@ -39,8 +39,8 @@ | |||
| 39 | /* | 39 | /* |
| 40 | * Literals | 40 | * Literals |
| 41 | */ | 41 | */ |
| 42 | #define IPR_DRIVER_VERSION "2.6.2" | 42 | #define IPR_DRIVER_VERSION "2.6.3" |
| 43 | #define IPR_DRIVER_DATE "(June 11, 2015)" | 43 | #define IPR_DRIVER_DATE "(October 17, 2015)" |
| 44 | 44 | ||
| 45 | /* | 45 | /* |
| 46 | * IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding | 46 | * IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding |
| @@ -216,6 +216,10 @@ | |||
| 216 | #define IPR_SET_ALL_SUPPORTED_DEVICES 0x80 | 216 | #define IPR_SET_ALL_SUPPORTED_DEVICES 0x80 |
| 217 | #define IPR_IOA_SHUTDOWN 0xF7 | 217 | #define IPR_IOA_SHUTDOWN 0xF7 |
| 218 | #define IPR_WR_BUF_DOWNLOAD_AND_SAVE 0x05 | 218 | #define IPR_WR_BUF_DOWNLOAD_AND_SAVE 0x05 |
| 219 | #define IPR_IOA_SERVICE_ACTION 0xD2 | ||
| 220 | |||
| 221 | /* IOA Service Actions */ | ||
| 222 | #define IPR_IOA_SA_CHANGE_CACHE_PARAMS 0x14 | ||
| 219 | 223 | ||
| 220 | /* | 224 | /* |
| 221 | * Timeouts | 225 | * Timeouts |
| @@ -279,6 +283,9 @@ | |||
| 279 | #define IPR_IPL_INIT_STAGE_TIME_MASK 0x0000ffff | 283 | #define IPR_IPL_INIT_STAGE_TIME_MASK 0x0000ffff |
| 280 | #define IPR_PCII_IPL_STAGE_CHANGE (0x80000000 >> 0) | 284 | #define IPR_PCII_IPL_STAGE_CHANGE (0x80000000 >> 0) |
| 281 | 285 | ||
| 286 | #define IPR_PCII_MAILBOX_STABLE (0x80000000 >> 4) | ||
| 287 | #define IPR_WAIT_FOR_MAILBOX (2 * HZ) | ||
| 288 | |||
| 282 | #define IPR_PCII_IOA_TRANS_TO_OPER (0x80000000 >> 0) | 289 | #define IPR_PCII_IOA_TRANS_TO_OPER (0x80000000 >> 0) |
| 283 | #define IPR_PCII_IOARCB_XFER_FAILED (0x80000000 >> 3) | 290 | #define IPR_PCII_IOARCB_XFER_FAILED (0x80000000 >> 3) |
| 284 | #define IPR_PCII_IOA_UNIT_CHECKED (0x80000000 >> 4) | 291 | #define IPR_PCII_IOA_UNIT_CHECKED (0x80000000 >> 4) |
| @@ -846,6 +853,16 @@ struct ipr_inquiry_page0 { | |||
| 846 | u8 page[IPR_INQUIRY_PAGE0_ENTRIES]; | 853 | u8 page[IPR_INQUIRY_PAGE0_ENTRIES]; |
| 847 | }__attribute__((packed)); | 854 | }__attribute__((packed)); |
| 848 | 855 | ||
| 856 | struct ipr_inquiry_pageC4 { | ||
| 857 | u8 peri_qual_dev_type; | ||
| 858 | u8 page_code; | ||
| 859 | u8 reserved1; | ||
| 860 | u8 len; | ||
| 861 | u8 cache_cap[4]; | ||
| 862 | #define IPR_CAP_SYNC_CACHE 0x08 | ||
| 863 | u8 reserved2[20]; | ||
| 864 | } __packed; | ||
| 865 | |||
| 849 | struct ipr_hostrcb_device_data_entry { | 866 | struct ipr_hostrcb_device_data_entry { |
| 850 | struct ipr_vpd vpd; | 867 | struct ipr_vpd vpd; |
| 851 | struct ipr_res_addr dev_res_addr; | 868 | struct ipr_res_addr dev_res_addr; |
| @@ -1319,6 +1336,7 @@ struct ipr_misc_cbs { | |||
| 1319 | struct ipr_inquiry_page0 page0_data; | 1336 | struct ipr_inquiry_page0 page0_data; |
| 1320 | struct ipr_inquiry_page3 page3_data; | 1337 | struct ipr_inquiry_page3 page3_data; |
| 1321 | struct ipr_inquiry_cap cap; | 1338 | struct ipr_inquiry_cap cap; |
| 1339 | struct ipr_inquiry_pageC4 pageC4_data; | ||
| 1322 | struct ipr_mode_pages mode_pages; | 1340 | struct ipr_mode_pages mode_pages; |
| 1323 | struct ipr_supported_device supp_dev; | 1341 | struct ipr_supported_device supp_dev; |
| 1324 | }; | 1342 | }; |
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 2f973df72d9b..77128d680e3b 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c | |||
| @@ -271,11 +271,11 @@ static void isci_unregister(struct isci_host *isci_host) | |||
| 271 | if (!isci_host) | 271 | if (!isci_host) |
| 272 | return; | 272 | return; |
| 273 | 273 | ||
| 274 | shost = to_shost(isci_host); | ||
| 275 | scsi_remove_host(shost); | ||
| 274 | sas_unregister_ha(&isci_host->sas_ha); | 276 | sas_unregister_ha(&isci_host->sas_ha); |
| 275 | 277 | ||
| 276 | shost = to_shost(isci_host); | ||
| 277 | sas_remove_host(shost); | 278 | sas_remove_host(shost); |
| 278 | scsi_remove_host(shost); | ||
| 279 | scsi_host_put(shost); | 279 | scsi_host_put(shost); |
| 280 | } | 280 | } |
| 281 | 281 | ||
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index 20c37541963f..c0f7c8ce54aa 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h | |||
| @@ -35,8 +35,8 @@ | |||
| 35 | /* | 35 | /* |
| 36 | * MegaRAID SAS Driver meta data | 36 | * MegaRAID SAS Driver meta data |
| 37 | */ | 37 | */ |
| 38 | #define MEGASAS_VERSION "06.807.10.00-rc1" | 38 | #define MEGASAS_VERSION "06.808.16.00-rc1" |
| 39 | #define MEGASAS_RELDATE "March 6, 2015" | 39 | #define MEGASAS_RELDATE "Oct. 8, 2015" |
| 40 | 40 | ||
| 41 | /* | 41 | /* |
| 42 | * Device IDs | 42 | * Device IDs |
| @@ -52,6 +52,10 @@ | |||
| 52 | #define PCI_DEVICE_ID_LSI_PLASMA 0x002f | 52 | #define PCI_DEVICE_ID_LSI_PLASMA 0x002f |
| 53 | #define PCI_DEVICE_ID_LSI_INVADER 0x005d | 53 | #define PCI_DEVICE_ID_LSI_INVADER 0x005d |
| 54 | #define PCI_DEVICE_ID_LSI_FURY 0x005f | 54 | #define PCI_DEVICE_ID_LSI_FURY 0x005f |
| 55 | #define PCI_DEVICE_ID_LSI_INTRUDER 0x00ce | ||
| 56 | #define PCI_DEVICE_ID_LSI_INTRUDER_24 0x00cf | ||
| 57 | #define PCI_DEVICE_ID_LSI_CUTLASS_52 0x0052 | ||
| 58 | #define PCI_DEVICE_ID_LSI_CUTLASS_53 0x0053 | ||
| 55 | 59 | ||
| 56 | /* | 60 | /* |
| 57 | * Intel HBA SSDIDs | 61 | * Intel HBA SSDIDs |
| @@ -62,6 +66,14 @@ | |||
| 62 | #define MEGARAID_INTEL_RS3MC044_SSDID 0x9381 | 66 | #define MEGARAID_INTEL_RS3MC044_SSDID 0x9381 |
| 63 | #define MEGARAID_INTEL_RS3WC080_SSDID 0x9341 | 67 | #define MEGARAID_INTEL_RS3WC080_SSDID 0x9341 |
| 64 | #define MEGARAID_INTEL_RS3WC040_SSDID 0x9343 | 68 | #define MEGARAID_INTEL_RS3WC040_SSDID 0x9343 |
| 69 | #define MEGARAID_INTEL_RMS3BC160_SSDID 0x352B | ||
| 70 | |||
| 71 | /* | ||
| 72 | * Intruder HBA SSDIDs | ||
| 73 | */ | ||
| 74 | #define MEGARAID_INTRUDER_SSDID1 0x9371 | ||
| 75 | #define MEGARAID_INTRUDER_SSDID2 0x9390 | ||
| 76 | #define MEGARAID_INTRUDER_SSDID3 0x9370 | ||
| 65 | 77 | ||
| 66 | /* | 78 | /* |
| 67 | * Intel HBA branding | 79 | * Intel HBA branding |
| @@ -78,6 +90,8 @@ | |||
| 78 | "Intel(R) RAID Controller RS3WC080" | 90 | "Intel(R) RAID Controller RS3WC080" |
| 79 | #define MEGARAID_INTEL_RS3WC040_BRANDING \ | 91 | #define MEGARAID_INTEL_RS3WC040_BRANDING \ |
| 80 | "Intel(R) RAID Controller RS3WC040" | 92 | "Intel(R) RAID Controller RS3WC040" |
| 93 | #define MEGARAID_INTEL_RMS3BC160_BRANDING \ | ||
| 94 | "Intel(R) Integrated RAID Module RMS3BC160" | ||
| 81 | 95 | ||
| 82 | /* | 96 | /* |
| 83 | * ===================================== | 97 | * ===================================== |
| @@ -273,6 +287,16 @@ enum MFI_STAT { | |||
| 273 | MFI_STAT_INVALID_STATUS = 0xFF | 287 | MFI_STAT_INVALID_STATUS = 0xFF |
| 274 | }; | 288 | }; |
| 275 | 289 | ||
| 290 | enum mfi_evt_class { | ||
| 291 | MFI_EVT_CLASS_DEBUG = -2, | ||
| 292 | MFI_EVT_CLASS_PROGRESS = -1, | ||
| 293 | MFI_EVT_CLASS_INFO = 0, | ||
| 294 | MFI_EVT_CLASS_WARNING = 1, | ||
| 295 | MFI_EVT_CLASS_CRITICAL = 2, | ||
| 296 | MFI_EVT_CLASS_FATAL = 3, | ||
| 297 | MFI_EVT_CLASS_DEAD = 4 | ||
| 298 | }; | ||
| 299 | |||
| 276 | /* | 300 | /* |
| 277 | * Crash dump related defines | 301 | * Crash dump related defines |
| 278 | */ | 302 | */ |
| @@ -364,6 +388,8 @@ enum MR_EVT_ARGS { | |||
| 364 | MR_EVT_ARGS_GENERIC, | 388 | MR_EVT_ARGS_GENERIC, |
| 365 | }; | 389 | }; |
| 366 | 390 | ||
| 391 | |||
| 392 | #define SGE_BUFFER_SIZE 4096 | ||
| 367 | /* | 393 | /* |
| 368 | * define constants for device list query options | 394 | * define constants for device list query options |
| 369 | */ | 395 | */ |
| @@ -394,6 +420,7 @@ enum MR_LD_QUERY_TYPE { | |||
| 394 | #define MR_EVT_FOREIGN_CFG_IMPORTED 0x00db | 420 | #define MR_EVT_FOREIGN_CFG_IMPORTED 0x00db |
| 395 | #define MR_EVT_LD_OFFLINE 0x00fc | 421 | #define MR_EVT_LD_OFFLINE 0x00fc |
| 396 | #define MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED 0x0152 | 422 | #define MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED 0x0152 |
| 423 | #define MR_EVT_CTRL_PROP_CHANGED 0x012f | ||
| 397 | 424 | ||
| 398 | enum MR_PD_STATE { | 425 | enum MR_PD_STATE { |
| 399 | MR_PD_STATE_UNCONFIGURED_GOOD = 0x00, | 426 | MR_PD_STATE_UNCONFIGURED_GOOD = 0x00, |
| @@ -973,7 +1000,12 @@ struct megasas_ctrl_info { | |||
| 973 | 1000 | ||
| 974 | struct { | 1001 | struct { |
| 975 | #if defined(__BIG_ENDIAN_BITFIELD) | 1002 | #if defined(__BIG_ENDIAN_BITFIELD) |
| 976 | u32 reserved:12; | 1003 | u32 reserved:7; |
| 1004 | u32 useSeqNumJbodFP:1; | ||
| 1005 | u32 supportExtendedSSCSize:1; | ||
| 1006 | u32 supportDiskCacheSettingForSysPDs:1; | ||
| 1007 | u32 supportCPLDUpdate:1; | ||
| 1008 | u32 supportTTYLogCompression:1; | ||
| 977 | u32 discardCacheDuringLDDelete:1; | 1009 | u32 discardCacheDuringLDDelete:1; |
| 978 | u32 supportSecurityonJBOD:1; | 1010 | u32 supportSecurityonJBOD:1; |
| 979 | u32 supportCacheBypassModes:1; | 1011 | u32 supportCacheBypassModes:1; |
| @@ -1013,7 +1045,12 @@ struct megasas_ctrl_info { | |||
| 1013 | u32 supportCacheBypassModes:1; | 1045 | u32 supportCacheBypassModes:1; |
| 1014 | u32 supportSecurityonJBOD:1; | 1046 | u32 supportSecurityonJBOD:1; |
| 1015 | u32 discardCacheDuringLDDelete:1; | 1047 | u32 discardCacheDuringLDDelete:1; |
| 1016 | u32 reserved:12; | 1048 | u32 supportTTYLogCompression:1; |
| 1049 | u32 supportCPLDUpdate:1; | ||
| 1050 | u32 supportDiskCacheSettingForSysPDs:1; | ||
| 1051 | u32 supportExtendedSSCSize:1; | ||
| 1052 | u32 useSeqNumJbodFP:1; | ||
| 1053 | u32 reserved:7; | ||
| 1017 | #endif | 1054 | #endif |
| 1018 | } adapterOperations3; | 1055 | } adapterOperations3; |
| 1019 | 1056 | ||
| @@ -1229,7 +1266,9 @@ union megasas_sgl_frame { | |||
| 1229 | typedef union _MFI_CAPABILITIES { | 1266 | typedef union _MFI_CAPABILITIES { |
| 1230 | struct { | 1267 | struct { |
| 1231 | #if defined(__BIG_ENDIAN_BITFIELD) | 1268 | #if defined(__BIG_ENDIAN_BITFIELD) |
| 1232 | u32 reserved:25; | 1269 | u32 reserved:23; |
| 1270 | u32 support_ext_io_size:1; | ||
| 1271 | u32 support_ext_queue_depth:1; | ||
| 1233 | u32 security_protocol_cmds_fw:1; | 1272 | u32 security_protocol_cmds_fw:1; |
| 1234 | u32 support_core_affinity:1; | 1273 | u32 support_core_affinity:1; |
| 1235 | u32 support_ndrive_r1_lb:1; | 1274 | u32 support_ndrive_r1_lb:1; |
| @@ -1245,7 +1284,9 @@ typedef union _MFI_CAPABILITIES { | |||
| 1245 | u32 support_ndrive_r1_lb:1; | 1284 | u32 support_ndrive_r1_lb:1; |
| 1246 | u32 support_core_affinity:1; | 1285 | u32 support_core_affinity:1; |
| 1247 | u32 security_protocol_cmds_fw:1; | 1286 | u32 security_protocol_cmds_fw:1; |
| 1248 | u32 reserved:25; | 1287 | u32 support_ext_queue_depth:1; |
| 1288 | u32 support_ext_io_size:1; | ||
| 1289 | u32 reserved:23; | ||
| 1249 | #endif | 1290 | #endif |
| 1250 | } mfi_capabilities; | 1291 | } mfi_capabilities; |
| 1251 | __le32 reg; | 1292 | __le32 reg; |
| @@ -1690,6 +1731,7 @@ struct megasas_instance { | |||
| 1690 | u32 crash_dump_drv_support; | 1731 | u32 crash_dump_drv_support; |
| 1691 | u32 crash_dump_app_support; | 1732 | u32 crash_dump_app_support; |
| 1692 | u32 secure_jbod_support; | 1733 | u32 secure_jbod_support; |
| 1734 | bool use_seqnum_jbod_fp; /* Added for PD sequence */ | ||
| 1693 | spinlock_t crashdump_lock; | 1735 | spinlock_t crashdump_lock; |
| 1694 | 1736 | ||
| 1695 | struct megasas_register_set __iomem *reg_set; | 1737 | struct megasas_register_set __iomem *reg_set; |
| @@ -1748,6 +1790,7 @@ struct megasas_instance { | |||
| 1748 | u8 UnevenSpanSupport; | 1790 | u8 UnevenSpanSupport; |
| 1749 | 1791 | ||
| 1750 | u8 supportmax256vd; | 1792 | u8 supportmax256vd; |
| 1793 | u8 allow_fw_scan; | ||
| 1751 | u16 fw_supported_vd_count; | 1794 | u16 fw_supported_vd_count; |
| 1752 | u16 fw_supported_pd_count; | 1795 | u16 fw_supported_pd_count; |
| 1753 | 1796 | ||
| @@ -1769,7 +1812,9 @@ struct megasas_instance { | |||
| 1769 | struct msix_entry msixentry[MEGASAS_MAX_MSIX_QUEUES]; | 1812 | struct msix_entry msixentry[MEGASAS_MAX_MSIX_QUEUES]; |
| 1770 | struct megasas_irq_context irq_context[MEGASAS_MAX_MSIX_QUEUES]; | 1813 | struct megasas_irq_context irq_context[MEGASAS_MAX_MSIX_QUEUES]; |
| 1771 | u64 map_id; | 1814 | u64 map_id; |
| 1815 | u64 pd_seq_map_id; | ||
| 1772 | struct megasas_cmd *map_update_cmd; | 1816 | struct megasas_cmd *map_update_cmd; |
| 1817 | struct megasas_cmd *jbod_seq_cmd; | ||
| 1773 | unsigned long bar; | 1818 | unsigned long bar; |
| 1774 | long reset_flags; | 1819 | long reset_flags; |
| 1775 | struct mutex reset_mutex; | 1820 | struct mutex reset_mutex; |
| @@ -1780,6 +1825,7 @@ struct megasas_instance { | |||
| 1780 | char mpio; | 1825 | char mpio; |
| 1781 | u16 throttlequeuedepth; | 1826 | u16 throttlequeuedepth; |
| 1782 | u8 mask_interrupts; | 1827 | u8 mask_interrupts; |
| 1828 | u16 max_chain_frame_sz; | ||
| 1783 | u8 is_imr; | 1829 | u8 is_imr; |
| 1784 | bool dev_handle; | 1830 | bool dev_handle; |
| 1785 | }; | 1831 | }; |
| @@ -1985,6 +2031,9 @@ __le16 get_updated_dev_handle(struct megasas_instance *instance, | |||
| 1985 | void mr_update_load_balance_params(struct MR_DRV_RAID_MAP_ALL *map, | 2031 | void mr_update_load_balance_params(struct MR_DRV_RAID_MAP_ALL *map, |
| 1986 | struct LD_LOAD_BALANCE_INFO *lbInfo); | 2032 | struct LD_LOAD_BALANCE_INFO *lbInfo); |
| 1987 | int megasas_get_ctrl_info(struct megasas_instance *instance); | 2033 | int megasas_get_ctrl_info(struct megasas_instance *instance); |
| 2034 | /* PD sequence */ | ||
| 2035 | int | ||
| 2036 | megasas_sync_pd_seq_num(struct megasas_instance *instance, bool pend); | ||
| 1988 | int megasas_set_crash_dump_params(struct megasas_instance *instance, | 2037 | int megasas_set_crash_dump_params(struct megasas_instance *instance, |
| 1989 | u8 crash_buf_state); | 2038 | u8 crash_buf_state); |
| 1990 | void megasas_free_host_crash_buffer(struct megasas_instance *instance); | 2039 | void megasas_free_host_crash_buffer(struct megasas_instance *instance); |
| @@ -2000,5 +2049,6 @@ void __megasas_return_cmd(struct megasas_instance *instance, | |||
| 2000 | void megasas_return_mfi_mpt_pthr(struct megasas_instance *instance, | 2049 | void megasas_return_mfi_mpt_pthr(struct megasas_instance *instance, |
| 2001 | struct megasas_cmd *cmd_mfi, struct megasas_cmd_fusion *cmd_fusion); | 2050 | struct megasas_cmd *cmd_mfi, struct megasas_cmd_fusion *cmd_fusion); |
| 2002 | int megasas_cmd_type(struct scsi_cmnd *cmd); | 2051 | int megasas_cmd_type(struct scsi_cmnd *cmd); |
| 2052 | void megasas_setup_jbod_map(struct megasas_instance *instance); | ||
| 2003 | 2053 | ||
| 2004 | #endif /*LSI_MEGARAID_SAS_H */ | 2054 | #endif /*LSI_MEGARAID_SAS_H */ |
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 3b3f4809331b..97a1c1c33b05 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c | |||
| @@ -135,6 +135,12 @@ static struct pci_device_id megasas_pci_table[] = { | |||
| 135 | /* Invader */ | 135 | /* Invader */ |
| 136 | {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FURY)}, | 136 | {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FURY)}, |
| 137 | /* Fury */ | 137 | /* Fury */ |
| 138 | {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_INTRUDER)}, | ||
| 139 | /* Intruder */ | ||
| 140 | {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_INTRUDER_24)}, | ||
| 141 | /* Intruder 24 port*/ | ||
| 142 | {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_CUTLASS_52)}, | ||
| 143 | {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_CUTLASS_53)}, | ||
| 138 | {} | 144 | {} |
| 139 | }; | 145 | }; |
| 140 | 146 | ||
| @@ -260,6 +266,66 @@ megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd) | |||
| 260 | 266 | ||
| 261 | } | 267 | } |
| 262 | 268 | ||
| 269 | static const char * | ||
| 270 | format_timestamp(uint32_t timestamp) | ||
| 271 | { | ||
| 272 | static char buffer[32]; | ||
| 273 | |||
| 274 | if ((timestamp & 0xff000000) == 0xff000000) | ||
| 275 | snprintf(buffer, sizeof(buffer), "boot + %us", timestamp & | ||
| 276 | 0x00ffffff); | ||
| 277 | else | ||
| 278 | snprintf(buffer, sizeof(buffer), "%us", timestamp); | ||
| 279 | return buffer; | ||
| 280 | } | ||
| 281 | |||
| 282 | static const char * | ||
| 283 | format_class(int8_t class) | ||
| 284 | { | ||
| 285 | static char buffer[6]; | ||
| 286 | |||
| 287 | switch (class) { | ||
| 288 | case MFI_EVT_CLASS_DEBUG: | ||
| 289 | return "debug"; | ||
| 290 | case MFI_EVT_CLASS_PROGRESS: | ||
| 291 | return "progress"; | ||
| 292 | case MFI_EVT_CLASS_INFO: | ||
| 293 | return "info"; | ||
| 294 | case MFI_EVT_CLASS_WARNING: | ||
| 295 | return "WARN"; | ||
| 296 | case MFI_EVT_CLASS_CRITICAL: | ||
| 297 | return "CRIT"; | ||
| 298 | case MFI_EVT_CLASS_FATAL: | ||
| 299 | return "FATAL"; | ||
| 300 | case MFI_EVT_CLASS_DEAD: | ||
| 301 | return "DEAD"; | ||
| 302 | default: | ||
| 303 | snprintf(buffer, sizeof(buffer), "%d", class); | ||
| 304 | return buffer; | ||
| 305 | } | ||
| 306 | } | ||
| 307 | |||
| 308 | /** | ||
| 309 | * megasas_decode_evt: Decode FW AEN event and print critical event | ||
| 310 | * for information. | ||
| 311 | * @instance: Adapter soft state | ||
| 312 | */ | ||
| 313 | static void | ||
| 314 | megasas_decode_evt(struct megasas_instance *instance) | ||
| 315 | { | ||
| 316 | struct megasas_evt_detail *evt_detail = instance->evt_detail; | ||
| 317 | union megasas_evt_class_locale class_locale; | ||
| 318 | class_locale.word = le32_to_cpu(evt_detail->cl.word); | ||
| 319 | |||
| 320 | if (class_locale.members.class >= MFI_EVT_CLASS_CRITICAL) | ||
| 321 | dev_info(&instance->pdev->dev, "%d (%s/0x%04x/%s) - %s\n", | ||
| 322 | le32_to_cpu(evt_detail->seq_num), | ||
| 323 | format_timestamp(le32_to_cpu(evt_detail->time_stamp)), | ||
| 324 | (class_locale.members.locale), | ||
| 325 | format_class(class_locale.members.class), | ||
| 326 | evt_detail->description); | ||
| 327 | } | ||
| 328 | |||
| 263 | /** | 329 | /** |
| 264 | * The following functions are defined for xscale | 330 | * The following functions are defined for xscale |
| 265 | * (deviceid : 1064R, PERC5) controllers | 331 | * (deviceid : 1064R, PERC5) controllers |
| @@ -1659,8 +1725,56 @@ static struct megasas_instance *megasas_lookup_instance(u16 host_no) | |||
| 1659 | return NULL; | 1725 | return NULL; |
| 1660 | } | 1726 | } |
| 1661 | 1727 | ||
| 1728 | /* | ||
| 1729 | * megasas_set_dma_alignment - Set DMA alignment for PI enabled VD | ||
| 1730 | * | ||
| 1731 | * @sdev: OS provided scsi device | ||
| 1732 | * | ||
| 1733 | * Returns void | ||
| 1734 | */ | ||
| 1735 | static void megasas_set_dma_alignment(struct scsi_device *sdev) | ||
| 1736 | { | ||
| 1737 | u32 device_id, ld; | ||
| 1738 | struct megasas_instance *instance; | ||
| 1739 | struct fusion_context *fusion; | ||
| 1740 | struct MR_LD_RAID *raid; | ||
| 1741 | struct MR_DRV_RAID_MAP_ALL *local_map_ptr; | ||
| 1742 | |||
| 1743 | instance = megasas_lookup_instance(sdev->host->host_no); | ||
| 1744 | fusion = instance->ctrl_context; | ||
| 1745 | |||
| 1746 | if (!fusion) | ||
| 1747 | return; | ||
| 1748 | |||
| 1749 | if (sdev->channel >= MEGASAS_MAX_PD_CHANNELS) { | ||
| 1750 | device_id = ((sdev->channel % 2) * MEGASAS_MAX_DEV_PER_CHANNEL) | ||
| 1751 | + sdev->id; | ||
| 1752 | local_map_ptr = fusion->ld_drv_map[(instance->map_id & 1)]; | ||
| 1753 | ld = MR_TargetIdToLdGet(device_id, local_map_ptr); | ||
| 1754 | raid = MR_LdRaidGet(ld, local_map_ptr); | ||
| 1755 | |||
| 1756 | if (raid->capability.ldPiMode == MR_PROT_INFO_TYPE_CONTROLLER) | ||
| 1757 | blk_queue_update_dma_alignment(sdev->request_queue, 0x7); | ||
| 1758 | } | ||
| 1759 | } | ||
| 1760 | |||
| 1662 | static int megasas_slave_configure(struct scsi_device *sdev) | 1761 | static int megasas_slave_configure(struct scsi_device *sdev) |
| 1663 | { | 1762 | { |
| 1763 | u16 pd_index = 0; | ||
| 1764 | struct megasas_instance *instance; | ||
| 1765 | |||
| 1766 | instance = megasas_lookup_instance(sdev->host->host_no); | ||
| 1767 | if (instance->allow_fw_scan) { | ||
| 1768 | if (sdev->channel < MEGASAS_MAX_PD_CHANNELS && | ||
| 1769 | sdev->type == TYPE_DISK) { | ||
| 1770 | pd_index = (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) + | ||
| 1771 | sdev->id; | ||
| 1772 | if (instance->pd_list[pd_index].driveState != | ||
| 1773 | MR_PD_STATE_SYSTEM) | ||
| 1774 | return -ENXIO; | ||
| 1775 | } | ||
| 1776 | } | ||
| 1777 | megasas_set_dma_alignment(sdev); | ||
| 1664 | /* | 1778 | /* |
| 1665 | * The RAID firmware may require extended timeouts. | 1779 | * The RAID firmware may require extended timeouts. |
| 1666 | */ | 1780 | */ |
| @@ -1683,8 +1797,8 @@ static int megasas_slave_alloc(struct scsi_device *sdev) | |||
| 1683 | pd_index = | 1797 | pd_index = |
| 1684 | (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) + | 1798 | (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) + |
| 1685 | sdev->id; | 1799 | sdev->id; |
| 1686 | if (instance->pd_list[pd_index].driveState == | 1800 | if ((instance->allow_fw_scan || instance->pd_list[pd_index].driveState == |
| 1687 | MR_PD_STATE_SYSTEM) { | 1801 | MR_PD_STATE_SYSTEM)) { |
| 1688 | return 0; | 1802 | return 0; |
| 1689 | } | 1803 | } |
| 1690 | return -ENXIO; | 1804 | return -ENXIO; |
| @@ -1736,10 +1850,7 @@ void megaraid_sas_kill_hba(struct megasas_instance *instance) | |||
| 1736 | msleep(1000); | 1850 | msleep(1000); |
| 1737 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) || | 1851 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) || |
| 1738 | (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY) || | 1852 | (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY) || |
| 1739 | (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) || | 1853 | (instance->ctrl_context)) { |
| 1740 | (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA) || | ||
| 1741 | (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || | ||
| 1742 | (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) { | ||
| 1743 | writel(MFI_STOP_ADP, &instance->reg_set->doorbell); | 1854 | writel(MFI_STOP_ADP, &instance->reg_set->doorbell); |
| 1744 | /* Flush */ | 1855 | /* Flush */ |
| 1745 | readl(&instance->reg_set->doorbell); | 1856 | readl(&instance->reg_set->doorbell); |
| @@ -2506,10 +2617,7 @@ static int megasas_reset_bus_host(struct scsi_cmnd *scmd) | |||
| 2506 | /* | 2617 | /* |
| 2507 | * First wait for all commands to complete | 2618 | * First wait for all commands to complete |
| 2508 | */ | 2619 | */ |
| 2509 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) || | 2620 | if (instance->ctrl_context) |
| 2510 | (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA) || | ||
| 2511 | (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || | ||
| 2512 | (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) | ||
| 2513 | ret = megasas_reset_fusion(scmd->device->host, 1); | 2621 | ret = megasas_reset_fusion(scmd->device->host, 1); |
| 2514 | else | 2622 | else |
| 2515 | ret = megasas_generic_reset(scmd); | 2623 | ret = megasas_generic_reset(scmd); |
| @@ -2837,7 +2945,7 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, | |||
| 2837 | struct megasas_header *hdr = &cmd->frame->hdr; | 2945 | struct megasas_header *hdr = &cmd->frame->hdr; |
| 2838 | unsigned long flags; | 2946 | unsigned long flags; |
| 2839 | struct fusion_context *fusion = instance->ctrl_context; | 2947 | struct fusion_context *fusion = instance->ctrl_context; |
| 2840 | u32 opcode; | 2948 | u32 opcode, status; |
| 2841 | 2949 | ||
| 2842 | /* flag for the retry reset */ | 2950 | /* flag for the retry reset */ |
| 2843 | cmd->retry_for_fw_reset = 0; | 2951 | cmd->retry_for_fw_reset = 0; |
| @@ -2945,6 +3053,7 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, | |||
| 2945 | && (cmd->frame->dcmd.mbox.b[1] == 1)) { | 3053 | && (cmd->frame->dcmd.mbox.b[1] == 1)) { |
| 2946 | fusion->fast_path_io = 0; | 3054 | fusion->fast_path_io = 0; |
| 2947 | spin_lock_irqsave(instance->host->host_lock, flags); | 3055 | spin_lock_irqsave(instance->host->host_lock, flags); |
| 3056 | instance->map_update_cmd = NULL; | ||
| 2948 | if (cmd->frame->hdr.cmd_status != 0) { | 3057 | if (cmd->frame->hdr.cmd_status != 0) { |
| 2949 | if (cmd->frame->hdr.cmd_status != | 3058 | if (cmd->frame->hdr.cmd_status != |
| 2950 | MFI_STAT_NOT_FOUND) | 3059 | MFI_STAT_NOT_FOUND) |
| @@ -2982,6 +3091,27 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, | |||
| 2982 | spin_unlock_irqrestore(&poll_aen_lock, flags); | 3091 | spin_unlock_irqrestore(&poll_aen_lock, flags); |
| 2983 | } | 3092 | } |
| 2984 | 3093 | ||
| 3094 | /* FW has an updated PD sequence */ | ||
| 3095 | if ((opcode == MR_DCMD_SYSTEM_PD_MAP_GET_INFO) && | ||
| 3096 | (cmd->frame->dcmd.mbox.b[0] == 1)) { | ||
| 3097 | |||
| 3098 | spin_lock_irqsave(instance->host->host_lock, flags); | ||
| 3099 | status = cmd->frame->hdr.cmd_status; | ||
| 3100 | instance->jbod_seq_cmd = NULL; | ||
| 3101 | megasas_return_cmd(instance, cmd); | ||
| 3102 | |||
| 3103 | if (status == MFI_STAT_OK) { | ||
| 3104 | instance->pd_seq_map_id++; | ||
| 3105 | /* Re-register a pd sync seq num cmd */ | ||
| 3106 | if (megasas_sync_pd_seq_num(instance, true)) | ||
| 3107 | instance->use_seqnum_jbod_fp = false; | ||
| 3108 | } else | ||
| 3109 | instance->use_seqnum_jbod_fp = false; | ||
| 3110 | |||
| 3111 | spin_unlock_irqrestore(instance->host->host_lock, flags); | ||
| 3112 | break; | ||
| 3113 | } | ||
| 3114 | |||
| 2985 | /* | 3115 | /* |
| 2986 | * See if got an event notification | 3116 | * See if got an event notification |
| 2987 | */ | 3117 | */ |
| @@ -3348,22 +3478,14 @@ megasas_transition_to_ready(struct megasas_instance *instance, int ocr) | |||
| 3348 | PCI_DEVICE_ID_LSI_SAS0073SKINNY) || | 3478 | PCI_DEVICE_ID_LSI_SAS0073SKINNY) || |
| 3349 | (instance->pdev->device == | 3479 | (instance->pdev->device == |
| 3350 | PCI_DEVICE_ID_LSI_SAS0071SKINNY) || | 3480 | PCI_DEVICE_ID_LSI_SAS0071SKINNY) || |
| 3351 | (instance->pdev->device == | 3481 | (instance->ctrl_context)) |
| 3352 | PCI_DEVICE_ID_LSI_FUSION) || | ||
| 3353 | (instance->pdev->device == | ||
| 3354 | PCI_DEVICE_ID_LSI_PLASMA) || | ||
| 3355 | (instance->pdev->device == | ||
| 3356 | PCI_DEVICE_ID_LSI_INVADER) || | ||
| 3357 | (instance->pdev->device == | ||
| 3358 | PCI_DEVICE_ID_LSI_FURY)) { | ||
| 3359 | writel( | 3482 | writel( |
| 3360 | MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG, | 3483 | MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG, |
| 3361 | &instance->reg_set->doorbell); | 3484 | &instance->reg_set->doorbell); |
| 3362 | } else { | 3485 | else |
| 3363 | writel( | 3486 | writel( |
| 3364 | MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG, | 3487 | MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG, |
| 3365 | &instance->reg_set->inbound_doorbell); | 3488 | &instance->reg_set->inbound_doorbell); |
| 3366 | } | ||
| 3367 | 3489 | ||
| 3368 | max_wait = MEGASAS_RESET_WAIT_TIME; | 3490 | max_wait = MEGASAS_RESET_WAIT_TIME; |
| 3369 | cur_state = MFI_STATE_WAIT_HANDSHAKE; | 3491 | cur_state = MFI_STATE_WAIT_HANDSHAKE; |
| @@ -3374,17 +3496,10 @@ megasas_transition_to_ready(struct megasas_instance *instance, int ocr) | |||
| 3374 | PCI_DEVICE_ID_LSI_SAS0073SKINNY) || | 3496 | PCI_DEVICE_ID_LSI_SAS0073SKINNY) || |
| 3375 | (instance->pdev->device == | 3497 | (instance->pdev->device == |
| 3376 | PCI_DEVICE_ID_LSI_SAS0071SKINNY) || | 3498 | PCI_DEVICE_ID_LSI_SAS0071SKINNY) || |
| 3377 | (instance->pdev->device == | 3499 | (instance->ctrl_context)) |
| 3378 | PCI_DEVICE_ID_LSI_FUSION) || | ||
| 3379 | (instance->pdev->device == | ||
| 3380 | PCI_DEVICE_ID_LSI_PLASMA) || | ||
| 3381 | (instance->pdev->device == | ||
| 3382 | PCI_DEVICE_ID_LSI_INVADER) || | ||
| 3383 | (instance->pdev->device == | ||
| 3384 | PCI_DEVICE_ID_LSI_FURY)) { | ||
| 3385 | writel(MFI_INIT_HOTPLUG, | 3500 | writel(MFI_INIT_HOTPLUG, |
| 3386 | &instance->reg_set->doorbell); | 3501 | &instance->reg_set->doorbell); |
| 3387 | } else | 3502 | else |
| 3388 | writel(MFI_INIT_HOTPLUG, | 3503 | writel(MFI_INIT_HOTPLUG, |
| 3389 | &instance->reg_set->inbound_doorbell); | 3504 | &instance->reg_set->inbound_doorbell); |
| 3390 | 3505 | ||
| @@ -3401,24 +3516,11 @@ megasas_transition_to_ready(struct megasas_instance *instance, int ocr) | |||
| 3401 | PCI_DEVICE_ID_LSI_SAS0073SKINNY) || | 3516 | PCI_DEVICE_ID_LSI_SAS0073SKINNY) || |
| 3402 | (instance->pdev->device == | 3517 | (instance->pdev->device == |
| 3403 | PCI_DEVICE_ID_LSI_SAS0071SKINNY) || | 3518 | PCI_DEVICE_ID_LSI_SAS0071SKINNY) || |
| 3404 | (instance->pdev->device | 3519 | (instance->ctrl_context)) { |
| 3405 | == PCI_DEVICE_ID_LSI_FUSION) || | ||
| 3406 | (instance->pdev->device | ||
| 3407 | == PCI_DEVICE_ID_LSI_PLASMA) || | ||
| 3408 | (instance->pdev->device | ||
| 3409 | == PCI_DEVICE_ID_LSI_INVADER) || | ||
| 3410 | (instance->pdev->device | ||
| 3411 | == PCI_DEVICE_ID_LSI_FURY)) { | ||
| 3412 | writel(MFI_RESET_FLAGS, | 3520 | writel(MFI_RESET_FLAGS, |
| 3413 | &instance->reg_set->doorbell); | 3521 | &instance->reg_set->doorbell); |
| 3414 | if ((instance->pdev->device == | 3522 | |
| 3415 | PCI_DEVICE_ID_LSI_FUSION) || | 3523 | if (instance->ctrl_context) { |
| 3416 | (instance->pdev->device == | ||
| 3417 | PCI_DEVICE_ID_LSI_PLASMA) || | ||
| 3418 | (instance->pdev->device == | ||
| 3419 | PCI_DEVICE_ID_LSI_INVADER) || | ||
| 3420 | (instance->pdev->device == | ||
| 3421 | PCI_DEVICE_ID_LSI_FURY)) { | ||
| 3422 | for (i = 0; i < (10 * 1000); i += 20) { | 3524 | for (i = 0; i < (10 * 1000); i += 20) { |
| 3423 | if (readl( | 3525 | if (readl( |
| 3424 | &instance-> | 3526 | &instance-> |
| @@ -3639,11 +3741,7 @@ static int megasas_create_frame_pool(struct megasas_instance *instance) | |||
| 3639 | memset(cmd->frame, 0, total_sz); | 3741 | memset(cmd->frame, 0, total_sz); |
| 3640 | cmd->frame->io.context = cpu_to_le32(cmd->index); | 3742 | cmd->frame->io.context = cpu_to_le32(cmd->index); |
| 3641 | cmd->frame->io.pad_0 = 0; | 3743 | cmd->frame->io.pad_0 = 0; |
| 3642 | if ((instance->pdev->device != PCI_DEVICE_ID_LSI_FUSION) && | 3744 | if (!instance->ctrl_context && reset_devices) |
| 3643 | (instance->pdev->device != PCI_DEVICE_ID_LSI_PLASMA) && | ||
| 3644 | (instance->pdev->device != PCI_DEVICE_ID_LSI_INVADER) && | ||
| 3645 | (instance->pdev->device != PCI_DEVICE_ID_LSI_FURY) && | ||
| 3646 | (reset_devices)) | ||
| 3647 | cmd->frame->hdr.cmd = MFI_CMD_INVALID; | 3745 | cmd->frame->hdr.cmd = MFI_CMD_INVALID; |
| 3648 | } | 3746 | } |
| 3649 | 3747 | ||
| @@ -4136,11 +4234,21 @@ megasas_get_ctrl_info(struct megasas_instance *instance) | |||
| 4136 | le32_to_cpus((u32 *)&ctrl_info->adapterOperations2); | 4234 | le32_to_cpus((u32 *)&ctrl_info->adapterOperations2); |
| 4137 | le32_to_cpus((u32 *)&ctrl_info->adapterOperations3); | 4235 | le32_to_cpus((u32 *)&ctrl_info->adapterOperations3); |
| 4138 | megasas_update_ext_vd_details(instance); | 4236 | megasas_update_ext_vd_details(instance); |
| 4237 | instance->use_seqnum_jbod_fp = | ||
| 4238 | ctrl_info->adapterOperations3.useSeqNumJbodFP; | ||
| 4139 | instance->is_imr = (ctrl_info->memory_size ? 0 : 1); | 4239 | instance->is_imr = (ctrl_info->memory_size ? 0 : 1); |
| 4140 | dev_info(&instance->pdev->dev, | 4240 | dev_info(&instance->pdev->dev, |
| 4141 | "controller type\t: %s(%dMB)\n", | 4241 | "controller type\t: %s(%dMB)\n", |
| 4142 | instance->is_imr ? "iMR" : "MR", | 4242 | instance->is_imr ? "iMR" : "MR", |
| 4143 | le16_to_cpu(ctrl_info->memory_size)); | 4243 | le16_to_cpu(ctrl_info->memory_size)); |
| 4244 | instance->disableOnlineCtrlReset = | ||
| 4245 | ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset; | ||
| 4246 | dev_info(&instance->pdev->dev, "Online Controller Reset(OCR)\t: %s\n", | ||
| 4247 | instance->disableOnlineCtrlReset ? "Disabled" : "Enabled"); | ||
| 4248 | instance->secure_jbod_support = | ||
| 4249 | ctrl_info->adapterOperations3.supportSecurityonJBOD; | ||
| 4250 | dev_info(&instance->pdev->dev, "Secure JBOD support\t: %s\n", | ||
| 4251 | instance->secure_jbod_support ? "Yes" : "No"); | ||
| 4144 | } | 4252 | } |
| 4145 | 4253 | ||
| 4146 | pci_free_consistent(instance->pdev, sizeof(struct megasas_ctrl_info), | 4254 | pci_free_consistent(instance->pdev, sizeof(struct megasas_ctrl_info), |
| @@ -4481,6 +4589,62 @@ megasas_destroy_irqs(struct megasas_instance *instance) { | |||
| 4481 | } | 4589 | } |
| 4482 | 4590 | ||
| 4483 | /** | 4591 | /** |
| 4592 | * megasas_setup_jbod_map - setup jbod map for FP seq_number. | ||
| 4593 | * @instance: Adapter soft state | ||
| 4594 | * @is_probe: Driver probe check | ||
| 4595 | * | ||
| 4596 | * Return 0 on success. | ||
| 4597 | */ | ||
| 4598 | void | ||
| 4599 | megasas_setup_jbod_map(struct megasas_instance *instance) | ||
| 4600 | { | ||
| 4601 | int i; | ||
| 4602 | struct fusion_context *fusion = instance->ctrl_context; | ||
| 4603 | u32 pd_seq_map_sz; | ||
| 4604 | |||
| 4605 | pd_seq_map_sz = sizeof(struct MR_PD_CFG_SEQ_NUM_SYNC) + | ||
| 4606 | (sizeof(struct MR_PD_CFG_SEQ) * (MAX_PHYSICAL_DEVICES - 1)); | ||
| 4607 | |||
| 4608 | if (reset_devices || !fusion || | ||
| 4609 | !instance->ctrl_info->adapterOperations3.useSeqNumJbodFP) { | ||
| 4610 | dev_info(&instance->pdev->dev, | ||
| 4611 | "Jbod map is not supported %s %d\n", | ||
| 4612 | __func__, __LINE__); | ||
| 4613 | instance->use_seqnum_jbod_fp = false; | ||
| 4614 | return; | ||
| 4615 | } | ||
| 4616 | |||
| 4617 | if (fusion->pd_seq_sync[0]) | ||
| 4618 | goto skip_alloc; | ||
| 4619 | |||
| 4620 | for (i = 0; i < JBOD_MAPS_COUNT; i++) { | ||
| 4621 | fusion->pd_seq_sync[i] = dma_alloc_coherent | ||
| 4622 | (&instance->pdev->dev, pd_seq_map_sz, | ||
| 4623 | &fusion->pd_seq_phys[i], GFP_KERNEL); | ||
| 4624 | if (!fusion->pd_seq_sync[i]) { | ||
| 4625 | dev_err(&instance->pdev->dev, | ||
| 4626 | "Failed to allocate memory from %s %d\n", | ||
| 4627 | __func__, __LINE__); | ||
| 4628 | if (i == 1) { | ||
| 4629 | dma_free_coherent(&instance->pdev->dev, | ||
| 4630 | pd_seq_map_sz, fusion->pd_seq_sync[0], | ||
| 4631 | fusion->pd_seq_phys[0]); | ||
| 4632 | fusion->pd_seq_sync[0] = NULL; | ||
| 4633 | } | ||
| 4634 | instance->use_seqnum_jbod_fp = false; | ||
| 4635 | return; | ||
| 4636 | } | ||
| 4637 | } | ||
| 4638 | |||
| 4639 | skip_alloc: | ||
| 4640 | if (!megasas_sync_pd_seq_num(instance, false) && | ||
| 4641 | !megasas_sync_pd_seq_num(instance, true)) | ||
| 4642 | instance->use_seqnum_jbod_fp = true; | ||
| 4643 | else | ||
| 4644 | instance->use_seqnum_jbod_fp = false; | ||
| 4645 | } | ||
| 4646 | |||
| 4647 | /** | ||
| 4484 | * megasas_init_fw - Initializes the FW | 4648 | * megasas_init_fw - Initializes the FW |
| 4485 | * @instance: Adapter soft state | 4649 | * @instance: Adapter soft state |
| 4486 | * | 4650 | * |
| @@ -4498,6 +4662,9 @@ static int megasas_init_fw(struct megasas_instance *instance) | |||
| 4498 | unsigned long bar_list; | 4662 | unsigned long bar_list; |
| 4499 | int i, loop, fw_msix_count = 0; | 4663 | int i, loop, fw_msix_count = 0; |
| 4500 | struct IOV_111 *iovPtr; | 4664 | struct IOV_111 *iovPtr; |
| 4665 | struct fusion_context *fusion; | ||
| 4666 | |||
| 4667 | fusion = instance->ctrl_context; | ||
| 4501 | 4668 | ||
| 4502 | /* Find first memory bar */ | 4669 | /* Find first memory bar */ |
| 4503 | bar_list = pci_select_bars(instance->pdev, IORESOURCE_MEM); | 4670 | bar_list = pci_select_bars(instance->pdev, IORESOURCE_MEM); |
| @@ -4523,6 +4690,10 @@ static int megasas_init_fw(struct megasas_instance *instance) | |||
| 4523 | case PCI_DEVICE_ID_LSI_PLASMA: | 4690 | case PCI_DEVICE_ID_LSI_PLASMA: |
| 4524 | case PCI_DEVICE_ID_LSI_INVADER: | 4691 | case PCI_DEVICE_ID_LSI_INVADER: |
| 4525 | case PCI_DEVICE_ID_LSI_FURY: | 4692 | case PCI_DEVICE_ID_LSI_FURY: |
| 4693 | case PCI_DEVICE_ID_LSI_INTRUDER: | ||
| 4694 | case PCI_DEVICE_ID_LSI_INTRUDER_24: | ||
| 4695 | case PCI_DEVICE_ID_LSI_CUTLASS_52: | ||
| 4696 | case PCI_DEVICE_ID_LSI_CUTLASS_53: | ||
| 4526 | instance->instancet = &megasas_instance_template_fusion; | 4697 | instance->instancet = &megasas_instance_template_fusion; |
| 4527 | break; | 4698 | break; |
| 4528 | case PCI_DEVICE_ID_LSI_SAS1078R: | 4699 | case PCI_DEVICE_ID_LSI_SAS1078R: |
| @@ -4541,6 +4712,7 @@ static int megasas_init_fw(struct megasas_instance *instance) | |||
| 4541 | case PCI_DEVICE_ID_DELL_PERC5: | 4712 | case PCI_DEVICE_ID_DELL_PERC5: |
| 4542 | default: | 4713 | default: |
| 4543 | instance->instancet = &megasas_instance_template_xscale; | 4714 | instance->instancet = &megasas_instance_template_xscale; |
| 4715 | instance->allow_fw_scan = 1; | ||
| 4544 | break; | 4716 | break; |
| 4545 | } | 4717 | } |
| 4546 | 4718 | ||
| @@ -4575,37 +4747,32 @@ static int megasas_init_fw(struct megasas_instance *instance) | |||
| 4575 | scratch_pad_2 = readl | 4747 | scratch_pad_2 = readl |
| 4576 | (&instance->reg_set->outbound_scratch_pad_2); | 4748 | (&instance->reg_set->outbound_scratch_pad_2); |
| 4577 | /* Check max MSI-X vectors */ | 4749 | /* Check max MSI-X vectors */ |
| 4578 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) || | 4750 | if (fusion) { |
| 4579 | (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA)) { | 4751 | if (fusion->adapter_type == THUNDERBOLT_SERIES) { /* Thunderbolt Series*/ |
| 4580 | instance->msix_vectors = (scratch_pad_2 | 4752 | instance->msix_vectors = (scratch_pad_2 |
| 4581 | & MR_MAX_REPLY_QUEUES_OFFSET) + 1; | 4753 | & MR_MAX_REPLY_QUEUES_OFFSET) + 1; |
| 4582 | fw_msix_count = instance->msix_vectors; | 4754 | fw_msix_count = instance->msix_vectors; |
| 4583 | if (msix_vectors) | 4755 | } else { /* Invader series supports more than 8 MSI-x vectors*/ |
| 4584 | instance->msix_vectors = | 4756 | instance->msix_vectors = ((scratch_pad_2 |
| 4585 | min(msix_vectors, | 4757 | & MR_MAX_REPLY_QUEUES_EXT_OFFSET) |
| 4586 | instance->msix_vectors); | 4758 | >> MR_MAX_REPLY_QUEUES_EXT_OFFSET_SHIFT) + 1; |
| 4587 | } else if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) | 4759 | fw_msix_count = instance->msix_vectors; |
| 4588 | || (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) { | 4760 | /* Save 1-15 reply post index address to local memory |
| 4589 | /* Invader/Fury supports more than 8 MSI-X */ | 4761 | * Index 0 is already saved from reg offset |
| 4590 | instance->msix_vectors = ((scratch_pad_2 | 4762 | * MPI2_REPLY_POST_HOST_INDEX_OFFSET |
| 4591 | & MR_MAX_REPLY_QUEUES_EXT_OFFSET) | 4763 | */ |
| 4592 | >> MR_MAX_REPLY_QUEUES_EXT_OFFSET_SHIFT) + 1; | 4764 | for (loop = 1; loop < MR_MAX_MSIX_REG_ARRAY; loop++) { |
| 4593 | fw_msix_count = instance->msix_vectors; | 4765 | instance->reply_post_host_index_addr[loop] = |
| 4594 | /* Save 1-15 reply post index address to local memory | 4766 | (u32 __iomem *) |
| 4595 | * Index 0 is already saved from reg offset | 4767 | ((u8 __iomem *)instance->reg_set + |
| 4596 | * MPI2_REPLY_POST_HOST_INDEX_OFFSET | 4768 | MPI2_SUP_REPLY_POST_HOST_INDEX_OFFSET |
| 4597 | */ | 4769 | + (loop * 0x10)); |
| 4598 | for (loop = 1; loop < MR_MAX_MSIX_REG_ARRAY; loop++) { | 4770 | } |
| 4599 | instance->reply_post_host_index_addr[loop] = | ||
| 4600 | (u32 __iomem *) | ||
| 4601 | ((u8 __iomem *)instance->reg_set + | ||
| 4602 | MPI2_SUP_REPLY_POST_HOST_INDEX_OFFSET | ||
| 4603 | + (loop * 0x10)); | ||
| 4604 | } | 4771 | } |
| 4605 | if (msix_vectors) | 4772 | if (msix_vectors) |
| 4606 | instance->msix_vectors = min(msix_vectors, | 4773 | instance->msix_vectors = min(msix_vectors, |
| 4607 | instance->msix_vectors); | 4774 | instance->msix_vectors); |
| 4608 | } else | 4775 | } else /* MFI adapters */ |
| 4609 | instance->msix_vectors = 1; | 4776 | instance->msix_vectors = 1; |
| 4610 | /* Don't bother allocating more MSI-X vectors than cpus */ | 4777 | /* Don't bother allocating more MSI-X vectors than cpus */ |
| 4611 | instance->msix_vectors = min(instance->msix_vectors, | 4778 | instance->msix_vectors = min(instance->msix_vectors, |
| @@ -4626,6 +4793,9 @@ static int megasas_init_fw(struct megasas_instance *instance) | |||
| 4626 | "current msix/online cpus\t: (%d/%d)\n", | 4793 | "current msix/online cpus\t: (%d/%d)\n", |
| 4627 | instance->msix_vectors, (unsigned int)num_online_cpus()); | 4794 | instance->msix_vectors, (unsigned int)num_online_cpus()); |
| 4628 | 4795 | ||
| 4796 | tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet, | ||
| 4797 | (unsigned long)instance); | ||
| 4798 | |||
| 4629 | if (instance->msix_vectors ? | 4799 | if (instance->msix_vectors ? |
| 4630 | megasas_setup_irqs_msix(instance, 1) : | 4800 | megasas_setup_irqs_msix(instance, 1) : |
| 4631 | megasas_setup_irqs_ioapic(instance)) | 4801 | megasas_setup_irqs_ioapic(instance)) |
| @@ -4646,13 +4816,13 @@ static int megasas_init_fw(struct megasas_instance *instance) | |||
| 4646 | if (instance->instancet->init_adapter(instance)) | 4816 | if (instance->instancet->init_adapter(instance)) |
| 4647 | goto fail_init_adapter; | 4817 | goto fail_init_adapter; |
| 4648 | 4818 | ||
| 4649 | tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet, | ||
| 4650 | (unsigned long)instance); | ||
| 4651 | 4819 | ||
| 4652 | instance->instancet->enable_intr(instance); | 4820 | instance->instancet->enable_intr(instance); |
| 4653 | 4821 | ||
| 4654 | dev_err(&instance->pdev->dev, "INIT adapter done\n"); | 4822 | dev_err(&instance->pdev->dev, "INIT adapter done\n"); |
| 4655 | 4823 | ||
| 4824 | megasas_setup_jbod_map(instance); | ||
| 4825 | |||
| 4656 | /** for passthrough | 4826 | /** for passthrough |
| 4657 | * the following function will get the PD LIST. | 4827 | * the following function will get the PD LIST. |
| 4658 | */ | 4828 | */ |
| @@ -4686,8 +4856,6 @@ static int megasas_init_fw(struct megasas_instance *instance) | |||
| 4686 | 4856 | ||
| 4687 | tmp_sectors = min_t(u32, max_sectors_1, max_sectors_2); | 4857 | tmp_sectors = min_t(u32, max_sectors_1, max_sectors_2); |
| 4688 | 4858 | ||
| 4689 | instance->disableOnlineCtrlReset = | ||
| 4690 | ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset; | ||
| 4691 | instance->mpio = ctrl_info->adapterOperations2.mpio; | 4859 | instance->mpio = ctrl_info->adapterOperations2.mpio; |
| 4692 | instance->UnevenSpanSupport = | 4860 | instance->UnevenSpanSupport = |
| 4693 | ctrl_info->adapterOperations2.supportUnevenSpans; | 4861 | ctrl_info->adapterOperations2.supportUnevenSpans; |
| @@ -4700,18 +4868,22 @@ static int megasas_init_fw(struct megasas_instance *instance) | |||
| 4700 | 4868 | ||
| 4701 | } | 4869 | } |
| 4702 | if (ctrl_info->host_interface.SRIOV) { | 4870 | if (ctrl_info->host_interface.SRIOV) { |
| 4703 | if (!ctrl_info->adapterOperations2.activePassive) | 4871 | instance->requestorId = ctrl_info->iov.requestorId; |
| 4704 | instance->PlasmaFW111 = 1; | 4872 | if (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA) { |
| 4705 | 4873 | if (!ctrl_info->adapterOperations2.activePassive) | |
| 4706 | if (!instance->PlasmaFW111) | 4874 | instance->PlasmaFW111 = 1; |
| 4707 | instance->requestorId = | 4875 | |
| 4708 | ctrl_info->iov.requestorId; | 4876 | dev_info(&instance->pdev->dev, "SR-IOV: firmware type: %s\n", |
| 4709 | else { | 4877 | instance->PlasmaFW111 ? "1.11" : "new"); |
| 4710 | iovPtr = (struct IOV_111 *)((unsigned char *)ctrl_info + IOV_111_OFFSET); | 4878 | |
| 4711 | instance->requestorId = iovPtr->requestorId; | 4879 | if (instance->PlasmaFW111) { |
| 4880 | iovPtr = (struct IOV_111 *) | ||
| 4881 | ((unsigned char *)ctrl_info + IOV_111_OFFSET); | ||
| 4882 | instance->requestorId = iovPtr->requestorId; | ||
| 4883 | } | ||
| 4712 | } | 4884 | } |
| 4713 | dev_warn(&instance->pdev->dev, "I am VF " | 4885 | dev_info(&instance->pdev->dev, "SRIOV: VF requestorId %d\n", |
| 4714 | "requestorId %d\n", instance->requestorId); | 4886 | instance->requestorId); |
| 4715 | } | 4887 | } |
| 4716 | 4888 | ||
| 4717 | instance->crash_dump_fw_support = | 4889 | instance->crash_dump_fw_support = |
| @@ -4732,8 +4904,6 @@ static int megasas_init_fw(struct megasas_instance *instance) | |||
| 4732 | instance->crash_dump_buf = NULL; | 4904 | instance->crash_dump_buf = NULL; |
| 4733 | } | 4905 | } |
| 4734 | 4906 | ||
| 4735 | instance->secure_jbod_support = | ||
| 4736 | ctrl_info->adapterOperations3.supportSecurityonJBOD; | ||
| 4737 | 4907 | ||
| 4738 | dev_info(&instance->pdev->dev, | 4908 | dev_info(&instance->pdev->dev, |
| 4739 | "pci id\t\t: (0x%04x)/(0x%04x)/(0x%04x)/(0x%04x)\n", | 4909 | "pci id\t\t: (0x%04x)/(0x%04x)/(0x%04x)/(0x%04x)\n", |
| @@ -4743,16 +4913,14 @@ static int megasas_init_fw(struct megasas_instance *instance) | |||
| 4743 | le16_to_cpu(ctrl_info->pci.sub_device_id)); | 4913 | le16_to_cpu(ctrl_info->pci.sub_device_id)); |
| 4744 | dev_info(&instance->pdev->dev, "unevenspan support : %s\n", | 4914 | dev_info(&instance->pdev->dev, "unevenspan support : %s\n", |
| 4745 | instance->UnevenSpanSupport ? "yes" : "no"); | 4915 | instance->UnevenSpanSupport ? "yes" : "no"); |
| 4746 | dev_info(&instance->pdev->dev, "disable ocr : %s\n", | ||
| 4747 | instance->disableOnlineCtrlReset ? "yes" : "no"); | ||
| 4748 | dev_info(&instance->pdev->dev, "firmware crash dump : %s\n", | 4916 | dev_info(&instance->pdev->dev, "firmware crash dump : %s\n", |
| 4749 | instance->crash_dump_drv_support ? "yes" : "no"); | 4917 | instance->crash_dump_drv_support ? "yes" : "no"); |
| 4750 | dev_info(&instance->pdev->dev, "secure jbod : %s\n", | 4918 | dev_info(&instance->pdev->dev, "jbod sync map : %s\n", |
| 4751 | instance->secure_jbod_support ? "yes" : "no"); | 4919 | instance->use_seqnum_jbod_fp ? "yes" : "no"); |
| 4752 | 4920 | ||
| 4753 | 4921 | ||
| 4754 | instance->max_sectors_per_req = instance->max_num_sge * | 4922 | instance->max_sectors_per_req = instance->max_num_sge * |
| 4755 | PAGE_SIZE / 512; | 4923 | SGE_BUFFER_SIZE / 512; |
| 4756 | if (tmp_sectors && (instance->max_sectors_per_req > tmp_sectors)) | 4924 | if (tmp_sectors && (instance->max_sectors_per_req > tmp_sectors)) |
| 4757 | instance->max_sectors_per_req = tmp_sectors; | 4925 | instance->max_sectors_per_req = tmp_sectors; |
| 4758 | 4926 | ||
| @@ -5091,10 +5259,7 @@ static int megasas_io_attach(struct megasas_instance *instance) | |||
| 5091 | host->max_cmd_len = 16; | 5259 | host->max_cmd_len = 16; |
| 5092 | 5260 | ||
| 5093 | /* Fusion only supports host reset */ | 5261 | /* Fusion only supports host reset */ |
| 5094 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) || | 5262 | if (instance->ctrl_context) { |
| 5095 | (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA) || | ||
| 5096 | (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || | ||
| 5097 | (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) { | ||
| 5098 | host->hostt->eh_device_reset_handler = NULL; | 5263 | host->hostt->eh_device_reset_handler = NULL; |
| 5099 | host->hostt->eh_bus_reset_handler = NULL; | 5264 | host->hostt->eh_bus_reset_handler = NULL; |
| 5100 | } | 5265 | } |
| @@ -5210,6 +5375,10 @@ static int megasas_probe_one(struct pci_dev *pdev, | |||
| 5210 | case PCI_DEVICE_ID_LSI_PLASMA: | 5375 | case PCI_DEVICE_ID_LSI_PLASMA: |
| 5211 | case PCI_DEVICE_ID_LSI_INVADER: | 5376 | case PCI_DEVICE_ID_LSI_INVADER: |
| 5212 | case PCI_DEVICE_ID_LSI_FURY: | 5377 | case PCI_DEVICE_ID_LSI_FURY: |
| 5378 | case PCI_DEVICE_ID_LSI_INTRUDER: | ||
| 5379 | case PCI_DEVICE_ID_LSI_INTRUDER_24: | ||
| 5380 | case PCI_DEVICE_ID_LSI_CUTLASS_52: | ||
| 5381 | case PCI_DEVICE_ID_LSI_CUTLASS_53: | ||
| 5213 | { | 5382 | { |
| 5214 | instance->ctrl_context_pages = | 5383 | instance->ctrl_context_pages = |
| 5215 | get_order(sizeof(struct fusion_context)); | 5384 | get_order(sizeof(struct fusion_context)); |
| @@ -5223,6 +5392,11 @@ static int megasas_probe_one(struct pci_dev *pdev, | |||
| 5223 | fusion = instance->ctrl_context; | 5392 | fusion = instance->ctrl_context; |
| 5224 | memset(fusion, 0, | 5393 | memset(fusion, 0, |
| 5225 | ((1 << PAGE_SHIFT) << instance->ctrl_context_pages)); | 5394 | ((1 << PAGE_SHIFT) << instance->ctrl_context_pages)); |
| 5395 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) || | ||
| 5396 | (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA)) | ||
| 5397 | fusion->adapter_type = THUNDERBOLT_SERIES; | ||
| 5398 | else | ||
| 5399 | fusion->adapter_type = INVADER_SERIES; | ||
| 5226 | } | 5400 | } |
| 5227 | break; | 5401 | break; |
| 5228 | default: /* For all other supported controllers */ | 5402 | default: /* For all other supported controllers */ |
| @@ -5325,10 +5499,7 @@ static int megasas_probe_one(struct pci_dev *pdev, | |||
| 5325 | instance->disableOnlineCtrlReset = 1; | 5499 | instance->disableOnlineCtrlReset = 1; |
| 5326 | instance->UnevenSpanSupport = 0; | 5500 | instance->UnevenSpanSupport = 0; |
| 5327 | 5501 | ||
| 5328 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) || | 5502 | if (instance->ctrl_context) { |
| 5329 | (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA) || | ||
| 5330 | (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || | ||
| 5331 | (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) { | ||
| 5332 | INIT_WORK(&instance->work_init, megasas_fusion_ocr_wq); | 5503 | INIT_WORK(&instance->work_init, megasas_fusion_ocr_wq); |
| 5333 | INIT_WORK(&instance->crash_init, megasas_fusion_crash_dump_wq); | 5504 | INIT_WORK(&instance->crash_init, megasas_fusion_crash_dump_wq); |
| 5334 | } else | 5505 | } else |
| @@ -5408,10 +5579,7 @@ fail_io_attach: | |||
| 5408 | instance->instancet->disable_intr(instance); | 5579 | instance->instancet->disable_intr(instance); |
| 5409 | megasas_destroy_irqs(instance); | 5580 | megasas_destroy_irqs(instance); |
| 5410 | 5581 | ||
| 5411 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) || | 5582 | if (instance->ctrl_context) |
| 5412 | (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA) || | ||
| 5413 | (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || | ||
| 5414 | (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) | ||
| 5415 | megasas_release_fusion(instance); | 5583 | megasas_release_fusion(instance); |
| 5416 | else | 5584 | else |
| 5417 | megasas_release_mfi(instance); | 5585 | megasas_release_mfi(instance); |
| @@ -5498,10 +5666,14 @@ static void megasas_shutdown_controller(struct megasas_instance *instance, | |||
| 5498 | 5666 | ||
| 5499 | if (instance->aen_cmd) | 5667 | if (instance->aen_cmd) |
| 5500 | megasas_issue_blocked_abort_cmd(instance, | 5668 | megasas_issue_blocked_abort_cmd(instance, |
| 5501 | instance->aen_cmd, 30); | 5669 | instance->aen_cmd, MEGASAS_BLOCKED_CMD_TIMEOUT); |
| 5502 | if (instance->map_update_cmd) | 5670 | if (instance->map_update_cmd) |
| 5503 | megasas_issue_blocked_abort_cmd(instance, | 5671 | megasas_issue_blocked_abort_cmd(instance, |
| 5504 | instance->map_update_cmd, 30); | 5672 | instance->map_update_cmd, MEGASAS_BLOCKED_CMD_TIMEOUT); |
| 5673 | if (instance->jbod_seq_cmd) | ||
| 5674 | megasas_issue_blocked_abort_cmd(instance, | ||
| 5675 | instance->jbod_seq_cmd, MEGASAS_BLOCKED_CMD_TIMEOUT); | ||
| 5676 | |||
| 5505 | dcmd = &cmd->frame->dcmd; | 5677 | dcmd = &cmd->frame->dcmd; |
| 5506 | 5678 | ||
| 5507 | memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); | 5679 | memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); |
| @@ -5620,12 +5792,7 @@ megasas_resume(struct pci_dev *pdev) | |||
| 5620 | instance->msix_vectors)) | 5792 | instance->msix_vectors)) |
| 5621 | goto fail_reenable_msix; | 5793 | goto fail_reenable_msix; |
| 5622 | 5794 | ||
| 5623 | switch (instance->pdev->device) { | 5795 | if (instance->ctrl_context) { |
| 5624 | case PCI_DEVICE_ID_LSI_FUSION: | ||
| 5625 | case PCI_DEVICE_ID_LSI_PLASMA: | ||
| 5626 | case PCI_DEVICE_ID_LSI_INVADER: | ||
| 5627 | case PCI_DEVICE_ID_LSI_FURY: | ||
| 5628 | { | ||
| 5629 | megasas_reset_reply_desc(instance); | 5796 | megasas_reset_reply_desc(instance); |
| 5630 | if (megasas_ioc_init_fusion(instance)) { | 5797 | if (megasas_ioc_init_fusion(instance)) { |
| 5631 | megasas_free_cmds(instance); | 5798 | megasas_free_cmds(instance); |
| @@ -5634,14 +5801,11 @@ megasas_resume(struct pci_dev *pdev) | |||
| 5634 | } | 5801 | } |
| 5635 | if (!megasas_get_map_info(instance)) | 5802 | if (!megasas_get_map_info(instance)) |
| 5636 | megasas_sync_map_info(instance); | 5803 | megasas_sync_map_info(instance); |
| 5637 | } | 5804 | } else { |
| 5638 | break; | ||
| 5639 | default: | ||
| 5640 | *instance->producer = 0; | 5805 | *instance->producer = 0; |
| 5641 | *instance->consumer = 0; | 5806 | *instance->consumer = 0; |
| 5642 | if (megasas_issue_init_mfi(instance)) | 5807 | if (megasas_issue_init_mfi(instance)) |
| 5643 | goto fail_init_mfi; | 5808 | goto fail_init_mfi; |
| 5644 | break; | ||
| 5645 | } | 5809 | } |
| 5646 | 5810 | ||
| 5647 | tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet, | 5811 | tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet, |
| @@ -5666,6 +5830,7 @@ megasas_resume(struct pci_dev *pdev) | |||
| 5666 | } | 5830 | } |
| 5667 | 5831 | ||
| 5668 | instance->instancet->enable_intr(instance); | 5832 | instance->instancet->enable_intr(instance); |
| 5833 | megasas_setup_jbod_map(instance); | ||
| 5669 | instance->unload = 0; | 5834 | instance->unload = 0; |
| 5670 | 5835 | ||
| 5671 | /* | 5836 | /* |
| @@ -5713,6 +5878,7 @@ static void megasas_detach_one(struct pci_dev *pdev) | |||
| 5713 | struct Scsi_Host *host; | 5878 | struct Scsi_Host *host; |
| 5714 | struct megasas_instance *instance; | 5879 | struct megasas_instance *instance; |
| 5715 | struct fusion_context *fusion; | 5880 | struct fusion_context *fusion; |
| 5881 | u32 pd_seq_map_sz; | ||
| 5716 | 5882 | ||
| 5717 | instance = pci_get_drvdata(pdev); | 5883 | instance = pci_get_drvdata(pdev); |
| 5718 | instance->unload = 1; | 5884 | instance->unload = 1; |
| @@ -5761,12 +5927,11 @@ static void megasas_detach_one(struct pci_dev *pdev) | |||
| 5761 | if (instance->msix_vectors) | 5927 | if (instance->msix_vectors) |
| 5762 | pci_disable_msix(instance->pdev); | 5928 | pci_disable_msix(instance->pdev); |
| 5763 | 5929 | ||
| 5764 | switch (instance->pdev->device) { | 5930 | if (instance->ctrl_context) { |
| 5765 | case PCI_DEVICE_ID_LSI_FUSION: | ||
| 5766 | case PCI_DEVICE_ID_LSI_PLASMA: | ||
| 5767 | case PCI_DEVICE_ID_LSI_INVADER: | ||
| 5768 | case PCI_DEVICE_ID_LSI_FURY: | ||
| 5769 | megasas_release_fusion(instance); | 5931 | megasas_release_fusion(instance); |
| 5932 | pd_seq_map_sz = sizeof(struct MR_PD_CFG_SEQ_NUM_SYNC) + | ||
| 5933 | (sizeof(struct MR_PD_CFG_SEQ) * | ||
| 5934 | (MAX_PHYSICAL_DEVICES - 1)); | ||
| 5770 | for (i = 0; i < 2 ; i++) { | 5935 | for (i = 0; i < 2 ; i++) { |
| 5771 | if (fusion->ld_map[i]) | 5936 | if (fusion->ld_map[i]) |
| 5772 | dma_free_coherent(&instance->pdev->dev, | 5937 | dma_free_coherent(&instance->pdev->dev, |
| @@ -5776,11 +5941,15 @@ static void megasas_detach_one(struct pci_dev *pdev) | |||
| 5776 | if (fusion->ld_drv_map[i]) | 5941 | if (fusion->ld_drv_map[i]) |
| 5777 | free_pages((ulong)fusion->ld_drv_map[i], | 5942 | free_pages((ulong)fusion->ld_drv_map[i], |
| 5778 | fusion->drv_map_pages); | 5943 | fusion->drv_map_pages); |
| 5944 | if (fusion->pd_seq_sync) | ||
| 5945 | dma_free_coherent(&instance->pdev->dev, | ||
| 5946 | pd_seq_map_sz, | ||
| 5947 | fusion->pd_seq_sync[i], | ||
| 5948 | fusion->pd_seq_phys[i]); | ||
| 5779 | } | 5949 | } |
| 5780 | free_pages((ulong)instance->ctrl_context, | 5950 | free_pages((ulong)instance->ctrl_context, |
| 5781 | instance->ctrl_context_pages); | 5951 | instance->ctrl_context_pages); |
| 5782 | break; | 5952 | } else { |
| 5783 | default: | ||
| 5784 | megasas_release_mfi(instance); | 5953 | megasas_release_mfi(instance); |
| 5785 | pci_free_consistent(pdev, sizeof(u32), | 5954 | pci_free_consistent(pdev, sizeof(u32), |
| 5786 | instance->producer, | 5955 | instance->producer, |
| @@ -5788,7 +5957,6 @@ static void megasas_detach_one(struct pci_dev *pdev) | |||
| 5788 | pci_free_consistent(pdev, sizeof(u32), | 5957 | pci_free_consistent(pdev, sizeof(u32), |
| 5789 | instance->consumer, | 5958 | instance->consumer, |
| 5790 | instance->consumer_h); | 5959 | instance->consumer_h); |
| 5791 | break; | ||
| 5792 | } | 5960 | } |
| 5793 | 5961 | ||
| 5794 | kfree(instance->ctrl_info); | 5962 | kfree(instance->ctrl_info); |
| @@ -6308,6 +6476,9 @@ static int megasas_mgmt_compat_ioctl_fw(struct file *file, unsigned long arg) | |||
| 6308 | int i; | 6476 | int i; |
| 6309 | int error = 0; | 6477 | int error = 0; |
| 6310 | compat_uptr_t ptr; | 6478 | compat_uptr_t ptr; |
| 6479 | unsigned long local_raw_ptr; | ||
| 6480 | u32 local_sense_off; | ||
| 6481 | u32 local_sense_len; | ||
| 6311 | 6482 | ||
| 6312 | if (clear_user(ioc, sizeof(*ioc))) | 6483 | if (clear_user(ioc, sizeof(*ioc))) |
| 6313 | return -EFAULT; | 6484 | return -EFAULT; |
| @@ -6325,9 +6496,15 @@ static int megasas_mgmt_compat_ioctl_fw(struct file *file, unsigned long arg) | |||
| 6325 | * sense_len is not null, so prepare the 64bit value under | 6496 | * sense_len is not null, so prepare the 64bit value under |
| 6326 | * the same condition. | 6497 | * the same condition. |
| 6327 | */ | 6498 | */ |
| 6328 | if (ioc->sense_len) { | 6499 | if (get_user(local_raw_ptr, ioc->frame.raw) || |
| 6500 | get_user(local_sense_off, &ioc->sense_off) || | ||
| 6501 | get_user(local_sense_len, &ioc->sense_len)) | ||
| 6502 | return -EFAULT; | ||
| 6503 | |||
| 6504 | |||
| 6505 | if (local_sense_len) { | ||
| 6329 | void __user **sense_ioc_ptr = | 6506 | void __user **sense_ioc_ptr = |
| 6330 | (void __user **)(ioc->frame.raw + ioc->sense_off); | 6507 | (void __user **)((u8*)local_raw_ptr + local_sense_off); |
| 6331 | compat_uptr_t *sense_cioc_ptr = | 6508 | compat_uptr_t *sense_cioc_ptr = |
| 6332 | (compat_uptr_t *)(cioc->frame.raw + cioc->sense_off); | 6509 | (compat_uptr_t *)(cioc->frame.raw + cioc->sense_off); |
| 6333 | if (get_user(ptr, sense_cioc_ptr) || | 6510 | if (get_user(ptr, sense_cioc_ptr) || |
| @@ -6496,6 +6673,7 @@ megasas_aen_polling(struct work_struct *work) | |||
| 6496 | instance->ev = NULL; | 6673 | instance->ev = NULL; |
| 6497 | host = instance->host; | 6674 | host = instance->host; |
| 6498 | if (instance->evt_detail) { | 6675 | if (instance->evt_detail) { |
| 6676 | megasas_decode_evt(instance); | ||
| 6499 | 6677 | ||
| 6500 | switch (le32_to_cpu(instance->evt_detail->code)) { | 6678 | switch (le32_to_cpu(instance->evt_detail->code)) { |
| 6501 | case MR_EVT_PD_INSERTED: | 6679 | case MR_EVT_PD_INSERTED: |
| @@ -6556,8 +6734,7 @@ megasas_aen_polling(struct work_struct *work) | |||
| 6556 | case MR_EVT_CFG_CLEARED: | 6734 | case MR_EVT_CFG_CLEARED: |
| 6557 | case MR_EVT_LD_DELETED: | 6735 | case MR_EVT_LD_DELETED: |
| 6558 | if (!instance->requestorId || | 6736 | if (!instance->requestorId || |
| 6559 | (instance->requestorId && | 6737 | megasas_get_ld_vf_affiliation(instance, 0)) { |
| 6560 | megasas_get_ld_vf_affiliation(instance, 0))) { | ||
| 6561 | if (megasas_ld_list_query(instance, | 6738 | if (megasas_ld_list_query(instance, |
| 6562 | MR_LD_QUERY_TYPE_EXPOSED_TO_HOST)) | 6739 | MR_LD_QUERY_TYPE_EXPOSED_TO_HOST)) |
| 6563 | megasas_get_ld_list(instance); | 6740 | megasas_get_ld_list(instance); |
| @@ -6588,8 +6765,7 @@ megasas_aen_polling(struct work_struct *work) | |||
| 6588 | break; | 6765 | break; |
| 6589 | case MR_EVT_LD_CREATED: | 6766 | case MR_EVT_LD_CREATED: |
| 6590 | if (!instance->requestorId || | 6767 | if (!instance->requestorId || |
| 6591 | (instance->requestorId && | 6768 | megasas_get_ld_vf_affiliation(instance, 0)) { |
| 6592 | megasas_get_ld_vf_affiliation(instance, 0))) { | ||
| 6593 | if (megasas_ld_list_query(instance, | 6769 | if (megasas_ld_list_query(instance, |
| 6594 | MR_LD_QUERY_TYPE_EXPOSED_TO_HOST)) | 6770 | MR_LD_QUERY_TYPE_EXPOSED_TO_HOST)) |
| 6595 | megasas_get_ld_list(instance); | 6771 | megasas_get_ld_list(instance); |
| @@ -6619,6 +6795,9 @@ megasas_aen_polling(struct work_struct *work) | |||
| 6619 | case MR_EVT_LD_STATE_CHANGE: | 6795 | case MR_EVT_LD_STATE_CHANGE: |
| 6620 | doscan = 1; | 6796 | doscan = 1; |
| 6621 | break; | 6797 | break; |
| 6798 | case MR_EVT_CTRL_PROP_CHANGED: | ||
| 6799 | megasas_get_ctrl_info(instance); | ||
| 6800 | break; | ||
| 6622 | default: | 6801 | default: |
| 6623 | doscan = 0; | 6802 | doscan = 0; |
| 6624 | break; | 6803 | break; |
| @@ -6655,8 +6834,7 @@ megasas_aen_polling(struct work_struct *work) | |||
| 6655 | } | 6834 | } |
| 6656 | 6835 | ||
| 6657 | if (!instance->requestorId || | 6836 | if (!instance->requestorId || |
| 6658 | (instance->requestorId && | 6837 | megasas_get_ld_vf_affiliation(instance, 0)) { |
| 6659 | megasas_get_ld_vf_affiliation(instance, 0))) { | ||
| 6660 | if (megasas_ld_list_query(instance, | 6838 | if (megasas_ld_list_query(instance, |
| 6661 | MR_LD_QUERY_TYPE_EXPOSED_TO_HOST)) | 6839 | MR_LD_QUERY_TYPE_EXPOSED_TO_HOST)) |
| 6662 | megasas_get_ld_list(instance); | 6840 | megasas_get_ld_list(instance); |
diff --git a/drivers/scsi/megaraid/megaraid_sas_fp.c b/drivers/scsi/megaraid/megaraid_sas_fp.c index be57b18675a4..741509b35617 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fp.c +++ b/drivers/scsi/megaraid/megaraid_sas_fp.c | |||
| @@ -741,14 +741,12 @@ static u8 mr_spanset_get_phy_params(struct megasas_instance *instance, u32 ld, | |||
| 741 | u8 physArm, span; | 741 | u8 physArm, span; |
| 742 | u64 row; | 742 | u64 row; |
| 743 | u8 retval = TRUE; | 743 | u8 retval = TRUE; |
| 744 | u8 do_invader = 0; | ||
| 745 | u64 *pdBlock = &io_info->pdBlock; | 744 | u64 *pdBlock = &io_info->pdBlock; |
| 746 | __le16 *pDevHandle = &io_info->devHandle; | 745 | __le16 *pDevHandle = &io_info->devHandle; |
| 747 | u32 logArm, rowMod, armQ, arm; | 746 | u32 logArm, rowMod, armQ, arm; |
| 747 | struct fusion_context *fusion; | ||
| 748 | 748 | ||
| 749 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER || | 749 | fusion = instance->ctrl_context; |
| 750 | instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) | ||
| 751 | do_invader = 1; | ||
| 752 | 750 | ||
| 753 | /*Get row and span from io_info for Uneven Span IO.*/ | 751 | /*Get row and span from io_info for Uneven Span IO.*/ |
| 754 | row = io_info->start_row; | 752 | row = io_info->start_row; |
| @@ -779,7 +777,8 @@ static u8 mr_spanset_get_phy_params(struct megasas_instance *instance, u32 ld, | |||
| 779 | else { | 777 | else { |
| 780 | *pDevHandle = cpu_to_le16(MR_PD_INVALID); | 778 | *pDevHandle = cpu_to_le16(MR_PD_INVALID); |
| 781 | if ((raid->level >= 5) && | 779 | if ((raid->level >= 5) && |
| 782 | (!do_invader || (do_invader && | 780 | ((fusion->adapter_type == THUNDERBOLT_SERIES) || |
| 781 | ((fusion->adapter_type == INVADER_SERIES) && | ||
| 783 | (raid->regTypeReqOnRead != REGION_TYPE_UNUSED)))) | 782 | (raid->regTypeReqOnRead != REGION_TYPE_UNUSED)))) |
| 784 | pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE; | 783 | pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE; |
| 785 | else if (raid->level == 1) { | 784 | else if (raid->level == 1) { |
| @@ -823,13 +822,12 @@ u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow, | |||
| 823 | u8 physArm, span; | 822 | u8 physArm, span; |
| 824 | u64 row; | 823 | u64 row; |
| 825 | u8 retval = TRUE; | 824 | u8 retval = TRUE; |
| 826 | u8 do_invader = 0; | ||
| 827 | u64 *pdBlock = &io_info->pdBlock; | 825 | u64 *pdBlock = &io_info->pdBlock; |
| 828 | __le16 *pDevHandle = &io_info->devHandle; | 826 | __le16 *pDevHandle = &io_info->devHandle; |
| 827 | struct fusion_context *fusion; | ||
| 828 | |||
| 829 | fusion = instance->ctrl_context; | ||
| 829 | 830 | ||
| 830 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER || | ||
| 831 | instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) | ||
| 832 | do_invader = 1; | ||
| 833 | 831 | ||
| 834 | row = mega_div64_32(stripRow, raid->rowDataSize); | 832 | row = mega_div64_32(stripRow, raid->rowDataSize); |
| 835 | 833 | ||
| @@ -875,7 +873,8 @@ u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow, | |||
| 875 | /* set dev handle as invalid. */ | 873 | /* set dev handle as invalid. */ |
| 876 | *pDevHandle = cpu_to_le16(MR_PD_INVALID); | 874 | *pDevHandle = cpu_to_le16(MR_PD_INVALID); |
| 877 | if ((raid->level >= 5) && | 875 | if ((raid->level >= 5) && |
| 878 | (!do_invader || (do_invader && | 876 | ((fusion->adapter_type == THUNDERBOLT_SERIES) || |
| 877 | ((fusion->adapter_type == INVADER_SERIES) && | ||
| 879 | (raid->regTypeReqOnRead != REGION_TYPE_UNUSED)))) | 878 | (raid->regTypeReqOnRead != REGION_TYPE_UNUSED)))) |
| 880 | pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE; | 879 | pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE; |
| 881 | else if (raid->level == 1) { | 880 | else if (raid->level == 1) { |
| @@ -909,6 +908,7 @@ MR_BuildRaidContext(struct megasas_instance *instance, | |||
| 909 | struct RAID_CONTEXT *pRAID_Context, | 908 | struct RAID_CONTEXT *pRAID_Context, |
| 910 | struct MR_DRV_RAID_MAP_ALL *map, u8 **raidLUN) | 909 | struct MR_DRV_RAID_MAP_ALL *map, u8 **raidLUN) |
| 911 | { | 910 | { |
| 911 | struct fusion_context *fusion; | ||
| 912 | struct MR_LD_RAID *raid; | 912 | struct MR_LD_RAID *raid; |
| 913 | u32 ld, stripSize, stripe_mask; | 913 | u32 ld, stripSize, stripe_mask; |
| 914 | u64 endLba, endStrip, endRow, start_row, start_strip; | 914 | u64 endLba, endStrip, endRow, start_row, start_strip; |
| @@ -929,6 +929,7 @@ MR_BuildRaidContext(struct megasas_instance *instance, | |||
| 929 | isRead = io_info->isRead; | 929 | isRead = io_info->isRead; |
| 930 | io_info->IoforUnevenSpan = 0; | 930 | io_info->IoforUnevenSpan = 0; |
| 931 | io_info->start_span = SPAN_INVALID; | 931 | io_info->start_span = SPAN_INVALID; |
| 932 | fusion = instance->ctrl_context; | ||
| 932 | 933 | ||
| 933 | ld = MR_TargetIdToLdGet(ldTgtId, map); | 934 | ld = MR_TargetIdToLdGet(ldTgtId, map); |
| 934 | raid = MR_LdRaidGet(ld, map); | 935 | raid = MR_LdRaidGet(ld, map); |
| @@ -1092,8 +1093,7 @@ MR_BuildRaidContext(struct megasas_instance *instance, | |||
| 1092 | cpu_to_le16(raid->fpIoTimeoutForLd ? | 1093 | cpu_to_le16(raid->fpIoTimeoutForLd ? |
| 1093 | raid->fpIoTimeoutForLd : | 1094 | raid->fpIoTimeoutForLd : |
| 1094 | map->raidMap.fpPdIoTimeoutSec); | 1095 | map->raidMap.fpPdIoTimeoutSec); |
| 1095 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || | 1096 | if (fusion->adapter_type == INVADER_SERIES) |
| 1096 | (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) | ||
| 1097 | pRAID_Context->regLockFlags = (isRead) ? | 1097 | pRAID_Context->regLockFlags = (isRead) ? |
| 1098 | raid->regTypeReqOnRead : raid->regTypeReqOnWrite; | 1098 | raid->regTypeReqOnRead : raid->regTypeReqOnWrite; |
| 1099 | else | 1099 | else |
| @@ -1198,10 +1198,6 @@ void mr_update_span_set(struct MR_DRV_RAID_MAP_ALL *map, | |||
| 1198 | span_row_width += | 1198 | span_row_width += |
| 1199 | MR_LdSpanPtrGet | 1199 | MR_LdSpanPtrGet |
| 1200 | (ld, count, map)->spanRowDataSize; | 1200 | (ld, count, map)->spanRowDataSize; |
| 1201 | printk(KERN_INFO "megasas:" | ||
| 1202 | "span %x rowDataSize %x\n", | ||
| 1203 | count, MR_LdSpanPtrGet | ||
| 1204 | (ld, count, map)->spanRowDataSize); | ||
| 1205 | } | 1201 | } |
| 1206 | } | 1202 | } |
| 1207 | 1203 | ||
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index f0837cc3b163..8d630a552b07 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c | |||
| @@ -316,26 +316,23 @@ static int megasas_create_frame_pool_fusion(struct megasas_instance *instance) | |||
| 316 | u32 max_cmd; | 316 | u32 max_cmd; |
| 317 | struct fusion_context *fusion; | 317 | struct fusion_context *fusion; |
| 318 | struct megasas_cmd_fusion *cmd; | 318 | struct megasas_cmd_fusion *cmd; |
| 319 | u32 total_sz_chain_frame; | ||
| 320 | 319 | ||
| 321 | fusion = instance->ctrl_context; | 320 | fusion = instance->ctrl_context; |
| 322 | max_cmd = instance->max_fw_cmds; | 321 | max_cmd = instance->max_fw_cmds; |
| 323 | 322 | ||
| 324 | total_sz_chain_frame = MEGASAS_MAX_SZ_CHAIN_FRAME; | ||
| 325 | 323 | ||
| 326 | /* | 324 | /* |
| 327 | * Use DMA pool facility provided by PCI layer | 325 | * Use DMA pool facility provided by PCI layer |
| 328 | */ | 326 | */ |
| 329 | 327 | ||
| 330 | fusion->sg_dma_pool = pci_pool_create("megasas sg pool fusion", | 328 | fusion->sg_dma_pool = pci_pool_create("sg_pool_fusion", instance->pdev, |
| 331 | instance->pdev, | 329 | instance->max_chain_frame_sz, |
| 332 | total_sz_chain_frame, 4, | 330 | 4, 0); |
| 333 | 0); | ||
| 334 | if (!fusion->sg_dma_pool) { | 331 | if (!fusion->sg_dma_pool) { |
| 335 | dev_printk(KERN_DEBUG, &instance->pdev->dev, "failed to setup request pool fusion\n"); | 332 | dev_printk(KERN_DEBUG, &instance->pdev->dev, "failed to setup request pool fusion\n"); |
| 336 | return -ENOMEM; | 333 | return -ENOMEM; |
| 337 | } | 334 | } |
| 338 | fusion->sense_dma_pool = pci_pool_create("megasas sense pool fusion", | 335 | fusion->sense_dma_pool = pci_pool_create("sense pool fusion", |
| 339 | instance->pdev, | 336 | instance->pdev, |
| 340 | SCSI_SENSE_BUFFERSIZE, 64, 0); | 337 | SCSI_SENSE_BUFFERSIZE, 64, 0); |
| 341 | 338 | ||
| @@ -605,6 +602,7 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) | |||
| 605 | int i; | 602 | int i; |
| 606 | struct megasas_header *frame_hdr; | 603 | struct megasas_header *frame_hdr; |
| 607 | const char *sys_info; | 604 | const char *sys_info; |
| 605 | MFI_CAPABILITIES *drv_ops; | ||
| 608 | 606 | ||
| 609 | fusion = instance->ctrl_context; | 607 | fusion = instance->ctrl_context; |
| 610 | 608 | ||
| @@ -652,20 +650,21 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) | |||
| 652 | init_frame->cmd = MFI_CMD_INIT; | 650 | init_frame->cmd = MFI_CMD_INIT; |
| 653 | init_frame->cmd_status = 0xFF; | 651 | init_frame->cmd_status = 0xFF; |
| 654 | 652 | ||
| 653 | drv_ops = (MFI_CAPABILITIES *) &(init_frame->driver_operations); | ||
| 654 | |||
| 655 | /* driver support Extended MSIX */ | 655 | /* driver support Extended MSIX */ |
| 656 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || | 656 | if (fusion->adapter_type == INVADER_SERIES) |
| 657 | (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) | 657 | drv_ops->mfi_capabilities.support_additional_msix = 1; |
| 658 | init_frame->driver_operations. | ||
| 659 | mfi_capabilities.support_additional_msix = 1; | ||
| 660 | /* driver supports HA / Remote LUN over Fast Path interface */ | 658 | /* driver supports HA / Remote LUN over Fast Path interface */ |
| 661 | init_frame->driver_operations.mfi_capabilities.support_fp_remote_lun | 659 | drv_ops->mfi_capabilities.support_fp_remote_lun = 1; |
| 662 | = 1; | 660 | |
| 663 | init_frame->driver_operations.mfi_capabilities.support_max_255lds | 661 | drv_ops->mfi_capabilities.support_max_255lds = 1; |
| 664 | = 1; | 662 | drv_ops->mfi_capabilities.support_ndrive_r1_lb = 1; |
| 665 | init_frame->driver_operations.mfi_capabilities.support_ndrive_r1_lb | 663 | drv_ops->mfi_capabilities.security_protocol_cmds_fw = 1; |
| 666 | = 1; | 664 | |
| 667 | init_frame->driver_operations.mfi_capabilities.security_protocol_cmds_fw | 665 | if (instance->max_chain_frame_sz > MEGASAS_CHAIN_FRAME_SZ_MIN) |
| 668 | = 1; | 666 | drv_ops->mfi_capabilities.support_ext_io_size = 1; |
| 667 | |||
| 669 | /* Convert capability to LE32 */ | 668 | /* Convert capability to LE32 */ |
| 670 | cpu_to_le32s((u32 *)&init_frame->driver_operations.mfi_capabilities); | 669 | cpu_to_le32s((u32 *)&init_frame->driver_operations.mfi_capabilities); |
| 671 | 670 | ||
| @@ -726,6 +725,83 @@ fail_get_cmd: | |||
| 726 | return ret; | 725 | return ret; |
| 727 | } | 726 | } |
| 728 | 727 | ||
| 728 | /** | ||
| 729 | * megasas_sync_pd_seq_num - JBOD SEQ MAP | ||
| 730 | * @instance: Adapter soft state | ||
| 731 | * @pend: set to 1, if it is pended jbod map. | ||
| 732 | * | ||
| 733 | * Issue Jbod map to the firmware. If it is pended command, | ||
| 734 | * issue command and return. If it is first instance of jbod map | ||
| 735 | * issue and receive command. | ||
| 736 | */ | ||
| 737 | int | ||
| 738 | megasas_sync_pd_seq_num(struct megasas_instance *instance, bool pend) { | ||
| 739 | int ret = 0; | ||
| 740 | u32 pd_seq_map_sz; | ||
| 741 | struct megasas_cmd *cmd; | ||
| 742 | struct megasas_dcmd_frame *dcmd; | ||
| 743 | struct fusion_context *fusion = instance->ctrl_context; | ||
| 744 | struct MR_PD_CFG_SEQ_NUM_SYNC *pd_sync; | ||
| 745 | dma_addr_t pd_seq_h; | ||
| 746 | |||
| 747 | pd_sync = (void *)fusion->pd_seq_sync[(instance->pd_seq_map_id & 1)]; | ||
| 748 | pd_seq_h = fusion->pd_seq_phys[(instance->pd_seq_map_id & 1)]; | ||
| 749 | pd_seq_map_sz = sizeof(struct MR_PD_CFG_SEQ_NUM_SYNC) + | ||
| 750 | (sizeof(struct MR_PD_CFG_SEQ) * | ||
| 751 | (MAX_PHYSICAL_DEVICES - 1)); | ||
| 752 | |||
| 753 | cmd = megasas_get_cmd(instance); | ||
| 754 | if (!cmd) { | ||
| 755 | dev_err(&instance->pdev->dev, | ||
| 756 | "Could not get mfi cmd. Fail from %s %d\n", | ||
| 757 | __func__, __LINE__); | ||
| 758 | return -ENOMEM; | ||
| 759 | } | ||
| 760 | |||
| 761 | dcmd = &cmd->frame->dcmd; | ||
| 762 | |||
| 763 | memset(pd_sync, 0, pd_seq_map_sz); | ||
| 764 | memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); | ||
| 765 | dcmd->cmd = MFI_CMD_DCMD; | ||
| 766 | dcmd->cmd_status = 0xFF; | ||
| 767 | dcmd->sge_count = 1; | ||
| 768 | dcmd->timeout = 0; | ||
| 769 | dcmd->pad_0 = 0; | ||
| 770 | dcmd->data_xfer_len = cpu_to_le32(pd_seq_map_sz); | ||
| 771 | dcmd->opcode = cpu_to_le32(MR_DCMD_SYSTEM_PD_MAP_GET_INFO); | ||
| 772 | dcmd->sgl.sge32[0].phys_addr = cpu_to_le32(pd_seq_h); | ||
| 773 | dcmd->sgl.sge32[0].length = cpu_to_le32(pd_seq_map_sz); | ||
| 774 | |||
| 775 | if (pend) { | ||
| 776 | dcmd->mbox.b[0] = MEGASAS_DCMD_MBOX_PEND_FLAG; | ||
| 777 | dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_WRITE); | ||
| 778 | instance->jbod_seq_cmd = cmd; | ||
| 779 | instance->instancet->issue_dcmd(instance, cmd); | ||
| 780 | return 0; | ||
| 781 | } | ||
| 782 | |||
| 783 | dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_READ); | ||
| 784 | |||
| 785 | /* Below code is only for non pended DCMD */ | ||
| 786 | if (instance->ctrl_context && !instance->mask_interrupts) | ||
| 787 | ret = megasas_issue_blocked_cmd(instance, cmd, 60); | ||
| 788 | else | ||
| 789 | ret = megasas_issue_polled(instance, cmd); | ||
| 790 | |||
| 791 | if (le32_to_cpu(pd_sync->count) > MAX_PHYSICAL_DEVICES) { | ||
| 792 | dev_warn(&instance->pdev->dev, | ||
| 793 | "driver supports max %d JBOD, but FW reports %d\n", | ||
| 794 | MAX_PHYSICAL_DEVICES, le32_to_cpu(pd_sync->count)); | ||
| 795 | ret = -EINVAL; | ||
| 796 | } | ||
| 797 | |||
| 798 | if (!ret) | ||
| 799 | instance->pd_seq_map_id++; | ||
| 800 | |||
| 801 | megasas_return_cmd(instance, cmd); | ||
| 802 | return ret; | ||
| 803 | } | ||
| 804 | |||
| 729 | /* | 805 | /* |
| 730 | * megasas_get_ld_map_info - Returns FW's ld_map structure | 806 | * megasas_get_ld_map_info - Returns FW's ld_map structure |
| 731 | * @instance: Adapter soft state | 807 | * @instance: Adapter soft state |
| @@ -961,6 +1037,18 @@ megasas_display_intel_branding(struct megasas_instance *instance) | |||
| 961 | break; | 1037 | break; |
| 962 | } | 1038 | } |
| 963 | break; | 1039 | break; |
| 1040 | case PCI_DEVICE_ID_LSI_CUTLASS_52: | ||
| 1041 | case PCI_DEVICE_ID_LSI_CUTLASS_53: | ||
| 1042 | switch (instance->pdev->subsystem_device) { | ||
| 1043 | case MEGARAID_INTEL_RMS3BC160_SSDID: | ||
| 1044 | dev_info(&instance->pdev->dev, "scsi host %d: %s\n", | ||
| 1045 | instance->host->host_no, | ||
| 1046 | MEGARAID_INTEL_RMS3BC160_BRANDING); | ||
| 1047 | break; | ||
| 1048 | default: | ||
| 1049 | break; | ||
| 1050 | } | ||
| 1051 | break; | ||
| 964 | default: | 1052 | default: |
| 965 | break; | 1053 | break; |
| 966 | } | 1054 | } |
| @@ -977,7 +1065,7 @@ megasas_init_adapter_fusion(struct megasas_instance *instance) | |||
| 977 | { | 1065 | { |
| 978 | struct megasas_register_set __iomem *reg_set; | 1066 | struct megasas_register_set __iomem *reg_set; |
| 979 | struct fusion_context *fusion; | 1067 | struct fusion_context *fusion; |
| 980 | u32 max_cmd; | 1068 | u32 max_cmd, scratch_pad_2; |
| 981 | int i = 0, count; | 1069 | int i = 0, count; |
| 982 | 1070 | ||
| 983 | fusion = instance->ctrl_context; | 1071 | fusion = instance->ctrl_context; |
| @@ -1016,15 +1104,40 @@ megasas_init_adapter_fusion(struct megasas_instance *instance) | |||
| 1016 | (MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE * | 1104 | (MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE * |
| 1017 | (max_cmd + 1)); /* Extra 1 for SMID 0 */ | 1105 | (max_cmd + 1)); /* Extra 1 for SMID 0 */ |
| 1018 | 1106 | ||
| 1107 | scratch_pad_2 = readl(&instance->reg_set->outbound_scratch_pad_2); | ||
| 1108 | /* If scratch_pad_2 & MEGASAS_MAX_CHAIN_SIZE_UNITS_MASK is set, | ||
| 1109 | * Firmware support extended IO chain frame which is 4 times more than | ||
| 1110 | * legacy Firmware. | ||
| 1111 | * Legacy Firmware - Frame size is (8 * 128) = 1K | ||
| 1112 | * 1M IO Firmware - Frame size is (8 * 128 * 4) = 4K | ||
| 1113 | */ | ||
| 1114 | if (scratch_pad_2 & MEGASAS_MAX_CHAIN_SIZE_UNITS_MASK) | ||
| 1115 | instance->max_chain_frame_sz = | ||
| 1116 | ((scratch_pad_2 & MEGASAS_MAX_CHAIN_SIZE_MASK) >> | ||
| 1117 | MEGASAS_MAX_CHAIN_SHIFT) * MEGASAS_1MB_IO; | ||
| 1118 | else | ||
| 1119 | instance->max_chain_frame_sz = | ||
| 1120 | ((scratch_pad_2 & MEGASAS_MAX_CHAIN_SIZE_MASK) >> | ||
| 1121 | MEGASAS_MAX_CHAIN_SHIFT) * MEGASAS_256K_IO; | ||
| 1122 | |||
| 1123 | if (instance->max_chain_frame_sz < MEGASAS_CHAIN_FRAME_SZ_MIN) { | ||
| 1124 | dev_warn(&instance->pdev->dev, "frame size %d invalid, fall back to legacy max frame size %d\n", | ||
| 1125 | instance->max_chain_frame_sz, | ||
| 1126 | MEGASAS_CHAIN_FRAME_SZ_MIN); | ||
| 1127 | instance->max_chain_frame_sz = MEGASAS_CHAIN_FRAME_SZ_MIN; | ||
| 1128 | } | ||
| 1129 | |||
| 1019 | fusion->max_sge_in_main_msg = | 1130 | fusion->max_sge_in_main_msg = |
| 1020 | (MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE - | 1131 | (MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE |
| 1021 | offsetof(struct MPI2_RAID_SCSI_IO_REQUEST, SGL))/16; | 1132 | - offsetof(struct MPI2_RAID_SCSI_IO_REQUEST, SGL))/16; |
| 1022 | 1133 | ||
| 1023 | fusion->max_sge_in_chain = | 1134 | fusion->max_sge_in_chain = |
| 1024 | MEGASAS_MAX_SZ_CHAIN_FRAME / sizeof(union MPI2_SGE_IO_UNION); | 1135 | instance->max_chain_frame_sz |
| 1136 | / sizeof(union MPI2_SGE_IO_UNION); | ||
| 1025 | 1137 | ||
| 1026 | instance->max_num_sge = rounddown_pow_of_two( | 1138 | instance->max_num_sge = |
| 1027 | fusion->max_sge_in_main_msg + fusion->max_sge_in_chain - 2); | 1139 | rounddown_pow_of_two(fusion->max_sge_in_main_msg |
| 1140 | + fusion->max_sge_in_chain - 2); | ||
| 1028 | 1141 | ||
| 1029 | /* Used for pass thru MFI frame (DCMD) */ | 1142 | /* Used for pass thru MFI frame (DCMD) */ |
| 1030 | fusion->chain_offset_mfi_pthru = | 1143 | fusion->chain_offset_mfi_pthru = |
| @@ -1186,8 +1299,7 @@ megasas_make_sgl_fusion(struct megasas_instance *instance, | |||
| 1186 | 1299 | ||
| 1187 | fusion = instance->ctrl_context; | 1300 | fusion = instance->ctrl_context; |
| 1188 | 1301 | ||
| 1189 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || | 1302 | if (fusion->adapter_type == INVADER_SERIES) { |
| 1190 | (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) { | ||
| 1191 | struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr_end = sgl_ptr; | 1303 | struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr_end = sgl_ptr; |
| 1192 | sgl_ptr_end += fusion->max_sge_in_main_msg - 1; | 1304 | sgl_ptr_end += fusion->max_sge_in_main_msg - 1; |
| 1193 | sgl_ptr_end->Flags = 0; | 1305 | sgl_ptr_end->Flags = 0; |
| @@ -1204,11 +1316,9 @@ megasas_make_sgl_fusion(struct megasas_instance *instance, | |||
| 1204 | sgl_ptr->Length = cpu_to_le32(sg_dma_len(os_sgl)); | 1316 | sgl_ptr->Length = cpu_to_le32(sg_dma_len(os_sgl)); |
| 1205 | sgl_ptr->Address = cpu_to_le64(sg_dma_address(os_sgl)); | 1317 | sgl_ptr->Address = cpu_to_le64(sg_dma_address(os_sgl)); |
| 1206 | sgl_ptr->Flags = 0; | 1318 | sgl_ptr->Flags = 0; |
| 1207 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || | 1319 | if (fusion->adapter_type == INVADER_SERIES) |
| 1208 | (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) { | ||
| 1209 | if (i == sge_count - 1) | 1320 | if (i == sge_count - 1) |
| 1210 | sgl_ptr->Flags = IEEE_SGE_FLAGS_END_OF_LIST; | 1321 | sgl_ptr->Flags = IEEE_SGE_FLAGS_END_OF_LIST; |
| 1211 | } | ||
| 1212 | sgl_ptr++; | 1322 | sgl_ptr++; |
| 1213 | 1323 | ||
| 1214 | sg_processed = i + 1; | 1324 | sg_processed = i + 1; |
| @@ -1217,10 +1327,7 @@ megasas_make_sgl_fusion(struct megasas_instance *instance, | |||
| 1217 | (sge_count > fusion->max_sge_in_main_msg)) { | 1327 | (sge_count > fusion->max_sge_in_main_msg)) { |
| 1218 | 1328 | ||
| 1219 | struct MPI25_IEEE_SGE_CHAIN64 *sg_chain; | 1329 | struct MPI25_IEEE_SGE_CHAIN64 *sg_chain; |
| 1220 | if ((instance->pdev->device == | 1330 | if (fusion->adapter_type == INVADER_SERIES) { |
| 1221 | PCI_DEVICE_ID_LSI_INVADER) || | ||
| 1222 | (instance->pdev->device == | ||
| 1223 | PCI_DEVICE_ID_LSI_FURY)) { | ||
| 1224 | if ((le16_to_cpu(cmd->io_request->IoFlags) & | 1331 | if ((le16_to_cpu(cmd->io_request->IoFlags) & |
| 1225 | MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH) != | 1332 | MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH) != |
| 1226 | MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH) | 1333 | MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH) |
| @@ -1236,10 +1343,7 @@ megasas_make_sgl_fusion(struct megasas_instance *instance, | |||
| 1236 | sg_chain = sgl_ptr; | 1343 | sg_chain = sgl_ptr; |
| 1237 | /* Prepare chain element */ | 1344 | /* Prepare chain element */ |
| 1238 | sg_chain->NextChainOffset = 0; | 1345 | sg_chain->NextChainOffset = 0; |
| 1239 | if ((instance->pdev->device == | 1346 | if (fusion->adapter_type == INVADER_SERIES) |
| 1240 | PCI_DEVICE_ID_LSI_INVADER) || | ||
| 1241 | (instance->pdev->device == | ||
| 1242 | PCI_DEVICE_ID_LSI_FURY)) | ||
| 1243 | sg_chain->Flags = IEEE_SGE_FLAGS_CHAIN_ELEMENT; | 1347 | sg_chain->Flags = IEEE_SGE_FLAGS_CHAIN_ELEMENT; |
| 1244 | else | 1348 | else |
| 1245 | sg_chain->Flags = | 1349 | sg_chain->Flags = |
| @@ -1250,7 +1354,7 @@ megasas_make_sgl_fusion(struct megasas_instance *instance, | |||
| 1250 | 1354 | ||
| 1251 | sgl_ptr = | 1355 | sgl_ptr = |
| 1252 | (struct MPI25_IEEE_SGE_CHAIN64 *)cmd->sg_frame; | 1356 | (struct MPI25_IEEE_SGE_CHAIN64 *)cmd->sg_frame; |
| 1253 | memset(sgl_ptr, 0, MEGASAS_MAX_SZ_CHAIN_FRAME); | 1357 | memset(sgl_ptr, 0, instance->max_chain_frame_sz); |
| 1254 | } | 1358 | } |
| 1255 | } | 1359 | } |
| 1256 | 1360 | ||
| @@ -1556,8 +1660,7 @@ megasas_build_ldio_fusion(struct megasas_instance *instance, | |||
| 1556 | cmd->request_desc->SCSIIO.RequestFlags = | 1660 | cmd->request_desc->SCSIIO.RequestFlags = |
| 1557 | (MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY | 1661 | (MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY |
| 1558 | << MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); | 1662 | << MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); |
| 1559 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || | 1663 | if (fusion->adapter_type == INVADER_SERIES) { |
| 1560 | (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) { | ||
| 1561 | if (io_request->RaidContext.regLockFlags == | 1664 | if (io_request->RaidContext.regLockFlags == |
| 1562 | REGION_TYPE_UNUSED) | 1665 | REGION_TYPE_UNUSED) |
| 1563 | cmd->request_desc->SCSIIO.RequestFlags = | 1666 | cmd->request_desc->SCSIIO.RequestFlags = |
| @@ -1582,7 +1685,7 @@ megasas_build_ldio_fusion(struct megasas_instance *instance, | |||
| 1582 | scp->SCp.Status &= ~MEGASAS_LOAD_BALANCE_FLAG; | 1685 | scp->SCp.Status &= ~MEGASAS_LOAD_BALANCE_FLAG; |
| 1583 | 1686 | ||
| 1584 | if ((raidLUN[0] == 1) && | 1687 | if ((raidLUN[0] == 1) && |
| 1585 | (local_map_ptr->raidMap.devHndlInfo[io_info.pd_after_lb].validHandles > 2)) { | 1688 | (local_map_ptr->raidMap.devHndlInfo[io_info.pd_after_lb].validHandles > 1)) { |
| 1586 | instance->dev_handle = !(instance->dev_handle); | 1689 | instance->dev_handle = !(instance->dev_handle); |
| 1587 | io_info.devHandle = | 1690 | io_info.devHandle = |
| 1588 | local_map_ptr->raidMap.devHndlInfo[io_info.pd_after_lb].devHandle[instance->dev_handle]; | 1691 | local_map_ptr->raidMap.devHndlInfo[io_info.pd_after_lb].devHandle[instance->dev_handle]; |
| @@ -1598,8 +1701,7 @@ megasas_build_ldio_fusion(struct megasas_instance *instance, | |||
| 1598 | cmd->request_desc->SCSIIO.RequestFlags = | 1701 | cmd->request_desc->SCSIIO.RequestFlags = |
| 1599 | (MEGASAS_REQ_DESCRIPT_FLAGS_LD_IO | 1702 | (MEGASAS_REQ_DESCRIPT_FLAGS_LD_IO |
| 1600 | << MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); | 1703 | << MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); |
| 1601 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || | 1704 | if (fusion->adapter_type == INVADER_SERIES) { |
| 1602 | (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) { | ||
| 1603 | if (io_request->RaidContext.regLockFlags == | 1705 | if (io_request->RaidContext.regLockFlags == |
| 1604 | REGION_TYPE_UNUSED) | 1706 | REGION_TYPE_UNUSED) |
| 1605 | cmd->request_desc->SCSIIO.RequestFlags = | 1707 | cmd->request_desc->SCSIIO.RequestFlags = |
| @@ -1722,7 +1824,9 @@ megasas_build_syspd_fusion(struct megasas_instance *instance, | |||
| 1722 | u16 timeout_limit; | 1824 | u16 timeout_limit; |
| 1723 | struct MR_DRV_RAID_MAP_ALL *local_map_ptr; | 1825 | struct MR_DRV_RAID_MAP_ALL *local_map_ptr; |
| 1724 | struct RAID_CONTEXT *pRAID_Context; | 1826 | struct RAID_CONTEXT *pRAID_Context; |
| 1827 | struct MR_PD_CFG_SEQ_NUM_SYNC *pd_sync; | ||
| 1725 | struct fusion_context *fusion = instance->ctrl_context; | 1828 | struct fusion_context *fusion = instance->ctrl_context; |
| 1829 | pd_sync = (void *)fusion->pd_seq_sync[(instance->pd_seq_map_id - 1) & 1]; | ||
| 1726 | 1830 | ||
| 1727 | device_id = MEGASAS_DEV_INDEX(scmd); | 1831 | device_id = MEGASAS_DEV_INDEX(scmd); |
| 1728 | pd_index = MEGASAS_PD_INDEX(scmd); | 1832 | pd_index = MEGASAS_PD_INDEX(scmd); |
| @@ -1731,16 +1835,38 @@ megasas_build_syspd_fusion(struct megasas_instance *instance, | |||
| 1731 | io_request = cmd->io_request; | 1835 | io_request = cmd->io_request; |
| 1732 | /* get RAID_Context pointer */ | 1836 | /* get RAID_Context pointer */ |
| 1733 | pRAID_Context = &io_request->RaidContext; | 1837 | pRAID_Context = &io_request->RaidContext; |
| 1838 | pRAID_Context->regLockFlags = 0; | ||
| 1839 | pRAID_Context->regLockRowLBA = 0; | ||
| 1840 | pRAID_Context->regLockLength = 0; | ||
| 1734 | io_request->DataLength = cpu_to_le32(scsi_bufflen(scmd)); | 1841 | io_request->DataLength = cpu_to_le32(scsi_bufflen(scmd)); |
| 1735 | io_request->LUN[1] = scmd->device->lun; | 1842 | io_request->LUN[1] = scmd->device->lun; |
| 1736 | pRAID_Context->RAIDFlags = MR_RAID_FLAGS_IO_SUB_TYPE_SYSTEM_PD | 1843 | pRAID_Context->RAIDFlags = MR_RAID_FLAGS_IO_SUB_TYPE_SYSTEM_PD |
| 1737 | << MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT; | 1844 | << MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT; |
| 1738 | 1845 | ||
| 1739 | pRAID_Context->VirtualDiskTgtId = cpu_to_le16(device_id); | 1846 | /* If FW supports PD sequence number */ |
| 1740 | pRAID_Context->configSeqNum = 0; | 1847 | if (instance->use_seqnum_jbod_fp && |
| 1741 | local_map_ptr = fusion->ld_drv_map[(instance->map_id & 1)]; | 1848 | instance->pd_list[pd_index].driveType == TYPE_DISK) { |
| 1742 | io_request->DevHandle = | 1849 | /* TgtId must be incremented by 255 as jbod seq number is index |
| 1743 | local_map_ptr->raidMap.devHndlInfo[device_id].curDevHdl; | 1850 | * below raid map |
| 1851 | */ | ||
| 1852 | pRAID_Context->VirtualDiskTgtId = | ||
| 1853 | cpu_to_le16(device_id + (MAX_PHYSICAL_DEVICES - 1)); | ||
| 1854 | pRAID_Context->configSeqNum = pd_sync->seq[pd_index].seqNum; | ||
| 1855 | io_request->DevHandle = pd_sync->seq[pd_index].devHandle; | ||
| 1856 | pRAID_Context->regLockFlags |= | ||
| 1857 | (MR_RL_FLAGS_SEQ_NUM_ENABLE|MR_RL_FLAGS_GRANT_DESTINATION_CUDA); | ||
| 1858 | } else if (fusion->fast_path_io) { | ||
| 1859 | pRAID_Context->VirtualDiskTgtId = cpu_to_le16(device_id); | ||
| 1860 | pRAID_Context->configSeqNum = 0; | ||
| 1861 | local_map_ptr = fusion->ld_drv_map[(instance->map_id & 1)]; | ||
| 1862 | io_request->DevHandle = | ||
| 1863 | local_map_ptr->raidMap.devHndlInfo[device_id].curDevHdl; | ||
| 1864 | } else { | ||
| 1865 | /* Want to send all IO via FW path */ | ||
| 1866 | pRAID_Context->VirtualDiskTgtId = cpu_to_le16(device_id); | ||
| 1867 | pRAID_Context->configSeqNum = 0; | ||
| 1868 | io_request->DevHandle = cpu_to_le16(0xFFFF); | ||
| 1869 | } | ||
| 1744 | 1870 | ||
| 1745 | cmd->request_desc->SCSIIO.DevHandle = io_request->DevHandle; | 1871 | cmd->request_desc->SCSIIO.DevHandle = io_request->DevHandle; |
| 1746 | cmd->request_desc->SCSIIO.MSIxIndex = | 1872 | cmd->request_desc->SCSIIO.MSIxIndex = |
| @@ -1755,22 +1881,16 @@ megasas_build_syspd_fusion(struct megasas_instance *instance, | |||
| 1755 | (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO << | 1881 | (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO << |
| 1756 | MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); | 1882 | MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); |
| 1757 | pRAID_Context->timeoutValue = cpu_to_le16(os_timeout_value); | 1883 | pRAID_Context->timeoutValue = cpu_to_le16(os_timeout_value); |
| 1884 | pRAID_Context->VirtualDiskTgtId = cpu_to_le16(device_id); | ||
| 1758 | } else { | 1885 | } else { |
| 1759 | /* system pd Fast Path */ | 1886 | /* system pd Fast Path */ |
| 1760 | io_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST; | 1887 | io_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST; |
| 1761 | pRAID_Context->regLockFlags = 0; | ||
| 1762 | pRAID_Context->regLockRowLBA = 0; | ||
| 1763 | pRAID_Context->regLockLength = 0; | ||
| 1764 | timeout_limit = (scmd->device->type == TYPE_DISK) ? | 1888 | timeout_limit = (scmd->device->type == TYPE_DISK) ? |
| 1765 | 255 : 0xFFFF; | 1889 | 255 : 0xFFFF; |
| 1766 | pRAID_Context->timeoutValue = | 1890 | pRAID_Context->timeoutValue = |
| 1767 | cpu_to_le16((os_timeout_value > timeout_limit) ? | 1891 | cpu_to_le16((os_timeout_value > timeout_limit) ? |
| 1768 | timeout_limit : os_timeout_value); | 1892 | timeout_limit : os_timeout_value); |
| 1769 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || | 1893 | if (fusion->adapter_type == INVADER_SERIES) { |
| 1770 | (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) { | ||
| 1771 | cmd->request_desc->SCSIIO.RequestFlags |= | ||
| 1772 | (MEGASAS_REQ_DESCRIPT_FLAGS_NO_LOCK << | ||
| 1773 | MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); | ||
| 1774 | pRAID_Context->Type = MPI2_TYPE_CUDA; | 1894 | pRAID_Context->Type = MPI2_TYPE_CUDA; |
| 1775 | pRAID_Context->nseg = 0x1; | 1895 | pRAID_Context->nseg = 0x1; |
| 1776 | io_request->IoFlags |= | 1896 | io_request->IoFlags |= |
| @@ -1796,7 +1916,7 @@ megasas_build_io_fusion(struct megasas_instance *instance, | |||
| 1796 | struct scsi_cmnd *scp, | 1916 | struct scsi_cmnd *scp, |
| 1797 | struct megasas_cmd_fusion *cmd) | 1917 | struct megasas_cmd_fusion *cmd) |
| 1798 | { | 1918 | { |
| 1799 | u32 sge_count; | 1919 | u16 sge_count; |
| 1800 | u8 cmd_type; | 1920 | u8 cmd_type; |
| 1801 | struct MPI2_RAID_SCSI_IO_REQUEST *io_request = cmd->io_request; | 1921 | struct MPI2_RAID_SCSI_IO_REQUEST *io_request = cmd->io_request; |
| 1802 | 1922 | ||
| @@ -1854,7 +1974,11 @@ megasas_build_io_fusion(struct megasas_instance *instance, | |||
| 1854 | return 1; | 1974 | return 1; |
| 1855 | } | 1975 | } |
| 1856 | 1976 | ||
| 1977 | /* numSGE store lower 8 bit of sge_count. | ||
| 1978 | * numSGEExt store higher 8 bit of sge_count | ||
| 1979 | */ | ||
| 1857 | io_request->RaidContext.numSGE = sge_count; | 1980 | io_request->RaidContext.numSGE = sge_count; |
| 1981 | io_request->RaidContext.numSGEExt = (u8)(sge_count >> 8); | ||
| 1858 | 1982 | ||
| 1859 | io_request->SGLFlags = cpu_to_le16(MPI2_SGE_FLAGS_64_BIT_ADDRESSING); | 1983 | io_request->SGLFlags = cpu_to_le16(MPI2_SGE_FLAGS_64_BIT_ADDRESSING); |
| 1860 | 1984 | ||
| @@ -2084,10 +2208,7 @@ complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex) | |||
| 2084 | * pending to be completed | 2208 | * pending to be completed |
| 2085 | */ | 2209 | */ |
| 2086 | if (threshold_reply_count >= THRESHOLD_REPLY_COUNT) { | 2210 | if (threshold_reply_count >= THRESHOLD_REPLY_COUNT) { |
| 2087 | if ((instance->pdev->device == | 2211 | if (fusion->adapter_type == INVADER_SERIES) |
| 2088 | PCI_DEVICE_ID_LSI_INVADER) || | ||
| 2089 | (instance->pdev->device == | ||
| 2090 | PCI_DEVICE_ID_LSI_FURY)) | ||
| 2091 | writel(((MSIxIndex & 0x7) << 24) | | 2212 | writel(((MSIxIndex & 0x7) << 24) | |
| 2092 | fusion->last_reply_idx[MSIxIndex], | 2213 | fusion->last_reply_idx[MSIxIndex], |
| 2093 | instance->reply_post_host_index_addr[MSIxIndex/8]); | 2214 | instance->reply_post_host_index_addr[MSIxIndex/8]); |
| @@ -2103,8 +2224,7 @@ complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex) | |||
| 2103 | return IRQ_NONE; | 2224 | return IRQ_NONE; |
| 2104 | 2225 | ||
| 2105 | wmb(); | 2226 | wmb(); |
| 2106 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || | 2227 | if (fusion->adapter_type == INVADER_SERIES) |
| 2107 | (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) | ||
| 2108 | writel(((MSIxIndex & 0x7) << 24) | | 2228 | writel(((MSIxIndex & 0x7) << 24) | |
| 2109 | fusion->last_reply_idx[MSIxIndex], | 2229 | fusion->last_reply_idx[MSIxIndex], |
| 2110 | instance->reply_post_host_index_addr[MSIxIndex/8]); | 2230 | instance->reply_post_host_index_addr[MSIxIndex/8]); |
| @@ -2227,8 +2347,7 @@ build_mpt_mfi_pass_thru(struct megasas_instance *instance, | |||
| 2227 | 2347 | ||
| 2228 | io_req = cmd->io_request; | 2348 | io_req = cmd->io_request; |
| 2229 | 2349 | ||
| 2230 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || | 2350 | if (fusion->adapter_type == INVADER_SERIES) { |
| 2231 | (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) { | ||
| 2232 | struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr_end = | 2351 | struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr_end = |
| 2233 | (struct MPI25_IEEE_SGE_CHAIN64 *)&io_req->SGL; | 2352 | (struct MPI25_IEEE_SGE_CHAIN64 *)&io_req->SGL; |
| 2234 | sgl_ptr_end += fusion->max_sge_in_main_msg - 1; | 2353 | sgl_ptr_end += fusion->max_sge_in_main_msg - 1; |
| @@ -2248,7 +2367,7 @@ build_mpt_mfi_pass_thru(struct megasas_instance *instance, | |||
| 2248 | mpi25_ieee_chain->Flags = IEEE_SGE_FLAGS_CHAIN_ELEMENT | | 2367 | mpi25_ieee_chain->Flags = IEEE_SGE_FLAGS_CHAIN_ELEMENT | |
| 2249 | MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR; | 2368 | MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR; |
| 2250 | 2369 | ||
| 2251 | mpi25_ieee_chain->Length = cpu_to_le32(MEGASAS_MAX_SZ_CHAIN_FRAME); | 2370 | mpi25_ieee_chain->Length = cpu_to_le32(instance->max_chain_frame_sz); |
| 2252 | 2371 | ||
| 2253 | return 0; | 2372 | return 0; |
| 2254 | } | 2373 | } |
| @@ -2384,6 +2503,70 @@ static int | |||
| 2384 | megasas_adp_reset_fusion(struct megasas_instance *instance, | 2503 | megasas_adp_reset_fusion(struct megasas_instance *instance, |
| 2385 | struct megasas_register_set __iomem *regs) | 2504 | struct megasas_register_set __iomem *regs) |
| 2386 | { | 2505 | { |
| 2506 | u32 host_diag, abs_state, retry; | ||
| 2507 | |||
| 2508 | /* Now try to reset the chip */ | ||
| 2509 | writel(MPI2_WRSEQ_FLUSH_KEY_VALUE, &instance->reg_set->fusion_seq_offset); | ||
| 2510 | writel(MPI2_WRSEQ_1ST_KEY_VALUE, &instance->reg_set->fusion_seq_offset); | ||
| 2511 | writel(MPI2_WRSEQ_2ND_KEY_VALUE, &instance->reg_set->fusion_seq_offset); | ||
| 2512 | writel(MPI2_WRSEQ_3RD_KEY_VALUE, &instance->reg_set->fusion_seq_offset); | ||
| 2513 | writel(MPI2_WRSEQ_4TH_KEY_VALUE, &instance->reg_set->fusion_seq_offset); | ||
| 2514 | writel(MPI2_WRSEQ_5TH_KEY_VALUE, &instance->reg_set->fusion_seq_offset); | ||
| 2515 | writel(MPI2_WRSEQ_6TH_KEY_VALUE, &instance->reg_set->fusion_seq_offset); | ||
| 2516 | |||
| 2517 | /* Check that the diag write enable (DRWE) bit is on */ | ||
| 2518 | host_diag = readl(&instance->reg_set->fusion_host_diag); | ||
| 2519 | retry = 0; | ||
| 2520 | while (!(host_diag & HOST_DIAG_WRITE_ENABLE)) { | ||
| 2521 | msleep(100); | ||
| 2522 | host_diag = readl(&instance->reg_set->fusion_host_diag); | ||
| 2523 | if (retry++ == 100) { | ||
| 2524 | dev_warn(&instance->pdev->dev, | ||
| 2525 | "Host diag unlock failed from %s %d\n", | ||
| 2526 | __func__, __LINE__); | ||
| 2527 | break; | ||
| 2528 | } | ||
| 2529 | } | ||
| 2530 | if (!(host_diag & HOST_DIAG_WRITE_ENABLE)) | ||
| 2531 | return -1; | ||
| 2532 | |||
| 2533 | /* Send chip reset command */ | ||
| 2534 | writel(host_diag | HOST_DIAG_RESET_ADAPTER, | ||
| 2535 | &instance->reg_set->fusion_host_diag); | ||
| 2536 | msleep(3000); | ||
| 2537 | |||
| 2538 | /* Make sure reset adapter bit is cleared */ | ||
| 2539 | host_diag = readl(&instance->reg_set->fusion_host_diag); | ||
| 2540 | retry = 0; | ||
| 2541 | while (host_diag & HOST_DIAG_RESET_ADAPTER) { | ||
| 2542 | msleep(100); | ||
| 2543 | host_diag = readl(&instance->reg_set->fusion_host_diag); | ||
| 2544 | if (retry++ == 1000) { | ||
| 2545 | dev_warn(&instance->pdev->dev, | ||
| 2546 | "Diag reset adapter never cleared %s %d\n", | ||
| 2547 | __func__, __LINE__); | ||
| 2548 | break; | ||
| 2549 | } | ||
| 2550 | } | ||
| 2551 | if (host_diag & HOST_DIAG_RESET_ADAPTER) | ||
| 2552 | return -1; | ||
| 2553 | |||
| 2554 | abs_state = instance->instancet->read_fw_status_reg(instance->reg_set) | ||
| 2555 | & MFI_STATE_MASK; | ||
| 2556 | retry = 0; | ||
| 2557 | |||
| 2558 | while ((abs_state <= MFI_STATE_FW_INIT) && (retry++ < 1000)) { | ||
| 2559 | msleep(100); | ||
| 2560 | abs_state = instance->instancet-> | ||
| 2561 | read_fw_status_reg(instance->reg_set) & MFI_STATE_MASK; | ||
| 2562 | } | ||
| 2563 | if (abs_state <= MFI_STATE_FW_INIT) { | ||
| 2564 | dev_warn(&instance->pdev->dev, | ||
| 2565 | "fw state < MFI_STATE_FW_INIT, state = 0x%x %s %d\n", | ||
| 2566 | abs_state, __func__, __LINE__); | ||
| 2567 | return -1; | ||
| 2568 | } | ||
| 2569 | |||
| 2387 | return 0; | 2570 | return 0; |
| 2388 | } | 2571 | } |
| 2389 | 2572 | ||
| @@ -2512,8 +2695,10 @@ void megasas_refire_mgmt_cmd(struct megasas_instance *instance) | |||
| 2512 | continue; | 2695 | continue; |
| 2513 | req_desc = megasas_get_request_descriptor | 2696 | req_desc = megasas_get_request_descriptor |
| 2514 | (instance, smid - 1); | 2697 | (instance, smid - 1); |
| 2515 | if (req_desc && (cmd_mfi->frame->dcmd.opcode != | 2698 | if (req_desc && ((cmd_mfi->frame->dcmd.opcode != |
| 2516 | cpu_to_le32(MR_DCMD_LD_MAP_GET_INFO))) | 2699 | cpu_to_le32(MR_DCMD_LD_MAP_GET_INFO)) && |
| 2700 | (cmd_mfi->frame->dcmd.opcode != | ||
| 2701 | cpu_to_le32(MR_DCMD_SYSTEM_PD_MAP_GET_INFO)))) | ||
| 2517 | megasas_fire_cmd_fusion(instance, req_desc); | 2702 | megasas_fire_cmd_fusion(instance, req_desc); |
| 2518 | else | 2703 | else |
| 2519 | megasas_return_cmd(instance, cmd_mfi); | 2704 | megasas_return_cmd(instance, cmd_mfi); |
| @@ -2547,11 +2732,11 @@ out: | |||
| 2547 | /* Core fusion reset function */ | 2732 | /* Core fusion reset function */ |
| 2548 | int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout) | 2733 | int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout) |
| 2549 | { | 2734 | { |
| 2550 | int retval = SUCCESS, i, retry = 0, convert = 0; | 2735 | int retval = SUCCESS, i, convert = 0; |
| 2551 | struct megasas_instance *instance; | 2736 | struct megasas_instance *instance; |
| 2552 | struct megasas_cmd_fusion *cmd_fusion; | 2737 | struct megasas_cmd_fusion *cmd_fusion; |
| 2553 | struct fusion_context *fusion; | 2738 | struct fusion_context *fusion; |
| 2554 | u32 host_diag, abs_state, status_reg, reset_adapter; | 2739 | u32 abs_state, status_reg, reset_adapter; |
| 2555 | u32 io_timeout_in_crash_mode = 0; | 2740 | u32 io_timeout_in_crash_mode = 0; |
| 2556 | struct scsi_cmnd *scmd_local = NULL; | 2741 | struct scsi_cmnd *scmd_local = NULL; |
| 2557 | 2742 | ||
| @@ -2705,82 +2890,11 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout) | |||
| 2705 | 2890 | ||
| 2706 | /* Now try to reset the chip */ | 2891 | /* Now try to reset the chip */ |
| 2707 | for (i = 0; i < MEGASAS_FUSION_MAX_RESET_TRIES; i++) { | 2892 | for (i = 0; i < MEGASAS_FUSION_MAX_RESET_TRIES; i++) { |
| 2708 | writel(MPI2_WRSEQ_FLUSH_KEY_VALUE, | ||
| 2709 | &instance->reg_set->fusion_seq_offset); | ||
| 2710 | writel(MPI2_WRSEQ_1ST_KEY_VALUE, | ||
| 2711 | &instance->reg_set->fusion_seq_offset); | ||
| 2712 | writel(MPI2_WRSEQ_2ND_KEY_VALUE, | ||
| 2713 | &instance->reg_set->fusion_seq_offset); | ||
| 2714 | writel(MPI2_WRSEQ_3RD_KEY_VALUE, | ||
| 2715 | &instance->reg_set->fusion_seq_offset); | ||
| 2716 | writel(MPI2_WRSEQ_4TH_KEY_VALUE, | ||
| 2717 | &instance->reg_set->fusion_seq_offset); | ||
| 2718 | writel(MPI2_WRSEQ_5TH_KEY_VALUE, | ||
| 2719 | &instance->reg_set->fusion_seq_offset); | ||
| 2720 | writel(MPI2_WRSEQ_6TH_KEY_VALUE, | ||
| 2721 | &instance->reg_set->fusion_seq_offset); | ||
| 2722 | |||
| 2723 | /* Check that the diag write enable (DRWE) bit is on */ | ||
| 2724 | host_diag = readl(&instance->reg_set->fusion_host_diag); | ||
| 2725 | retry = 0; | ||
| 2726 | while (!(host_diag & HOST_DIAG_WRITE_ENABLE)) { | ||
| 2727 | msleep(100); | ||
| 2728 | host_diag = | ||
| 2729 | readl(&instance->reg_set->fusion_host_diag); | ||
| 2730 | if (retry++ == 100) { | ||
| 2731 | dev_warn(&instance->pdev->dev, | ||
| 2732 | "Host diag unlock failed! " | ||
| 2733 | "for scsi%d\n", | ||
| 2734 | instance->host->host_no); | ||
| 2735 | break; | ||
| 2736 | } | ||
| 2737 | } | ||
| 2738 | if (!(host_diag & HOST_DIAG_WRITE_ENABLE)) | ||
| 2739 | continue; | ||
| 2740 | 2893 | ||
| 2741 | /* Send chip reset command */ | 2894 | if (instance->instancet->adp_reset |
| 2742 | writel(host_diag | HOST_DIAG_RESET_ADAPTER, | 2895 | (instance, instance->reg_set)) |
| 2743 | &instance->reg_set->fusion_host_diag); | ||
| 2744 | msleep(3000); | ||
| 2745 | |||
| 2746 | /* Make sure reset adapter bit is cleared */ | ||
| 2747 | host_diag = readl(&instance->reg_set->fusion_host_diag); | ||
| 2748 | retry = 0; | ||
| 2749 | while (host_diag & HOST_DIAG_RESET_ADAPTER) { | ||
| 2750 | msleep(100); | ||
| 2751 | host_diag = | ||
| 2752 | readl(&instance->reg_set->fusion_host_diag); | ||
| 2753 | if (retry++ == 1000) { | ||
| 2754 | dev_warn(&instance->pdev->dev, | ||
| 2755 | "Diag reset adapter never " | ||
| 2756 | "cleared for scsi%d!\n", | ||
| 2757 | instance->host->host_no); | ||
| 2758 | break; | ||
| 2759 | } | ||
| 2760 | } | ||
| 2761 | if (host_diag & HOST_DIAG_RESET_ADAPTER) | ||
| 2762 | continue; | 2896 | continue; |
| 2763 | 2897 | ||
| 2764 | abs_state = | ||
| 2765 | instance->instancet->read_fw_status_reg( | ||
| 2766 | instance->reg_set) & MFI_STATE_MASK; | ||
| 2767 | retry = 0; | ||
| 2768 | |||
| 2769 | while ((abs_state <= MFI_STATE_FW_INIT) && | ||
| 2770 | (retry++ < 1000)) { | ||
| 2771 | msleep(100); | ||
| 2772 | abs_state = | ||
| 2773 | instance->instancet->read_fw_status_reg( | ||
| 2774 | instance->reg_set) & MFI_STATE_MASK; | ||
| 2775 | } | ||
| 2776 | if (abs_state <= MFI_STATE_FW_INIT) { | ||
| 2777 | dev_warn(&instance->pdev->dev, "firmware " | ||
| 2778 | "state < MFI_STATE_FW_INIT, state = " | ||
| 2779 | "0x%x for scsi%d\n", abs_state, | ||
| 2780 | instance->host->host_no); | ||
| 2781 | continue; | ||
| 2782 | } | ||
| 2783 | |||
| 2784 | /* Wait for FW to become ready */ | 2898 | /* Wait for FW to become ready */ |
| 2785 | if (megasas_transition_to_ready(instance, 1)) { | 2899 | if (megasas_transition_to_ready(instance, 1)) { |
| 2786 | dev_warn(&instance->pdev->dev, "Failed to " | 2900 | dev_warn(&instance->pdev->dev, "Failed to " |
| @@ -2816,6 +2930,8 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout) | |||
| 2816 | if (!megasas_get_map_info(instance)) | 2930 | if (!megasas_get_map_info(instance)) |
| 2817 | megasas_sync_map_info(instance); | 2931 | megasas_sync_map_info(instance); |
| 2818 | 2932 | ||
| 2933 | megasas_setup_jbod_map(instance); | ||
| 2934 | |||
| 2819 | clear_bit(MEGASAS_FUSION_IN_RESET, | 2935 | clear_bit(MEGASAS_FUSION_IN_RESET, |
| 2820 | &instance->reset_flags); | 2936 | &instance->reset_flags); |
| 2821 | instance->instancet->enable_intr(instance); | 2937 | instance->instancet->enable_intr(instance); |
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.h b/drivers/scsi/megaraid/megaraid_sas_fusion.h index ced6dc0cf8e8..473005c99b44 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.h +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.h | |||
| @@ -35,8 +35,13 @@ | |||
| 35 | #define _MEGARAID_SAS_FUSION_H_ | 35 | #define _MEGARAID_SAS_FUSION_H_ |
| 36 | 36 | ||
| 37 | /* Fusion defines */ | 37 | /* Fusion defines */ |
| 38 | #define MEGASAS_MAX_SZ_CHAIN_FRAME 1024 | 38 | #define MEGASAS_CHAIN_FRAME_SZ_MIN 1024 |
| 39 | #define MFI_FUSION_ENABLE_INTERRUPT_MASK (0x00000009) | 39 | #define MFI_FUSION_ENABLE_INTERRUPT_MASK (0x00000009) |
| 40 | #define MEGASAS_MAX_CHAIN_SHIFT 5 | ||
| 41 | #define MEGASAS_MAX_CHAIN_SIZE_UNITS_MASK 0x400000 | ||
| 42 | #define MEGASAS_MAX_CHAIN_SIZE_MASK 0x3E0 | ||
| 43 | #define MEGASAS_256K_IO 128 | ||
| 44 | #define MEGASAS_1MB_IO (MEGASAS_256K_IO * 4) | ||
| 40 | #define MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE 256 | 45 | #define MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE 256 |
| 41 | #define MEGASAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST 0xF0 | 46 | #define MEGASAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST 0xF0 |
| 42 | #define MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST 0xF1 | 47 | #define MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST 0xF1 |
| @@ -89,6 +94,12 @@ enum MR_RAID_FLAGS_IO_SUB_TYPE { | |||
| 89 | #define MEGASAS_FP_CMD_LEN 16 | 94 | #define MEGASAS_FP_CMD_LEN 16 |
| 90 | #define MEGASAS_FUSION_IN_RESET 0 | 95 | #define MEGASAS_FUSION_IN_RESET 0 |
| 91 | #define THRESHOLD_REPLY_COUNT 50 | 96 | #define THRESHOLD_REPLY_COUNT 50 |
| 97 | #define JBOD_MAPS_COUNT 2 | ||
| 98 | |||
| 99 | enum MR_FUSION_ADAPTER_TYPE { | ||
| 100 | THUNDERBOLT_SERIES = 0, | ||
| 101 | INVADER_SERIES = 1, | ||
| 102 | }; | ||
| 92 | 103 | ||
| 93 | /* | 104 | /* |
| 94 | * Raid Context structure which describes MegaRAID specific IO Parameters | 105 | * Raid Context structure which describes MegaRAID specific IO Parameters |
| @@ -117,7 +128,9 @@ struct RAID_CONTEXT { | |||
| 117 | u8 numSGE; | 128 | u8 numSGE; |
| 118 | __le16 configSeqNum; | 129 | __le16 configSeqNum; |
| 119 | u8 spanArm; | 130 | u8 spanArm; |
| 120 | u8 resvd2[3]; | 131 | u8 priority; |
| 132 | u8 numSGEExt; | ||
| 133 | u8 resvd2; | ||
| 121 | }; | 134 | }; |
| 122 | 135 | ||
| 123 | #define RAID_CTX_SPANARM_ARM_SHIFT (0) | 136 | #define RAID_CTX_SPANARM_ARM_SHIFT (0) |
| @@ -486,6 +499,7 @@ struct MPI2_IOC_INIT_REQUEST { | |||
| 486 | #define MAX_PHYSICAL_DEVICES 256 | 499 | #define MAX_PHYSICAL_DEVICES 256 |
| 487 | #define MAX_RAIDMAP_PHYSICAL_DEVICES (MAX_PHYSICAL_DEVICES) | 500 | #define MAX_RAIDMAP_PHYSICAL_DEVICES (MAX_PHYSICAL_DEVICES) |
| 488 | #define MR_DCMD_LD_MAP_GET_INFO 0x0300e101 | 501 | #define MR_DCMD_LD_MAP_GET_INFO 0x0300e101 |
| 502 | #define MR_DCMD_SYSTEM_PD_MAP_GET_INFO 0x0200e102 | ||
| 489 | #define MR_DCMD_CTRL_SHARED_HOST_MEM_ALLOC 0x010e8485 /* SR-IOV HB alloc*/ | 503 | #define MR_DCMD_CTRL_SHARED_HOST_MEM_ALLOC 0x010e8485 /* SR-IOV HB alloc*/ |
| 490 | #define MR_DCMD_LD_VF_MAP_GET_ALL_LDS_111 0x03200200 | 504 | #define MR_DCMD_LD_VF_MAP_GET_ALL_LDS_111 0x03200200 |
| 491 | #define MR_DCMD_LD_VF_MAP_GET_ALL_LDS 0x03150200 | 505 | #define MR_DCMD_LD_VF_MAP_GET_ALL_LDS 0x03150200 |
| @@ -789,6 +803,21 @@ struct MR_FW_RAID_MAP_EXT { | |||
| 789 | struct MR_LD_SPAN_MAP ldSpanMap[MAX_LOGICAL_DRIVES_EXT]; | 803 | struct MR_LD_SPAN_MAP ldSpanMap[MAX_LOGICAL_DRIVES_EXT]; |
| 790 | }; | 804 | }; |
| 791 | 805 | ||
| 806 | /* | ||
| 807 | * * define MR_PD_CFG_SEQ structure for system PDs | ||
| 808 | * */ | ||
| 809 | struct MR_PD_CFG_SEQ { | ||
| 810 | __le16 seqNum; | ||
| 811 | __le16 devHandle; | ||
| 812 | u8 reserved[4]; | ||
| 813 | } __packed; | ||
| 814 | |||
| 815 | struct MR_PD_CFG_SEQ_NUM_SYNC { | ||
| 816 | __le32 size; | ||
| 817 | __le32 count; | ||
| 818 | struct MR_PD_CFG_SEQ seq[1]; | ||
| 819 | } __packed; | ||
| 820 | |||
| 792 | struct fusion_context { | 821 | struct fusion_context { |
| 793 | struct megasas_cmd_fusion **cmd_list; | 822 | struct megasas_cmd_fusion **cmd_list; |
| 794 | dma_addr_t req_frames_desc_phys; | 823 | dma_addr_t req_frames_desc_phys; |
| @@ -828,9 +857,12 @@ struct fusion_context { | |||
| 828 | u32 current_map_sz; | 857 | u32 current_map_sz; |
| 829 | u32 drv_map_sz; | 858 | u32 drv_map_sz; |
| 830 | u32 drv_map_pages; | 859 | u32 drv_map_pages; |
| 860 | struct MR_PD_CFG_SEQ_NUM_SYNC *pd_seq_sync[JBOD_MAPS_COUNT]; | ||
| 861 | dma_addr_t pd_seq_phys[JBOD_MAPS_COUNT]; | ||
| 831 | u8 fast_path_io; | 862 | u8 fast_path_io; |
| 832 | struct LD_LOAD_BALANCE_INFO load_balance_info[MAX_LOGICAL_DRIVES_EXT]; | 863 | struct LD_LOAD_BALANCE_INFO load_balance_info[MAX_LOGICAL_DRIVES_EXT]; |
| 833 | LD_SPAN_INFO log_to_span[MAX_LOGICAL_DRIVES_EXT]; | 864 | LD_SPAN_INFO log_to_span[MAX_LOGICAL_DRIVES_EXT]; |
| 865 | u8 adapter_type; | ||
| 834 | }; | 866 | }; |
| 835 | 867 | ||
| 836 | union desc_value { | 868 | union desc_value { |
diff --git a/drivers/scsi/mpt2sas/Kconfig b/drivers/scsi/mpt2sas/Kconfig deleted file mode 100644 index 657b45ca04c5..000000000000 --- a/drivers/scsi/mpt2sas/Kconfig +++ /dev/null | |||
| @@ -1,67 +0,0 @@ | |||
| 1 | # | ||
| 2 | # Kernel configuration file for the MPT2SAS | ||
| 3 | # | ||
| 4 | # This code is based on drivers/scsi/mpt2sas/Kconfig | ||
| 5 | # Copyright (C) 2007-2014 LSI Corporation | ||
| 6 | # (mailto:DL-MPTFusionLinux@lsi.com) | ||
| 7 | |||
| 8 | # This program is free software; you can redistribute it and/or | ||
| 9 | # modify it under the terms of the GNU General Public License | ||
| 10 | # as published by the Free Software Foundation; either version 2 | ||
| 11 | # of the License, or (at your option) any later version. | ||
| 12 | |||
| 13 | # This program is distributed in the hope that it will be useful, | ||
| 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | # GNU General Public License for more details. | ||
| 17 | |||
| 18 | # NO WARRANTY | ||
| 19 | # THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR | ||
| 20 | # CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT | ||
| 21 | # LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, | ||
| 22 | # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is | ||
| 23 | # solely responsible for determining the appropriateness of using and | ||
| 24 | # distributing the Program and assumes all risks associated with its | ||
| 25 | # exercise of rights under this Agreement, including but not limited to | ||
| 26 | # the risks and costs of program errors, damage to or loss of data, | ||
| 27 | # programs or equipment, and unavailability or interruption of operations. | ||
| 28 | |||
| 29 | # DISCLAIMER OF LIABILITY | ||
| 30 | # NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY | ||
| 31 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 32 | # DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND | ||
| 33 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR | ||
| 34 | # TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | ||
| 35 | # USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED | ||
| 36 | # HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES | ||
| 37 | |||
| 38 | # You should have received a copy of the GNU General Public License | ||
| 39 | # along with this program; if not, write to the Free Software | ||
| 40 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
| 41 | # USA. | ||
| 42 | |||
| 43 | config SCSI_MPT2SAS | ||
| 44 | tristate "LSI MPT Fusion SAS 2.0 Device Driver" | ||
| 45 | depends on PCI && SCSI | ||
| 46 | select SCSI_SAS_ATTRS | ||
| 47 | select RAID_ATTRS | ||
| 48 | ---help--- | ||
| 49 | This driver supports PCI-Express SAS 6Gb/s Host Adapters. | ||
| 50 | |||
| 51 | config SCSI_MPT2SAS_MAX_SGE | ||
| 52 | int "LSI MPT Fusion Max number of SG Entries (16 - 128)" | ||
| 53 | depends on PCI && SCSI && SCSI_MPT2SAS | ||
| 54 | default "128" | ||
| 55 | range 16 128 | ||
| 56 | ---help--- | ||
| 57 | This option allows you to specify the maximum number of scatter- | ||
| 58 | gather entries per I/O. The driver default is 128, which matches | ||
| 59 | SAFE_PHYS_SEGMENTS. However, it may decreased down to 16. | ||
| 60 | Decreasing this parameter will reduce memory requirements | ||
| 61 | on a per controller instance. | ||
| 62 | |||
| 63 | config SCSI_MPT2SAS_LOGGING | ||
| 64 | bool "LSI MPT Fusion logging facility" | ||
| 65 | depends on PCI && SCSI && SCSI_MPT2SAS | ||
| 66 | ---help--- | ||
| 67 | This turns on a logging facility. | ||
diff --git a/drivers/scsi/mpt2sas/Makefile b/drivers/scsi/mpt2sas/Makefile deleted file mode 100644 index 728f0475711d..000000000000 --- a/drivers/scsi/mpt2sas/Makefile +++ /dev/null | |||
| @@ -1,7 +0,0 @@ | |||
| 1 | # mpt2sas makefile | ||
| 2 | obj-$(CONFIG_SCSI_MPT2SAS) += mpt2sas.o | ||
| 3 | mpt2sas-y += mpt2sas_base.o \ | ||
| 4 | mpt2sas_config.o \ | ||
| 5 | mpt2sas_scsih.o \ | ||
| 6 | mpt2sas_transport.o \ | ||
| 7 | mpt2sas_ctl.o | ||
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2.h b/drivers/scsi/mpt2sas/mpi/mpi2.h deleted file mode 100644 index 7fc6f23bd9dc..000000000000 --- a/drivers/scsi/mpt2sas/mpi/mpi2.h +++ /dev/null | |||
| @@ -1,1170 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2000-2014 LSI Corporation. | ||
| 3 | * | ||
| 4 | * | ||
| 5 | * Name: mpi2.h | ||
| 6 | * Title: MPI Message independent structures and definitions | ||
| 7 | * including System Interface Register Set and | ||
| 8 | * scatter/gather formats. | ||
| 9 | * Creation Date: June 21, 2006 | ||
| 10 | * | ||
| 11 | * mpi2.h Version: 02.00.35 | ||
| 12 | * | ||
| 13 | * Version History | ||
| 14 | * --------------- | ||
| 15 | * | ||
| 16 | * Date Version Description | ||
| 17 | * -------- -------- ------------------------------------------------------ | ||
| 18 | * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. | ||
| 19 | * 06-04-07 02.00.01 Bumped MPI2_HEADER_VERSION_UNIT. | ||
| 20 | * 06-26-07 02.00.02 Bumped MPI2_HEADER_VERSION_UNIT. | ||
| 21 | * 08-31-07 02.00.03 Bumped MPI2_HEADER_VERSION_UNIT. | ||
| 22 | * Moved ReplyPostHostIndex register to offset 0x6C of the | ||
| 23 | * MPI2_SYSTEM_INTERFACE_REGS and modified the define for | ||
| 24 | * MPI2_REPLY_POST_HOST_INDEX_OFFSET. | ||
| 25 | * Added union of request descriptors. | ||
| 26 | * Added union of reply descriptors. | ||
| 27 | * 10-31-07 02.00.04 Bumped MPI2_HEADER_VERSION_UNIT. | ||
| 28 | * Added define for MPI2_VERSION_02_00. | ||
| 29 | * Fixed the size of the FunctionDependent5 field in the | ||
| 30 | * MPI2_DEFAULT_REPLY structure. | ||
| 31 | * 12-18-07 02.00.05 Bumped MPI2_HEADER_VERSION_UNIT. | ||
| 32 | * Removed the MPI-defined Fault Codes and extended the | ||
| 33 | * product specific codes up to 0xEFFF. | ||
| 34 | * Added a sixth key value for the WriteSequence register | ||
| 35 | * and changed the flush value to 0x0. | ||
| 36 | * Added message function codes for Diagnostic Buffer Post | ||
| 37 | * and Diagnsotic Release. | ||
| 38 | * New IOCStatus define: MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED | ||
| 39 | * Moved MPI2_VERSION_UNION from mpi2_ioc.h. | ||
| 40 | * 02-29-08 02.00.06 Bumped MPI2_HEADER_VERSION_UNIT. | ||
| 41 | * 03-03-08 02.00.07 Bumped MPI2_HEADER_VERSION_UNIT. | ||
| 42 | * 05-21-08 02.00.08 Bumped MPI2_HEADER_VERSION_UNIT. | ||
| 43 | * Added #defines for marking a reply descriptor as unused. | ||
| 44 | * 06-27-08 02.00.09 Bumped MPI2_HEADER_VERSION_UNIT. | ||
| 45 | * 10-02-08 02.00.10 Bumped MPI2_HEADER_VERSION_UNIT. | ||
| 46 | * Moved LUN field defines from mpi2_init.h. | ||
| 47 | * 01-19-09 02.00.11 Bumped MPI2_HEADER_VERSION_UNIT. | ||
| 48 | * 05-06-09 02.00.12 Bumped MPI2_HEADER_VERSION_UNIT. | ||
| 49 | * In all request and reply descriptors, replaced VF_ID | ||
| 50 | * field with MSIxIndex field. | ||
| 51 | * Removed DevHandle field from | ||
| 52 | * MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR and made those | ||
| 53 | * bytes reserved. | ||
| 54 | * Added RAID Accelerator functionality. | ||
| 55 | * 07-30-09 02.00.13 Bumped MPI2_HEADER_VERSION_UNIT. | ||
| 56 | * 10-28-09 02.00.14 Bumped MPI2_HEADER_VERSION_UNIT. | ||
| 57 | * Added MSI-x index mask and shift for Reply Post Host | ||
| 58 | * Index register. | ||
| 59 | * Added function code for Host Based Discovery Action. | ||
| 60 | * 02-10-10 02.00.15 Bumped MPI2_HEADER_VERSION_UNIT. | ||
| 61 | * Added define for MPI2_FUNCTION_PWR_MGMT_CONTROL. | ||
| 62 | * Added defines for product-specific range of message | ||
| 63 | * function codes, 0xF0 to 0xFF. | ||
| 64 | * 05-12-10 02.00.16 Bumped MPI2_HEADER_VERSION_UNIT. | ||
| 65 | * Added alternative defines for the SGE Direction bit. | ||
| 66 | * 08-11-10 02.00.17 Bumped MPI2_HEADER_VERSION_UNIT. | ||
| 67 | * 11-10-10 02.00.18 Bumped MPI2_HEADER_VERSION_UNIT. | ||
| 68 | * Added MPI2_IEEE_SGE_FLAGS_SYSTEMPLBCPI_ADDR define. | ||
| 69 | * 02-23-11 02.00.19 Bumped MPI2_HEADER_VERSION_UNIT. | ||
| 70 | * Added MPI2_FUNCTION_SEND_HOST_MESSAGE. | ||
| 71 | * 03-09-11 02.00.20 Bumped MPI2_HEADER_VERSION_UNIT. | ||
| 72 | * 05-25-11 02.00.21 Bumped MPI2_HEADER_VERSION_UNIT. | ||
| 73 | * 08-24-11 02.00.22 Bumped MPI2_HEADER_VERSION_UNIT. | ||
| 74 | * 11-18-11 02.00.23 Bumped MPI2_HEADER_VERSION_UNIT. | ||
| 75 | * 02-06-12 02.00.24 Bumped MPI2_HEADER_VERSION_UNIT. | ||
| 76 | * 03-29-12 02.00.25 Bumped MPI2_HEADER_VERSION_UNIT. | ||
| 77 | * Added Hard Reset delay timings. | ||
| 78 | * 07-10-12 02.00.26 Bumped MPI2_HEADER_VERSION_UNIT. | ||
| 79 | * 07-26-12 02.00.27 Bumped MPI2_HEADER_VERSION_UNIT. | ||
| 80 | * 11-27-12 02.00.28 Bumped MPI2_HEADER_VERSION_UNIT. | ||
| 81 | * 12-20-12 02.00.29 Bumped MPI2_HEADER_VERSION_UNIT. | ||
| 82 | * Added MPI25_SUP_REPLY_POST_HOST_INDEX_OFFSET. | ||
| 83 | * 04-09-13 02.00.30 Bumped MPI2_HEADER_VERSION_UNIT. | ||
| 84 | * 04-17-13 02.00.31 Bumped MPI2_HEADER_VERSION_UNIT. | ||
| 85 | * 08-19-13 02.00.32 Bumped MPI2_HEADER_VERSION_UNIT. | ||
| 86 | * 12-05-13 02.00.33 Bumped MPI2_HEADER_VERSION_UNIT. | ||
| 87 | * 01-08-14 02.00.34 Bumped MPI2_HEADER_VERSION_UNIT. | ||
| 88 | * 06-13-14 02.00.35 Bumped MPI2_HEADER_VERSION_UNIT. | ||
| 89 | * -------------------------------------------------------------------------- | ||
| 90 | */ | ||
| 91 | |||
| 92 | #ifndef MPI2_H | ||
| 93 | #define MPI2_H | ||
| 94 | |||
| 95 | |||
| 96 | /***************************************************************************** | ||
| 97 | * | ||
| 98 | * MPI Version Definitions | ||
| 99 | * | ||
| 100 | *****************************************************************************/ | ||
| 101 | |||
| 102 | #define MPI2_VERSION_MAJOR (0x02) | ||
| 103 | #define MPI2_VERSION_MINOR (0x00) | ||
| 104 | #define MPI2_VERSION_MAJOR_MASK (0xFF00) | ||
| 105 | #define MPI2_VERSION_MAJOR_SHIFT (8) | ||
| 106 | #define MPI2_VERSION_MINOR_MASK (0x00FF) | ||
| 107 | #define MPI2_VERSION_MINOR_SHIFT (0) | ||
| 108 | #define MPI2_VERSION ((MPI2_VERSION_MAJOR << MPI2_VERSION_MAJOR_SHIFT) | \ | ||
| 109 | MPI2_VERSION_MINOR) | ||
| 110 | |||
| 111 | #define MPI2_VERSION_02_00 (0x0200) | ||
| 112 | |||
| 113 | /* versioning for this MPI header set */ | ||
| 114 | #define MPI2_HEADER_VERSION_UNIT (0x23) | ||
| 115 | #define MPI2_HEADER_VERSION_DEV (0x00) | ||
| 116 | #define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00) | ||
| 117 | #define MPI2_HEADER_VERSION_UNIT_SHIFT (8) | ||
| 118 | #define MPI2_HEADER_VERSION_DEV_MASK (0x00FF) | ||
| 119 | #define MPI2_HEADER_VERSION_DEV_SHIFT (0) | ||
| 120 | #define MPI2_HEADER_VERSION ((MPI2_HEADER_VERSION_UNIT << 8) | MPI2_HEADER_VERSION_DEV) | ||
| 121 | |||
| 122 | |||
| 123 | /***************************************************************************** | ||
| 124 | * | ||
| 125 | * IOC State Definitions | ||
| 126 | * | ||
| 127 | *****************************************************************************/ | ||
| 128 | |||
| 129 | #define MPI2_IOC_STATE_RESET (0x00000000) | ||
| 130 | #define MPI2_IOC_STATE_READY (0x10000000) | ||
| 131 | #define MPI2_IOC_STATE_OPERATIONAL (0x20000000) | ||
| 132 | #define MPI2_IOC_STATE_FAULT (0x40000000) | ||
| 133 | |||
| 134 | #define MPI2_IOC_STATE_MASK (0xF0000000) | ||
| 135 | #define MPI2_IOC_STATE_SHIFT (28) | ||
| 136 | |||
| 137 | /* Fault state range for prodcut specific codes */ | ||
| 138 | #define MPI2_FAULT_PRODUCT_SPECIFIC_MIN (0x0000) | ||
| 139 | #define MPI2_FAULT_PRODUCT_SPECIFIC_MAX (0xEFFF) | ||
| 140 | |||
| 141 | |||
| 142 | /***************************************************************************** | ||
| 143 | * | ||
| 144 | * System Interface Register Definitions | ||
| 145 | * | ||
| 146 | *****************************************************************************/ | ||
| 147 | |||
| 148 | typedef volatile struct _MPI2_SYSTEM_INTERFACE_REGS | ||
| 149 | { | ||
| 150 | U32 Doorbell; /* 0x00 */ | ||
| 151 | U32 WriteSequence; /* 0x04 */ | ||
| 152 | U32 HostDiagnostic; /* 0x08 */ | ||
| 153 | U32 Reserved1; /* 0x0C */ | ||
| 154 | U32 DiagRWData; /* 0x10 */ | ||
| 155 | U32 DiagRWAddressLow; /* 0x14 */ | ||
| 156 | U32 DiagRWAddressHigh; /* 0x18 */ | ||
| 157 | U32 Reserved2[5]; /* 0x1C */ | ||
| 158 | U32 HostInterruptStatus; /* 0x30 */ | ||
| 159 | U32 HostInterruptMask; /* 0x34 */ | ||
| 160 | U32 DCRData; /* 0x38 */ | ||
| 161 | U32 DCRAddress; /* 0x3C */ | ||
| 162 | U32 Reserved3[2]; /* 0x40 */ | ||
| 163 | U32 ReplyFreeHostIndex; /* 0x48 */ | ||
| 164 | U32 Reserved4[8]; /* 0x4C */ | ||
| 165 | U32 ReplyPostHostIndex; /* 0x6C */ | ||
| 166 | U32 Reserved5; /* 0x70 */ | ||
| 167 | U32 HCBSize; /* 0x74 */ | ||
| 168 | U32 HCBAddressLow; /* 0x78 */ | ||
| 169 | U32 HCBAddressHigh; /* 0x7C */ | ||
| 170 | U32 Reserved6[16]; /* 0x80 */ | ||
| 171 | U32 RequestDescriptorPostLow; /* 0xC0 */ | ||
| 172 | U32 RequestDescriptorPostHigh; /* 0xC4 */ | ||
| 173 | U32 Reserved7[14]; /* 0xC8 */ | ||
| 174 | } MPI2_SYSTEM_INTERFACE_REGS, MPI2_POINTER PTR_MPI2_SYSTEM_INTERFACE_REGS, | ||
| 175 | Mpi2SystemInterfaceRegs_t, MPI2_POINTER pMpi2SystemInterfaceRegs_t; | ||
| 176 | |||
| 177 | /* | ||
| 178 | * Defines for working with the Doorbell register. | ||
| 179 | */ | ||
| 180 | #define MPI2_DOORBELL_OFFSET (0x00000000) | ||
| 181 | |||
| 182 | /* IOC --> System values */ | ||
| 183 | #define MPI2_DOORBELL_USED (0x08000000) | ||
| 184 | #define MPI2_DOORBELL_WHO_INIT_MASK (0x07000000) | ||
| 185 | #define MPI2_DOORBELL_WHO_INIT_SHIFT (24) | ||
| 186 | #define MPI2_DOORBELL_FAULT_CODE_MASK (0x0000FFFF) | ||
| 187 | #define MPI2_DOORBELL_DATA_MASK (0x0000FFFF) | ||
| 188 | |||
| 189 | /* System --> IOC values */ | ||
| 190 | #define MPI2_DOORBELL_FUNCTION_MASK (0xFF000000) | ||
| 191 | #define MPI2_DOORBELL_FUNCTION_SHIFT (24) | ||
| 192 | #define MPI2_DOORBELL_ADD_DWORDS_MASK (0x00FF0000) | ||
| 193 | #define MPI2_DOORBELL_ADD_DWORDS_SHIFT (16) | ||
| 194 | |||
| 195 | |||
| 196 | /* | ||
| 197 | * Defines for the WriteSequence register | ||
| 198 | */ | ||
| 199 | #define MPI2_WRITE_SEQUENCE_OFFSET (0x00000004) | ||
| 200 | #define MPI2_WRSEQ_KEY_VALUE_MASK (0x0000000F) | ||
| 201 | #define MPI2_WRSEQ_FLUSH_KEY_VALUE (0x0) | ||
| 202 | #define MPI2_WRSEQ_1ST_KEY_VALUE (0xF) | ||
| 203 | #define MPI2_WRSEQ_2ND_KEY_VALUE (0x4) | ||
| 204 | #define MPI2_WRSEQ_3RD_KEY_VALUE (0xB) | ||
| 205 | #define MPI2_WRSEQ_4TH_KEY_VALUE (0x2) | ||
| 206 | #define MPI2_WRSEQ_5TH_KEY_VALUE (0x7) | ||
| 207 | #define MPI2_WRSEQ_6TH_KEY_VALUE (0xD) | ||
| 208 | |||
| 209 | /* | ||
| 210 | * Defines for the HostDiagnostic register | ||
| 211 | */ | ||
| 212 | #define MPI2_HOST_DIAGNOSTIC_OFFSET (0x00000008) | ||
| 213 | |||
| 214 | #define MPI2_DIAG_BOOT_DEVICE_SELECT_MASK (0x00001800) | ||
| 215 | #define MPI2_DIAG_BOOT_DEVICE_SELECT_DEFAULT (0x00000000) | ||
| 216 | #define MPI2_DIAG_BOOT_DEVICE_SELECT_HCDW (0x00000800) | ||
| 217 | |||
| 218 | #define MPI2_DIAG_CLEAR_FLASH_BAD_SIG (0x00000400) | ||
| 219 | #define MPI2_DIAG_FORCE_HCB_ON_RESET (0x00000200) | ||
| 220 | #define MPI2_DIAG_HCB_MODE (0x00000100) | ||
| 221 | #define MPI2_DIAG_DIAG_WRITE_ENABLE (0x00000080) | ||
| 222 | #define MPI2_DIAG_FLASH_BAD_SIG (0x00000040) | ||
| 223 | #define MPI2_DIAG_RESET_HISTORY (0x00000020) | ||
| 224 | #define MPI2_DIAG_DIAG_RW_ENABLE (0x00000010) | ||
| 225 | #define MPI2_DIAG_RESET_ADAPTER (0x00000004) | ||
| 226 | #define MPI2_DIAG_HOLD_IOC_RESET (0x00000002) | ||
| 227 | |||
| 228 | /* | ||
| 229 | * Offsets for DiagRWData and address | ||
| 230 | */ | ||
| 231 | #define MPI2_DIAG_RW_DATA_OFFSET (0x00000010) | ||
| 232 | #define MPI2_DIAG_RW_ADDRESS_LOW_OFFSET (0x00000014) | ||
| 233 | #define MPI2_DIAG_RW_ADDRESS_HIGH_OFFSET (0x00000018) | ||
| 234 | |||
| 235 | /* | ||
| 236 | * Defines for the HostInterruptStatus register | ||
| 237 | */ | ||
| 238 | #define MPI2_HOST_INTERRUPT_STATUS_OFFSET (0x00000030) | ||
| 239 | #define MPI2_HIS_SYS2IOC_DB_STATUS (0x80000000) | ||
| 240 | #define MPI2_HIS_IOP_DOORBELL_STATUS MPI2_HIS_SYS2IOC_DB_STATUS | ||
| 241 | #define MPI2_HIS_RESET_IRQ_STATUS (0x40000000) | ||
| 242 | #define MPI2_HIS_REPLY_DESCRIPTOR_INTERRUPT (0x00000008) | ||
| 243 | #define MPI2_HIS_IOC2SYS_DB_STATUS (0x00000001) | ||
| 244 | #define MPI2_HIS_DOORBELL_INTERRUPT MPI2_HIS_IOC2SYS_DB_STATUS | ||
| 245 | |||
| 246 | /* | ||
| 247 | * Defines for the HostInterruptMask register | ||
| 248 | */ | ||
| 249 | #define MPI2_HOST_INTERRUPT_MASK_OFFSET (0x00000034) | ||
| 250 | #define MPI2_HIM_RESET_IRQ_MASK (0x40000000) | ||
| 251 | #define MPI2_HIM_REPLY_INT_MASK (0x00000008) | ||
| 252 | #define MPI2_HIM_RIM MPI2_HIM_REPLY_INT_MASK | ||
| 253 | #define MPI2_HIM_IOC2SYS_DB_MASK (0x00000001) | ||
| 254 | #define MPI2_HIM_DIM MPI2_HIM_IOC2SYS_DB_MASK | ||
| 255 | |||
| 256 | /* | ||
| 257 | * Offsets for DCRData and address | ||
| 258 | */ | ||
| 259 | #define MPI2_DCR_DATA_OFFSET (0x00000038) | ||
| 260 | #define MPI2_DCR_ADDRESS_OFFSET (0x0000003C) | ||
| 261 | |||
| 262 | /* | ||
| 263 | * Offset for the Reply Free Queue | ||
| 264 | */ | ||
| 265 | #define MPI2_REPLY_FREE_HOST_INDEX_OFFSET (0x00000048) | ||
| 266 | |||
| 267 | /* | ||
| 268 | * Defines for the Reply Descriptor Post Queue | ||
| 269 | */ | ||
| 270 | #define MPI2_REPLY_POST_HOST_INDEX_OFFSET (0x0000006C) | ||
| 271 | #define MPI2_REPLY_POST_HOST_INDEX_MASK (0x00FFFFFF) | ||
| 272 | #define MPI2_RPHI_MSIX_INDEX_MASK (0xFF000000) | ||
| 273 | #define MPI2_RPHI_MSIX_INDEX_SHIFT (24) | ||
| 274 | #define MPI25_SUP_REPLY_POST_HOST_INDEX_OFFSET (0x0000030C) /* MPI v2.5 only */ | ||
| 275 | |||
| 276 | /* | ||
| 277 | * Defines for the HCBSize and address | ||
| 278 | */ | ||
| 279 | #define MPI2_HCB_SIZE_OFFSET (0x00000074) | ||
| 280 | #define MPI2_HCB_SIZE_SIZE_MASK (0xFFFFF000) | ||
| 281 | #define MPI2_HCB_SIZE_HCB_ENABLE (0x00000001) | ||
| 282 | |||
| 283 | #define MPI2_HCB_ADDRESS_LOW_OFFSET (0x00000078) | ||
| 284 | #define MPI2_HCB_ADDRESS_HIGH_OFFSET (0x0000007C) | ||
| 285 | |||
| 286 | /* | ||
| 287 | * Offsets for the Request Queue | ||
| 288 | */ | ||
| 289 | #define MPI2_REQUEST_DESCRIPTOR_POST_LOW_OFFSET (0x000000C0) | ||
| 290 | #define MPI2_REQUEST_DESCRIPTOR_POST_HIGH_OFFSET (0x000000C4) | ||
| 291 | |||
| 292 | |||
| 293 | /* Hard Reset delay timings */ | ||
| 294 | #define MPI2_HARD_RESET_PCIE_FIRST_READ_DELAY_MICRO_SEC (50000) | ||
| 295 | #define MPI2_HARD_RESET_PCIE_RESET_READ_WINDOW_MICRO_SEC (255000) | ||
| 296 | #define MPI2_HARD_RESET_PCIE_SECOND_READ_DELAY_MICRO_SEC (256000) | ||
| 297 | |||
| 298 | /***************************************************************************** | ||
| 299 | * | ||
| 300 | * Message Descriptors | ||
| 301 | * | ||
| 302 | *****************************************************************************/ | ||
| 303 | |||
| 304 | /* Request Descriptors */ | ||
| 305 | |||
| 306 | /* Default Request Descriptor */ | ||
| 307 | typedef struct _MPI2_DEFAULT_REQUEST_DESCRIPTOR | ||
| 308 | { | ||
| 309 | U8 RequestFlags; /* 0x00 */ | ||
| 310 | U8 MSIxIndex; /* 0x01 */ | ||
| 311 | U16 SMID; /* 0x02 */ | ||
| 312 | U16 LMID; /* 0x04 */ | ||
| 313 | U16 DescriptorTypeDependent; /* 0x06 */ | ||
| 314 | } MPI2_DEFAULT_REQUEST_DESCRIPTOR, | ||
| 315 | MPI2_POINTER PTR_MPI2_DEFAULT_REQUEST_DESCRIPTOR, | ||
| 316 | Mpi2DefaultRequestDescriptor_t, MPI2_POINTER pMpi2DefaultRequestDescriptor_t; | ||
| 317 | |||
| 318 | /* defines for the RequestFlags field */ | ||
| 319 | #define MPI2_REQ_DESCRIPT_FLAGS_TYPE_MASK (0x0E) | ||
| 320 | #define MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO (0x00) | ||
| 321 | #define MPI2_REQ_DESCRIPT_FLAGS_SCSI_TARGET (0x02) | ||
| 322 | #define MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY (0x06) | ||
| 323 | #define MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE (0x08) | ||
| 324 | #define MPI2_REQ_DESCRIPT_FLAGS_RAID_ACCELERATOR (0x0A) | ||
| 325 | |||
| 326 | #define MPI2_REQ_DESCRIPT_FLAGS_IOC_FIFO_MARKER (0x01) | ||
| 327 | |||
| 328 | |||
| 329 | /* High Priority Request Descriptor */ | ||
| 330 | typedef struct _MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR | ||
| 331 | { | ||
| 332 | U8 RequestFlags; /* 0x00 */ | ||
| 333 | U8 MSIxIndex; /* 0x01 */ | ||
| 334 | U16 SMID; /* 0x02 */ | ||
| 335 | U16 LMID; /* 0x04 */ | ||
| 336 | U16 Reserved1; /* 0x06 */ | ||
| 337 | } MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR, | ||
| 338 | MPI2_POINTER PTR_MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR, | ||
| 339 | Mpi2HighPriorityRequestDescriptor_t, | ||
| 340 | MPI2_POINTER pMpi2HighPriorityRequestDescriptor_t; | ||
| 341 | |||
| 342 | |||
| 343 | /* SCSI IO Request Descriptor */ | ||
| 344 | typedef struct _MPI2_SCSI_IO_REQUEST_DESCRIPTOR | ||
| 345 | { | ||
| 346 | U8 RequestFlags; /* 0x00 */ | ||
| 347 | U8 MSIxIndex; /* 0x01 */ | ||
| 348 | U16 SMID; /* 0x02 */ | ||
| 349 | U16 LMID; /* 0x04 */ | ||
| 350 | U16 DevHandle; /* 0x06 */ | ||
| 351 | } MPI2_SCSI_IO_REQUEST_DESCRIPTOR, | ||
| 352 | MPI2_POINTER PTR_MPI2_SCSI_IO_REQUEST_DESCRIPTOR, | ||
| 353 | Mpi2SCSIIORequestDescriptor_t, MPI2_POINTER pMpi2SCSIIORequestDescriptor_t; | ||
| 354 | |||
| 355 | |||
| 356 | /* SCSI Target Request Descriptor */ | ||
| 357 | typedef struct _MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR | ||
| 358 | { | ||
| 359 | U8 RequestFlags; /* 0x00 */ | ||
| 360 | U8 MSIxIndex; /* 0x01 */ | ||
| 361 | U16 SMID; /* 0x02 */ | ||
| 362 | U16 LMID; /* 0x04 */ | ||
| 363 | U16 IoIndex; /* 0x06 */ | ||
| 364 | } MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR, | ||
| 365 | MPI2_POINTER PTR_MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR, | ||
| 366 | Mpi2SCSITargetRequestDescriptor_t, | ||
| 367 | MPI2_POINTER pMpi2SCSITargetRequestDescriptor_t; | ||
| 368 | |||
| 369 | |||
| 370 | /* RAID Accelerator Request Descriptor */ | ||
| 371 | typedef struct _MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR { | ||
| 372 | U8 RequestFlags; /* 0x00 */ | ||
| 373 | U8 MSIxIndex; /* 0x01 */ | ||
| 374 | U16 SMID; /* 0x02 */ | ||
| 375 | U16 LMID; /* 0x04 */ | ||
| 376 | U16 Reserved; /* 0x06 */ | ||
| 377 | } MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR, | ||
| 378 | MPI2_POINTER PTR_MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR, | ||
| 379 | Mpi2RAIDAcceleratorRequestDescriptor_t, | ||
| 380 | MPI2_POINTER pMpi2RAIDAcceleratorRequestDescriptor_t; | ||
| 381 | |||
| 382 | |||
| 383 | /* union of Request Descriptors */ | ||
| 384 | typedef union _MPI2_REQUEST_DESCRIPTOR_UNION | ||
| 385 | { | ||
| 386 | MPI2_DEFAULT_REQUEST_DESCRIPTOR Default; | ||
| 387 | MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR HighPriority; | ||
| 388 | MPI2_SCSI_IO_REQUEST_DESCRIPTOR SCSIIO; | ||
| 389 | MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR SCSITarget; | ||
| 390 | MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR RAIDAccelerator; | ||
| 391 | U64 Words; | ||
| 392 | } MPI2_REQUEST_DESCRIPTOR_UNION, MPI2_POINTER PTR_MPI2_REQUEST_DESCRIPTOR_UNION, | ||
| 393 | Mpi2RequestDescriptorUnion_t, MPI2_POINTER pMpi2RequestDescriptorUnion_t; | ||
| 394 | |||
| 395 | |||
| 396 | /* Reply Descriptors */ | ||
| 397 | |||
| 398 | /* Default Reply Descriptor */ | ||
| 399 | typedef struct _MPI2_DEFAULT_REPLY_DESCRIPTOR | ||
| 400 | { | ||
| 401 | U8 ReplyFlags; /* 0x00 */ | ||
| 402 | U8 MSIxIndex; /* 0x01 */ | ||
| 403 | U16 DescriptorTypeDependent1; /* 0x02 */ | ||
| 404 | U32 DescriptorTypeDependent2; /* 0x04 */ | ||
| 405 | } MPI2_DEFAULT_REPLY_DESCRIPTOR, MPI2_POINTER PTR_MPI2_DEFAULT_REPLY_DESCRIPTOR, | ||
| 406 | Mpi2DefaultReplyDescriptor_t, MPI2_POINTER pMpi2DefaultReplyDescriptor_t; | ||
| 407 | |||
| 408 | /* defines for the ReplyFlags field */ | ||
| 409 | #define MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK (0x0F) | ||
| 410 | #define MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS (0x00) | ||
| 411 | #define MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY (0x01) | ||
| 412 | #define MPI2_RPY_DESCRIPT_FLAGS_TARGETASSIST_SUCCESS (0x02) | ||
| 413 | #define MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER (0x03) | ||
| 414 | #define MPI2_RPY_DESCRIPT_FLAGS_RAID_ACCELERATOR_SUCCESS (0x05) | ||
| 415 | #define MPI2_RPY_DESCRIPT_FLAGS_UNUSED (0x0F) | ||
| 416 | |||
| 417 | /* values for marking a reply descriptor as unused */ | ||
| 418 | #define MPI2_RPY_DESCRIPT_UNUSED_WORD0_MARK (0xFFFFFFFF) | ||
| 419 | #define MPI2_RPY_DESCRIPT_UNUSED_WORD1_MARK (0xFFFFFFFF) | ||
| 420 | |||
| 421 | /* Address Reply Descriptor */ | ||
| 422 | typedef struct _MPI2_ADDRESS_REPLY_DESCRIPTOR | ||
| 423 | { | ||
| 424 | U8 ReplyFlags; /* 0x00 */ | ||
| 425 | U8 MSIxIndex; /* 0x01 */ | ||
| 426 | U16 SMID; /* 0x02 */ | ||
| 427 | U32 ReplyFrameAddress; /* 0x04 */ | ||
| 428 | } MPI2_ADDRESS_REPLY_DESCRIPTOR, MPI2_POINTER PTR_MPI2_ADDRESS_REPLY_DESCRIPTOR, | ||
| 429 | Mpi2AddressReplyDescriptor_t, MPI2_POINTER pMpi2AddressReplyDescriptor_t; | ||
| 430 | |||
| 431 | #define MPI2_ADDRESS_REPLY_SMID_INVALID (0x00) | ||
| 432 | |||
| 433 | |||
| 434 | /* SCSI IO Success Reply Descriptor */ | ||
| 435 | typedef struct _MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR | ||
| 436 | { | ||
| 437 | U8 ReplyFlags; /* 0x00 */ | ||
| 438 | U8 MSIxIndex; /* 0x01 */ | ||
| 439 | U16 SMID; /* 0x02 */ | ||
| 440 | U16 TaskTag; /* 0x04 */ | ||
| 441 | U16 Reserved1; /* 0x06 */ | ||
| 442 | } MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR, | ||
| 443 | MPI2_POINTER PTR_MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR, | ||
| 444 | Mpi2SCSIIOSuccessReplyDescriptor_t, | ||
| 445 | MPI2_POINTER pMpi2SCSIIOSuccessReplyDescriptor_t; | ||
| 446 | |||
| 447 | |||
| 448 | /* TargetAssist Success Reply Descriptor */ | ||
| 449 | typedef struct _MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR | ||
| 450 | { | ||
| 451 | U8 ReplyFlags; /* 0x00 */ | ||
| 452 | U8 MSIxIndex; /* 0x01 */ | ||
| 453 | U16 SMID; /* 0x02 */ | ||
| 454 | U8 SequenceNumber; /* 0x04 */ | ||
| 455 | U8 Reserved1; /* 0x05 */ | ||
| 456 | U16 IoIndex; /* 0x06 */ | ||
| 457 | } MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR, | ||
| 458 | MPI2_POINTER PTR_MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR, | ||
| 459 | Mpi2TargetAssistSuccessReplyDescriptor_t, | ||
| 460 | MPI2_POINTER pMpi2TargetAssistSuccessReplyDescriptor_t; | ||
| 461 | |||
| 462 | |||
| 463 | /* Target Command Buffer Reply Descriptor */ | ||
| 464 | typedef struct _MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR | ||
| 465 | { | ||
| 466 | U8 ReplyFlags; /* 0x00 */ | ||
| 467 | U8 MSIxIndex; /* 0x01 */ | ||
| 468 | U8 VP_ID; /* 0x02 */ | ||
| 469 | U8 Flags; /* 0x03 */ | ||
| 470 | U16 InitiatorDevHandle; /* 0x04 */ | ||
| 471 | U16 IoIndex; /* 0x06 */ | ||
| 472 | } MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR, | ||
| 473 | MPI2_POINTER PTR_MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR, | ||
| 474 | Mpi2TargetCommandBufferReplyDescriptor_t, | ||
| 475 | MPI2_POINTER pMpi2TargetCommandBufferReplyDescriptor_t; | ||
| 476 | |||
| 477 | /* defines for Flags field */ | ||
| 478 | #define MPI2_RPY_DESCRIPT_TCB_FLAGS_PHYNUM_MASK (0x3F) | ||
| 479 | |||
| 480 | |||
| 481 | /* RAID Accelerator Success Reply Descriptor */ | ||
| 482 | typedef struct _MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR { | ||
| 483 | U8 ReplyFlags; /* 0x00 */ | ||
| 484 | U8 MSIxIndex; /* 0x01 */ | ||
| 485 | U16 SMID; /* 0x02 */ | ||
| 486 | U32 Reserved; /* 0x04 */ | ||
| 487 | } MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR, | ||
| 488 | MPI2_POINTER PTR_MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR, | ||
| 489 | Mpi2RAIDAcceleratorSuccessReplyDescriptor_t, | ||
| 490 | MPI2_POINTER pMpi2RAIDAcceleratorSuccessReplyDescriptor_t; | ||
| 491 | |||
| 492 | |||
| 493 | /* union of Reply Descriptors */ | ||
| 494 | typedef union _MPI2_REPLY_DESCRIPTORS_UNION | ||
| 495 | { | ||
| 496 | MPI2_DEFAULT_REPLY_DESCRIPTOR Default; | ||
| 497 | MPI2_ADDRESS_REPLY_DESCRIPTOR AddressReply; | ||
| 498 | MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR SCSIIOSuccess; | ||
| 499 | MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR TargetAssistSuccess; | ||
| 500 | MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR TargetCommandBuffer; | ||
| 501 | MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR RAIDAcceleratorSuccess; | ||
| 502 | U64 Words; | ||
| 503 | } MPI2_REPLY_DESCRIPTORS_UNION, MPI2_POINTER PTR_MPI2_REPLY_DESCRIPTORS_UNION, | ||
| 504 | Mpi2ReplyDescriptorsUnion_t, MPI2_POINTER pMpi2ReplyDescriptorsUnion_t; | ||
| 505 | |||
| 506 | |||
| 507 | |||
| 508 | /***************************************************************************** | ||
| 509 | * | ||
| 510 | * Message Functions | ||
| 511 | * | ||
| 512 | *****************************************************************************/ | ||
| 513 | |||
| 514 | #define MPI2_FUNCTION_SCSI_IO_REQUEST (0x00) /* SCSI IO */ | ||
| 515 | #define MPI2_FUNCTION_SCSI_TASK_MGMT (0x01) /* SCSI Task Management */ | ||
| 516 | #define MPI2_FUNCTION_IOC_INIT (0x02) /* IOC Init */ | ||
| 517 | #define MPI2_FUNCTION_IOC_FACTS (0x03) /* IOC Facts */ | ||
| 518 | #define MPI2_FUNCTION_CONFIG (0x04) /* Configuration */ | ||
| 519 | #define MPI2_FUNCTION_PORT_FACTS (0x05) /* Port Facts */ | ||
| 520 | #define MPI2_FUNCTION_PORT_ENABLE (0x06) /* Port Enable */ | ||
| 521 | #define MPI2_FUNCTION_EVENT_NOTIFICATION (0x07) /* Event Notification */ | ||
| 522 | #define MPI2_FUNCTION_EVENT_ACK (0x08) /* Event Acknowledge */ | ||
| 523 | #define MPI2_FUNCTION_FW_DOWNLOAD (0x09) /* FW Download */ | ||
| 524 | #define MPI2_FUNCTION_TARGET_ASSIST (0x0B) /* Target Assist */ | ||
| 525 | #define MPI2_FUNCTION_TARGET_STATUS_SEND (0x0C) /* Target Status Send */ | ||
| 526 | #define MPI2_FUNCTION_TARGET_MODE_ABORT (0x0D) /* Target Mode Abort */ | ||
| 527 | #define MPI2_FUNCTION_FW_UPLOAD (0x12) /* FW Upload */ | ||
| 528 | #define MPI2_FUNCTION_RAID_ACTION (0x15) /* RAID Action */ | ||
| 529 | #define MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH (0x16) /* SCSI IO RAID Passthrough */ | ||
| 530 | #define MPI2_FUNCTION_TOOLBOX (0x17) /* Toolbox */ | ||
| 531 | #define MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR (0x18) /* SCSI Enclosure Processor */ | ||
| 532 | #define MPI2_FUNCTION_SMP_PASSTHROUGH (0x1A) /* SMP Passthrough */ | ||
| 533 | #define MPI2_FUNCTION_SAS_IO_UNIT_CONTROL (0x1B) /* SAS IO Unit Control */ | ||
| 534 | #define MPI2_FUNCTION_SATA_PASSTHROUGH (0x1C) /* SATA Passthrough */ | ||
| 535 | #define MPI2_FUNCTION_DIAG_BUFFER_POST (0x1D) /* Diagnostic Buffer Post */ | ||
| 536 | #define MPI2_FUNCTION_DIAG_RELEASE (0x1E) /* Diagnostic Release */ | ||
| 537 | #define MPI2_FUNCTION_TARGET_CMD_BUF_BASE_POST (0x24) /* Target Command Buffer Post Base */ | ||
| 538 | #define MPI2_FUNCTION_TARGET_CMD_BUF_LIST_POST (0x25) /* Target Command Buffer Post List */ | ||
| 539 | #define MPI2_FUNCTION_RAID_ACCELERATOR (0x2C) /* RAID Accelerator*/ | ||
| 540 | /* Host Based Discovery Action */ | ||
| 541 | #define MPI2_FUNCTION_HOST_BASED_DISCOVERY_ACTION (0x2F) | ||
| 542 | /* Power Management Control */ | ||
| 543 | #define MPI2_FUNCTION_PWR_MGMT_CONTROL (0x30) | ||
| 544 | /* Send Host Message */ | ||
| 545 | #define MPI2_FUNCTION_SEND_HOST_MESSAGE (0x31) | ||
| 546 | /* beginning of product-specific range */ | ||
| 547 | #define MPI2_FUNCTION_MIN_PRODUCT_SPECIFIC (0xF0) | ||
| 548 | /* end of product-specific range */ | ||
| 549 | #define MPI2_FUNCTION_MAX_PRODUCT_SPECIFIC (0xFF) | ||
| 550 | |||
| 551 | |||
| 552 | |||
| 553 | |||
| 554 | /* Doorbell functions */ | ||
| 555 | #define MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET (0x40) | ||
| 556 | #define MPI2_FUNCTION_HANDSHAKE (0x42) | ||
| 557 | |||
| 558 | |||
| 559 | /***************************************************************************** | ||
| 560 | * | ||
| 561 | * IOC Status Values | ||
| 562 | * | ||
| 563 | *****************************************************************************/ | ||
| 564 | |||
| 565 | /* mask for IOCStatus status value */ | ||
| 566 | #define MPI2_IOCSTATUS_MASK (0x7FFF) | ||
| 567 | |||
| 568 | /**************************************************************************** | ||
| 569 | * Common IOCStatus values for all replies | ||
| 570 | ****************************************************************************/ | ||
| 571 | |||
| 572 | #define MPI2_IOCSTATUS_SUCCESS (0x0000) | ||
| 573 | #define MPI2_IOCSTATUS_INVALID_FUNCTION (0x0001) | ||
| 574 | #define MPI2_IOCSTATUS_BUSY (0x0002) | ||
| 575 | #define MPI2_IOCSTATUS_INVALID_SGL (0x0003) | ||
| 576 | #define MPI2_IOCSTATUS_INTERNAL_ERROR (0x0004) | ||
| 577 | #define MPI2_IOCSTATUS_INVALID_VPID (0x0005) | ||
| 578 | #define MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES (0x0006) | ||
| 579 | #define MPI2_IOCSTATUS_INVALID_FIELD (0x0007) | ||
| 580 | #define MPI2_IOCSTATUS_INVALID_STATE (0x0008) | ||
| 581 | #define MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED (0x0009) | ||
| 582 | |||
| 583 | /**************************************************************************** | ||
| 584 | * Config IOCStatus values | ||
| 585 | ****************************************************************************/ | ||
| 586 | |||
| 587 | #define MPI2_IOCSTATUS_CONFIG_INVALID_ACTION (0x0020) | ||
| 588 | #define MPI2_IOCSTATUS_CONFIG_INVALID_TYPE (0x0021) | ||
| 589 | #define MPI2_IOCSTATUS_CONFIG_INVALID_PAGE (0x0022) | ||
| 590 | #define MPI2_IOCSTATUS_CONFIG_INVALID_DATA (0x0023) | ||
| 591 | #define MPI2_IOCSTATUS_CONFIG_NO_DEFAULTS (0x0024) | ||
| 592 | #define MPI2_IOCSTATUS_CONFIG_CANT_COMMIT (0x0025) | ||
| 593 | |||
| 594 | /**************************************************************************** | ||
| 595 | * SCSI IO Reply | ||
| 596 | ****************************************************************************/ | ||
| 597 | |||
| 598 | #define MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR (0x0040) | ||
| 599 | #define MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE (0x0042) | ||
| 600 | #define MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE (0x0043) | ||
| 601 | #define MPI2_IOCSTATUS_SCSI_DATA_OVERRUN (0x0044) | ||
| 602 | #define MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN (0x0045) | ||
| 603 | #define MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR (0x0046) | ||
| 604 | #define MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR (0x0047) | ||
| 605 | #define MPI2_IOCSTATUS_SCSI_TASK_TERMINATED (0x0048) | ||
| 606 | #define MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH (0x0049) | ||
| 607 | #define MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED (0x004A) | ||
| 608 | #define MPI2_IOCSTATUS_SCSI_IOC_TERMINATED (0x004B) | ||
| 609 | #define MPI2_IOCSTATUS_SCSI_EXT_TERMINATED (0x004C) | ||
| 610 | |||
| 611 | /**************************************************************************** | ||
| 612 | * For use by SCSI Initiator and SCSI Target end-to-end data protection | ||
| 613 | ****************************************************************************/ | ||
| 614 | |||
| 615 | #define MPI2_IOCSTATUS_EEDP_GUARD_ERROR (0x004D) | ||
| 616 | #define MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR (0x004E) | ||
| 617 | #define MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR (0x004F) | ||
| 618 | |||
| 619 | /**************************************************************************** | ||
| 620 | * SCSI Target values | ||
| 621 | ****************************************************************************/ | ||
| 622 | |||
| 623 | #define MPI2_IOCSTATUS_TARGET_INVALID_IO_INDEX (0x0062) | ||
| 624 | #define MPI2_IOCSTATUS_TARGET_ABORTED (0x0063) | ||
| 625 | #define MPI2_IOCSTATUS_TARGET_NO_CONN_RETRYABLE (0x0064) | ||
| 626 | #define MPI2_IOCSTATUS_TARGET_NO_CONNECTION (0x0065) | ||
| 627 | #define MPI2_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH (0x006A) | ||
| 628 | #define MPI2_IOCSTATUS_TARGET_DATA_OFFSET_ERROR (0x006D) | ||
| 629 | #define MPI2_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA (0x006E) | ||
| 630 | #define MPI2_IOCSTATUS_TARGET_IU_TOO_SHORT (0x006F) | ||
| 631 | #define MPI2_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT (0x0070) | ||
| 632 | #define MPI2_IOCSTATUS_TARGET_NAK_RECEIVED (0x0071) | ||
| 633 | |||
| 634 | /**************************************************************************** | ||
| 635 | * Serial Attached SCSI values | ||
| 636 | ****************************************************************************/ | ||
| 637 | |||
| 638 | #define MPI2_IOCSTATUS_SAS_SMP_REQUEST_FAILED (0x0090) | ||
| 639 | #define MPI2_IOCSTATUS_SAS_SMP_DATA_OVERRUN (0x0091) | ||
| 640 | |||
| 641 | /**************************************************************************** | ||
| 642 | * Diagnostic Buffer Post / Diagnostic Release values | ||
| 643 | ****************************************************************************/ | ||
| 644 | |||
| 645 | #define MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED (0x00A0) | ||
| 646 | |||
| 647 | /**************************************************************************** | ||
| 648 | * RAID Accelerator values | ||
| 649 | ****************************************************************************/ | ||
| 650 | |||
| 651 | #define MPI2_IOCSTATUS_RAID_ACCEL_ERROR (0x00B0) | ||
| 652 | |||
| 653 | /**************************************************************************** | ||
| 654 | * IOCStatus flag to indicate that log info is available | ||
| 655 | ****************************************************************************/ | ||
| 656 | |||
| 657 | #define MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE (0x8000) | ||
| 658 | |||
| 659 | /**************************************************************************** | ||
| 660 | * IOCLogInfo Types | ||
| 661 | ****************************************************************************/ | ||
| 662 | |||
| 663 | #define MPI2_IOCLOGINFO_TYPE_MASK (0xF0000000) | ||
| 664 | #define MPI2_IOCLOGINFO_TYPE_SHIFT (28) | ||
| 665 | #define MPI2_IOCLOGINFO_TYPE_NONE (0x0) | ||
| 666 | #define MPI2_IOCLOGINFO_TYPE_SCSI (0x1) | ||
| 667 | #define MPI2_IOCLOGINFO_TYPE_FC (0x2) | ||
| 668 | #define MPI2_IOCLOGINFO_TYPE_SAS (0x3) | ||
| 669 | #define MPI2_IOCLOGINFO_TYPE_ISCSI (0x4) | ||
| 670 | #define MPI2_IOCLOGINFO_LOG_DATA_MASK (0x0FFFFFFF) | ||
| 671 | |||
| 672 | |||
| 673 | /***************************************************************************** | ||
| 674 | * | ||
| 675 | * Standard Message Structures | ||
| 676 | * | ||
| 677 | *****************************************************************************/ | ||
| 678 | |||
| 679 | /**************************************************************************** | ||
| 680 | * Request Message Header for all request messages | ||
| 681 | ****************************************************************************/ | ||
| 682 | |||
| 683 | typedef struct _MPI2_REQUEST_HEADER | ||
| 684 | { | ||
| 685 | U16 FunctionDependent1; /* 0x00 */ | ||
| 686 | U8 ChainOffset; /* 0x02 */ | ||
| 687 | U8 Function; /* 0x03 */ | ||
| 688 | U16 FunctionDependent2; /* 0x04 */ | ||
| 689 | U8 FunctionDependent3; /* 0x06 */ | ||
| 690 | U8 MsgFlags; /* 0x07 */ | ||
| 691 | U8 VP_ID; /* 0x08 */ | ||
| 692 | U8 VF_ID; /* 0x09 */ | ||
| 693 | U16 Reserved1; /* 0x0A */ | ||
| 694 | } MPI2_REQUEST_HEADER, MPI2_POINTER PTR_MPI2_REQUEST_HEADER, | ||
| 695 | MPI2RequestHeader_t, MPI2_POINTER pMPI2RequestHeader_t; | ||
| 696 | |||
| 697 | |||
| 698 | /**************************************************************************** | ||
| 699 | * Default Reply | ||
| 700 | ****************************************************************************/ | ||
| 701 | |||
| 702 | typedef struct _MPI2_DEFAULT_REPLY | ||
| 703 | { | ||
| 704 | U16 FunctionDependent1; /* 0x00 */ | ||
| 705 | U8 MsgLength; /* 0x02 */ | ||
| 706 | U8 Function; /* 0x03 */ | ||
| 707 | U16 FunctionDependent2; /* 0x04 */ | ||
| 708 | U8 FunctionDependent3; /* 0x06 */ | ||
| 709 | U8 MsgFlags; /* 0x07 */ | ||
| 710 | U8 VP_ID; /* 0x08 */ | ||
| 711 | U8 VF_ID; /* 0x09 */ | ||
| 712 | U16 Reserved1; /* 0x0A */ | ||
| 713 | U16 FunctionDependent5; /* 0x0C */ | ||
| 714 | U16 IOCStatus; /* 0x0E */ | ||
| 715 | U32 IOCLogInfo; /* 0x10 */ | ||
| 716 | } MPI2_DEFAULT_REPLY, MPI2_POINTER PTR_MPI2_DEFAULT_REPLY, | ||
| 717 | MPI2DefaultReply_t, MPI2_POINTER pMPI2DefaultReply_t; | ||
| 718 | |||
| 719 | |||
| 720 | /* common version structure/union used in messages and configuration pages */ | ||
| 721 | |||
| 722 | typedef struct _MPI2_VERSION_STRUCT | ||
| 723 | { | ||
| 724 | U8 Dev; /* 0x00 */ | ||
| 725 | U8 Unit; /* 0x01 */ | ||
| 726 | U8 Minor; /* 0x02 */ | ||
| 727 | U8 Major; /* 0x03 */ | ||
| 728 | } MPI2_VERSION_STRUCT; | ||
| 729 | |||
| 730 | typedef union _MPI2_VERSION_UNION | ||
| 731 | { | ||
| 732 | MPI2_VERSION_STRUCT Struct; | ||
| 733 | U32 Word; | ||
| 734 | } MPI2_VERSION_UNION; | ||
| 735 | |||
| 736 | |||
| 737 | /* LUN field defines, common to many structures */ | ||
| 738 | #define MPI2_LUN_FIRST_LEVEL_ADDRESSING (0x0000FFFF) | ||
| 739 | #define MPI2_LUN_SECOND_LEVEL_ADDRESSING (0xFFFF0000) | ||
| 740 | #define MPI2_LUN_THIRD_LEVEL_ADDRESSING (0x0000FFFF) | ||
| 741 | #define MPI2_LUN_FOURTH_LEVEL_ADDRESSING (0xFFFF0000) | ||
| 742 | #define MPI2_LUN_LEVEL_1_WORD (0xFF00) | ||
| 743 | #define MPI2_LUN_LEVEL_1_DWORD (0x0000FF00) | ||
| 744 | |||
| 745 | |||
| 746 | /***************************************************************************** | ||
| 747 | * | ||
| 748 | * Fusion-MPT MPI Scatter Gather Elements | ||
| 749 | * | ||
| 750 | *****************************************************************************/ | ||
| 751 | |||
| 752 | /**************************************************************************** | ||
| 753 | * MPI Simple Element structures | ||
| 754 | ****************************************************************************/ | ||
| 755 | |||
| 756 | typedef struct _MPI2_SGE_SIMPLE32 | ||
| 757 | { | ||
| 758 | U32 FlagsLength; | ||
| 759 | U32 Address; | ||
| 760 | } MPI2_SGE_SIMPLE32, MPI2_POINTER PTR_MPI2_SGE_SIMPLE32, | ||
| 761 | Mpi2SGESimple32_t, MPI2_POINTER pMpi2SGESimple32_t; | ||
| 762 | |||
| 763 | typedef struct _MPI2_SGE_SIMPLE64 | ||
| 764 | { | ||
| 765 | U32 FlagsLength; | ||
| 766 | U64 Address; | ||
| 767 | } MPI2_SGE_SIMPLE64, MPI2_POINTER PTR_MPI2_SGE_SIMPLE64, | ||
| 768 | Mpi2SGESimple64_t, MPI2_POINTER pMpi2SGESimple64_t; | ||
| 769 | |||
| 770 | typedef struct _MPI2_SGE_SIMPLE_UNION | ||
| 771 | { | ||
| 772 | U32 FlagsLength; | ||
| 773 | union | ||
| 774 | { | ||
| 775 | U32 Address32; | ||
| 776 | U64 Address64; | ||
| 777 | } u; | ||
| 778 | } MPI2_SGE_SIMPLE_UNION, MPI2_POINTER PTR_MPI2_SGE_SIMPLE_UNION, | ||
| 779 | Mpi2SGESimpleUnion_t, MPI2_POINTER pMpi2SGESimpleUnion_t; | ||
| 780 | |||
| 781 | |||
| 782 | /**************************************************************************** | ||
| 783 | * MPI Chain Element structures | ||
| 784 | ****************************************************************************/ | ||
| 785 | |||
| 786 | typedef struct _MPI2_SGE_CHAIN32 | ||
| 787 | { | ||
| 788 | U16 Length; | ||
| 789 | U8 NextChainOffset; | ||
| 790 | U8 Flags; | ||
| 791 | U32 Address; | ||
| 792 | } MPI2_SGE_CHAIN32, MPI2_POINTER PTR_MPI2_SGE_CHAIN32, | ||
| 793 | Mpi2SGEChain32_t, MPI2_POINTER pMpi2SGEChain32_t; | ||
| 794 | |||
| 795 | typedef struct _MPI2_SGE_CHAIN64 | ||
| 796 | { | ||
| 797 | U16 Length; | ||
| 798 | U8 NextChainOffset; | ||
| 799 | U8 Flags; | ||
| 800 | U64 Address; | ||
| 801 | } MPI2_SGE_CHAIN64, MPI2_POINTER PTR_MPI2_SGE_CHAIN64, | ||
| 802 | Mpi2SGEChain64_t, MPI2_POINTER pMpi2SGEChain64_t; | ||
| 803 | |||
| 804 | typedef struct _MPI2_SGE_CHAIN_UNION | ||
| 805 | { | ||
| 806 | U16 Length; | ||
| 807 | U8 NextChainOffset; | ||
| 808 | U8 Flags; | ||
| 809 | union | ||
| 810 | { | ||
| 811 | U32 Address32; | ||
| 812 | U64 Address64; | ||
| 813 | } u; | ||
| 814 | } MPI2_SGE_CHAIN_UNION, MPI2_POINTER PTR_MPI2_SGE_CHAIN_UNION, | ||
| 815 | Mpi2SGEChainUnion_t, MPI2_POINTER pMpi2SGEChainUnion_t; | ||
| 816 | |||
| 817 | |||
| 818 | /**************************************************************************** | ||
| 819 | * MPI Transaction Context Element structures | ||
| 820 | ****************************************************************************/ | ||
| 821 | |||
| 822 | typedef struct _MPI2_SGE_TRANSACTION32 | ||
| 823 | { | ||
| 824 | U8 Reserved; | ||
| 825 | U8 ContextSize; | ||
| 826 | U8 DetailsLength; | ||
| 827 | U8 Flags; | ||
| 828 | U32 TransactionContext[1]; | ||
| 829 | U32 TransactionDetails[1]; | ||
| 830 | } MPI2_SGE_TRANSACTION32, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION32, | ||
| 831 | Mpi2SGETransaction32_t, MPI2_POINTER pMpi2SGETransaction32_t; | ||
| 832 | |||
| 833 | typedef struct _MPI2_SGE_TRANSACTION64 | ||
| 834 | { | ||
| 835 | U8 Reserved; | ||
| 836 | U8 ContextSize; | ||
| 837 | U8 DetailsLength; | ||
| 838 | U8 Flags; | ||
| 839 | U32 TransactionContext[2]; | ||
| 840 | U32 TransactionDetails[1]; | ||
| 841 | } MPI2_SGE_TRANSACTION64, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION64, | ||
| 842 | Mpi2SGETransaction64_t, MPI2_POINTER pMpi2SGETransaction64_t; | ||
| 843 | |||
| 844 | typedef struct _MPI2_SGE_TRANSACTION96 | ||
| 845 | { | ||
| 846 | U8 Reserved; | ||
| 847 | U8 ContextSize; | ||
| 848 | U8 DetailsLength; | ||
| 849 | U8 Flags; | ||
| 850 | U32 TransactionContext[3]; | ||
| 851 | U32 TransactionDetails[1]; | ||
| 852 | } MPI2_SGE_TRANSACTION96, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION96, | ||
| 853 | Mpi2SGETransaction96_t, MPI2_POINTER pMpi2SGETransaction96_t; | ||
| 854 | |||
| 855 | typedef struct _MPI2_SGE_TRANSACTION128 | ||
| 856 | { | ||
| 857 | U8 Reserved; | ||
| 858 | U8 ContextSize; | ||
| 859 | U8 DetailsLength; | ||
| 860 | U8 Flags; | ||
| 861 | U32 TransactionContext[4]; | ||
| 862 | U32 TransactionDetails[1]; | ||
| 863 | } MPI2_SGE_TRANSACTION128, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION128, | ||
| 864 | Mpi2SGETransaction_t128, MPI2_POINTER pMpi2SGETransaction_t128; | ||
| 865 | |||
| 866 | typedef struct _MPI2_SGE_TRANSACTION_UNION | ||
| 867 | { | ||
| 868 | U8 Reserved; | ||
| 869 | U8 ContextSize; | ||
| 870 | U8 DetailsLength; | ||
| 871 | U8 Flags; | ||
| 872 | union | ||
| 873 | { | ||
| 874 | U32 TransactionContext32[1]; | ||
| 875 | U32 TransactionContext64[2]; | ||
| 876 | U32 TransactionContext96[3]; | ||
| 877 | U32 TransactionContext128[4]; | ||
| 878 | } u; | ||
| 879 | U32 TransactionDetails[1]; | ||
| 880 | } MPI2_SGE_TRANSACTION_UNION, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION_UNION, | ||
| 881 | Mpi2SGETransactionUnion_t, MPI2_POINTER pMpi2SGETransactionUnion_t; | ||
| 882 | |||
| 883 | |||
| 884 | /**************************************************************************** | ||
| 885 | * MPI SGE union for IO SGL's | ||
| 886 | ****************************************************************************/ | ||
| 887 | |||
| 888 | typedef struct _MPI2_MPI_SGE_IO_UNION | ||
| 889 | { | ||
| 890 | union | ||
| 891 | { | ||
| 892 | MPI2_SGE_SIMPLE_UNION Simple; | ||
| 893 | MPI2_SGE_CHAIN_UNION Chain; | ||
| 894 | } u; | ||
| 895 | } MPI2_MPI_SGE_IO_UNION, MPI2_POINTER PTR_MPI2_MPI_SGE_IO_UNION, | ||
| 896 | Mpi2MpiSGEIOUnion_t, MPI2_POINTER pMpi2MpiSGEIOUnion_t; | ||
| 897 | |||
| 898 | |||
| 899 | /**************************************************************************** | ||
| 900 | * MPI SGE union for SGL's with Simple and Transaction elements | ||
| 901 | ****************************************************************************/ | ||
| 902 | |||
| 903 | typedef struct _MPI2_SGE_TRANS_SIMPLE_UNION | ||
| 904 | { | ||
| 905 | union | ||
| 906 | { | ||
| 907 | MPI2_SGE_SIMPLE_UNION Simple; | ||
| 908 | MPI2_SGE_TRANSACTION_UNION Transaction; | ||
| 909 | } u; | ||
| 910 | } MPI2_SGE_TRANS_SIMPLE_UNION, MPI2_POINTER PTR_MPI2_SGE_TRANS_SIMPLE_UNION, | ||
| 911 | Mpi2SGETransSimpleUnion_t, MPI2_POINTER pMpi2SGETransSimpleUnion_t; | ||
| 912 | |||
| 913 | |||
| 914 | /**************************************************************************** | ||
| 915 | * All MPI SGE types union | ||
| 916 | ****************************************************************************/ | ||
| 917 | |||
| 918 | typedef struct _MPI2_MPI_SGE_UNION | ||
| 919 | { | ||
| 920 | union | ||
| 921 | { | ||
| 922 | MPI2_SGE_SIMPLE_UNION Simple; | ||
| 923 | MPI2_SGE_CHAIN_UNION Chain; | ||
| 924 | MPI2_SGE_TRANSACTION_UNION Transaction; | ||
| 925 | } u; | ||
| 926 | } MPI2_MPI_SGE_UNION, MPI2_POINTER PTR_MPI2_MPI_SGE_UNION, | ||
| 927 | Mpi2MpiSgeUnion_t, MPI2_POINTER pMpi2MpiSgeUnion_t; | ||
| 928 | |||
| 929 | |||
| 930 | /**************************************************************************** | ||
| 931 | * MPI SGE field definition and masks | ||
| 932 | ****************************************************************************/ | ||
| 933 | |||
| 934 | /* Flags field bit definitions */ | ||
| 935 | |||
| 936 | #define MPI2_SGE_FLAGS_LAST_ELEMENT (0x80) | ||
| 937 | #define MPI2_SGE_FLAGS_END_OF_BUFFER (0x40) | ||
| 938 | #define MPI2_SGE_FLAGS_ELEMENT_TYPE_MASK (0x30) | ||
| 939 | #define MPI2_SGE_FLAGS_LOCAL_ADDRESS (0x08) | ||
| 940 | #define MPI2_SGE_FLAGS_DIRECTION (0x04) | ||
| 941 | #define MPI2_SGE_FLAGS_ADDRESS_SIZE (0x02) | ||
| 942 | #define MPI2_SGE_FLAGS_END_OF_LIST (0x01) | ||
| 943 | |||
| 944 | #define MPI2_SGE_FLAGS_SHIFT (24) | ||
| 945 | |||
| 946 | #define MPI2_SGE_LENGTH_MASK (0x00FFFFFF) | ||
| 947 | #define MPI2_SGE_CHAIN_LENGTH_MASK (0x0000FFFF) | ||
| 948 | |||
| 949 | /* Element Type */ | ||
| 950 | |||
| 951 | #define MPI2_SGE_FLAGS_TRANSACTION_ELEMENT (0x00) | ||
| 952 | #define MPI2_SGE_FLAGS_SIMPLE_ELEMENT (0x10) | ||
| 953 | #define MPI2_SGE_FLAGS_CHAIN_ELEMENT (0x30) | ||
| 954 | #define MPI2_SGE_FLAGS_ELEMENT_MASK (0x30) | ||
| 955 | |||
| 956 | /* Address location */ | ||
| 957 | |||
| 958 | #define MPI2_SGE_FLAGS_SYSTEM_ADDRESS (0x00) | ||
| 959 | |||
| 960 | /* Direction */ | ||
| 961 | |||
| 962 | #define MPI2_SGE_FLAGS_IOC_TO_HOST (0x00) | ||
| 963 | #define MPI2_SGE_FLAGS_HOST_TO_IOC (0x04) | ||
| 964 | |||
| 965 | #define MPI2_SGE_FLAGS_DEST (MPI2_SGE_FLAGS_IOC_TO_HOST) | ||
| 966 | #define MPI2_SGE_FLAGS_SOURCE (MPI2_SGE_FLAGS_HOST_TO_IOC) | ||
| 967 | |||
| 968 | /* Address Size */ | ||
| 969 | |||
| 970 | #define MPI2_SGE_FLAGS_32_BIT_ADDRESSING (0x00) | ||
| 971 | #define MPI2_SGE_FLAGS_64_BIT_ADDRESSING (0x02) | ||
| 972 | |||
| 973 | /* Context Size */ | ||
| 974 | |||
| 975 | #define MPI2_SGE_FLAGS_32_BIT_CONTEXT (0x00) | ||
| 976 | #define MPI2_SGE_FLAGS_64_BIT_CONTEXT (0x02) | ||
| 977 | #define MPI2_SGE_FLAGS_96_BIT_CONTEXT (0x04) | ||
| 978 | #define MPI2_SGE_FLAGS_128_BIT_CONTEXT (0x06) | ||
| 979 | |||
| 980 | #define MPI2_SGE_CHAIN_OFFSET_MASK (0x00FF0000) | ||
| 981 | #define MPI2_SGE_CHAIN_OFFSET_SHIFT (16) | ||
| 982 | |||
| 983 | /**************************************************************************** | ||
| 984 | * MPI SGE operation Macros | ||
| 985 | ****************************************************************************/ | ||
| 986 | |||
| 987 | /* SIMPLE FlagsLength manipulations... */ | ||
| 988 | #define MPI2_SGE_SET_FLAGS(f) ((U32)(f) << MPI2_SGE_FLAGS_SHIFT) | ||
| 989 | #define MPI2_SGE_GET_FLAGS(f) (((f) & ~MPI2_SGE_LENGTH_MASK) >> MPI2_SGE_FLAGS_SHIFT) | ||
| 990 | #define MPI2_SGE_LENGTH(f) ((f) & MPI2_SGE_LENGTH_MASK) | ||
| 991 | #define MPI2_SGE_CHAIN_LENGTH(f) ((f) & MPI2_SGE_CHAIN_LENGTH_MASK) | ||
| 992 | |||
| 993 | #define MPI2_SGE_SET_FLAGS_LENGTH(f,l) (MPI2_SGE_SET_FLAGS(f) | MPI2_SGE_LENGTH(l)) | ||
| 994 | |||
| 995 | #define MPI2_pSGE_GET_FLAGS(psg) MPI2_SGE_GET_FLAGS((psg)->FlagsLength) | ||
| 996 | #define MPI2_pSGE_GET_LENGTH(psg) MPI2_SGE_LENGTH((psg)->FlagsLength) | ||
| 997 | #define MPI2_pSGE_SET_FLAGS_LENGTH(psg,f,l) (psg)->FlagsLength = MPI2_SGE_SET_FLAGS_LENGTH(f,l) | ||
| 998 | |||
| 999 | /* CAUTION - The following are READ-MODIFY-WRITE! */ | ||
| 1000 | #define MPI2_pSGE_SET_FLAGS(psg,f) (psg)->FlagsLength |= MPI2_SGE_SET_FLAGS(f) | ||
| 1001 | #define MPI2_pSGE_SET_LENGTH(psg,l) (psg)->FlagsLength |= MPI2_SGE_LENGTH(l) | ||
| 1002 | |||
| 1003 | #define MPI2_GET_CHAIN_OFFSET(x) ((x & MPI2_SGE_CHAIN_OFFSET_MASK) >> MPI2_SGE_CHAIN_OFFSET_SHIFT) | ||
| 1004 | |||
| 1005 | |||
| 1006 | /***************************************************************************** | ||
| 1007 | * | ||
| 1008 | * Fusion-MPT IEEE Scatter Gather Elements | ||
| 1009 | * | ||
| 1010 | *****************************************************************************/ | ||
| 1011 | |||
| 1012 | /**************************************************************************** | ||
| 1013 | * IEEE Simple Element structures | ||
| 1014 | ****************************************************************************/ | ||
| 1015 | |||
| 1016 | typedef struct _MPI2_IEEE_SGE_SIMPLE32 | ||
| 1017 | { | ||
| 1018 | U32 Address; | ||
| 1019 | U32 FlagsLength; | ||
| 1020 | } MPI2_IEEE_SGE_SIMPLE32, MPI2_POINTER PTR_MPI2_IEEE_SGE_SIMPLE32, | ||
| 1021 | Mpi2IeeeSgeSimple32_t, MPI2_POINTER pMpi2IeeeSgeSimple32_t; | ||
| 1022 | |||
| 1023 | typedef struct _MPI2_IEEE_SGE_SIMPLE64 | ||
| 1024 | { | ||
| 1025 | U64 Address; | ||
| 1026 | U32 Length; | ||
| 1027 | U16 Reserved1; | ||
| 1028 | U8 Reserved2; | ||
| 1029 | U8 Flags; | ||
| 1030 | } MPI2_IEEE_SGE_SIMPLE64, MPI2_POINTER PTR_MPI2_IEEE_SGE_SIMPLE64, | ||
| 1031 | Mpi2IeeeSgeSimple64_t, MPI2_POINTER pMpi2IeeeSgeSimple64_t; | ||
| 1032 | |||
| 1033 | typedef union _MPI2_IEEE_SGE_SIMPLE_UNION | ||
| 1034 | { | ||
| 1035 | MPI2_IEEE_SGE_SIMPLE32 Simple32; | ||
| 1036 | MPI2_IEEE_SGE_SIMPLE64 Simple64; | ||
| 1037 | } MPI2_IEEE_SGE_SIMPLE_UNION, MPI2_POINTER PTR_MPI2_IEEE_SGE_SIMPLE_UNION, | ||
| 1038 | Mpi2IeeeSgeSimpleUnion_t, MPI2_POINTER pMpi2IeeeSgeSimpleUnion_t; | ||
| 1039 | |||
| 1040 | |||
| 1041 | /**************************************************************************** | ||
| 1042 | * IEEE Chain Element structures | ||
| 1043 | ****************************************************************************/ | ||
| 1044 | |||
| 1045 | typedef MPI2_IEEE_SGE_SIMPLE32 MPI2_IEEE_SGE_CHAIN32; | ||
| 1046 | |||
| 1047 | typedef MPI2_IEEE_SGE_SIMPLE64 MPI2_IEEE_SGE_CHAIN64; | ||
| 1048 | |||
| 1049 | typedef union _MPI2_IEEE_SGE_CHAIN_UNION | ||
| 1050 | { | ||
| 1051 | MPI2_IEEE_SGE_CHAIN32 Chain32; | ||
| 1052 | MPI2_IEEE_SGE_CHAIN64 Chain64; | ||
| 1053 | } MPI2_IEEE_SGE_CHAIN_UNION, MPI2_POINTER PTR_MPI2_IEEE_SGE_CHAIN_UNION, | ||
| 1054 | Mpi2IeeeSgeChainUnion_t, MPI2_POINTER pMpi2IeeeSgeChainUnion_t; | ||
| 1055 | |||
| 1056 | |||
| 1057 | /**************************************************************************** | ||
| 1058 | * All IEEE SGE types union | ||
| 1059 | ****************************************************************************/ | ||
| 1060 | |||
| 1061 | typedef struct _MPI2_IEEE_SGE_UNION | ||
| 1062 | { | ||
| 1063 | union | ||
| 1064 | { | ||
| 1065 | MPI2_IEEE_SGE_SIMPLE_UNION Simple; | ||
| 1066 | MPI2_IEEE_SGE_CHAIN_UNION Chain; | ||
| 1067 | } u; | ||
| 1068 | } MPI2_IEEE_SGE_UNION, MPI2_POINTER PTR_MPI2_IEEE_SGE_UNION, | ||
| 1069 | Mpi2IeeeSgeUnion_t, MPI2_POINTER pMpi2IeeeSgeUnion_t; | ||
| 1070 | |||
| 1071 | |||
| 1072 | /**************************************************************************** | ||
| 1073 | * IEEE SGE field definitions and masks | ||
| 1074 | ****************************************************************************/ | ||
| 1075 | |||
| 1076 | /* Flags field bit definitions */ | ||
| 1077 | |||
| 1078 | #define MPI2_IEEE_SGE_FLAGS_ELEMENT_TYPE_MASK (0x80) | ||
| 1079 | |||
| 1080 | #define MPI2_IEEE32_SGE_FLAGS_SHIFT (24) | ||
| 1081 | |||
| 1082 | #define MPI2_IEEE32_SGE_LENGTH_MASK (0x00FFFFFF) | ||
| 1083 | |||
| 1084 | /* Element Type */ | ||
| 1085 | |||
| 1086 | #define MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT (0x00) | ||
| 1087 | #define MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT (0x80) | ||
| 1088 | |||
| 1089 | /* Data Location Address Space */ | ||
| 1090 | |||
| 1091 | #define MPI2_IEEE_SGE_FLAGS_ADDR_MASK (0x03) | ||
| 1092 | #define MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR (0x00) | ||
| 1093 | /* IEEE Simple Element only */ | ||
| 1094 | #define MPI2_IEEE_SGE_FLAGS_IOCDDR_ADDR (0x01) | ||
| 1095 | /* IEEE Simple Element only */ | ||
| 1096 | #define MPI2_IEEE_SGE_FLAGS_IOCPLB_ADDR (0x02) | ||
| 1097 | #define MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR (0x03) | ||
| 1098 | /* IEEE Simple Element only */ | ||
| 1099 | #define MPI2_IEEE_SGE_FLAGS_SYSTEMPLBPCI_ADDR (0x03) | ||
| 1100 | /* IEEE Chain Element only */ | ||
| 1101 | #define MPI2_IEEE_SGE_FLAGS_SYSTEMPLBCPI_ADDR \ | ||
| 1102 | (MPI2_IEEE_SGE_FLAGS_SYSTEMPLBPCI_ADDR) /* typo in name */ | ||
| 1103 | |||
| 1104 | /**************************************************************************** | ||
| 1105 | * IEEE SGE operation Macros | ||
| 1106 | ****************************************************************************/ | ||
| 1107 | |||
| 1108 | /* SIMPLE FlagsLength manipulations... */ | ||
| 1109 | #define MPI2_IEEE32_SGE_SET_FLAGS(f) ((U32)(f) << MPI2_IEEE32_SGE_FLAGS_SHIFT) | ||
| 1110 | #define MPI2_IEEE32_SGE_GET_FLAGS(f) (((f) & ~MPI2_IEEE32_SGE_LENGTH_MASK) >> MPI2_IEEE32_SGE_FLAGS_SHIFT) | ||
| 1111 | #define MPI2_IEEE32_SGE_LENGTH(f) ((f) & MPI2_IEEE32_SGE_LENGTH_MASK) | ||
| 1112 | |||
| 1113 | #define MPI2_IEEE32_SGE_SET_FLAGS_LENGTH(f, l) (MPI2_IEEE32_SGE_SET_FLAGS(f) | MPI2_IEEE32_SGE_LENGTH(l)) | ||
| 1114 | |||
| 1115 | #define MPI2_IEEE32_pSGE_GET_FLAGS(psg) MPI2_IEEE32_SGE_GET_FLAGS((psg)->FlagsLength) | ||
| 1116 | #define MPI2_IEEE32_pSGE_GET_LENGTH(psg) MPI2_IEEE32_SGE_LENGTH((psg)->FlagsLength) | ||
| 1117 | #define MPI2_IEEE32_pSGE_SET_FLAGS_LENGTH(psg,f,l) (psg)->FlagsLength = MPI2_IEEE32_SGE_SET_FLAGS_LENGTH(f,l) | ||
| 1118 | |||
| 1119 | /* CAUTION - The following are READ-MODIFY-WRITE! */ | ||
| 1120 | #define MPI2_IEEE32_pSGE_SET_FLAGS(psg,f) (psg)->FlagsLength |= MPI2_IEEE32_SGE_SET_FLAGS(f) | ||
| 1121 | #define MPI2_IEEE32_pSGE_SET_LENGTH(psg,l) (psg)->FlagsLength |= MPI2_IEEE32_SGE_LENGTH(l) | ||
| 1122 | |||
| 1123 | |||
| 1124 | |||
| 1125 | |||
| 1126 | /***************************************************************************** | ||
| 1127 | * | ||
| 1128 | * Fusion-MPT MPI/IEEE Scatter Gather Unions | ||
| 1129 | * | ||
| 1130 | *****************************************************************************/ | ||
| 1131 | |||
| 1132 | typedef union _MPI2_SIMPLE_SGE_UNION | ||
| 1133 | { | ||
| 1134 | MPI2_SGE_SIMPLE_UNION MpiSimple; | ||
| 1135 | MPI2_IEEE_SGE_SIMPLE_UNION IeeeSimple; | ||
| 1136 | } MPI2_SIMPLE_SGE_UNION, MPI2_POINTER PTR_MPI2_SIMPLE_SGE_UNION, | ||
| 1137 | Mpi2SimpleSgeUntion_t, MPI2_POINTER pMpi2SimpleSgeUntion_t; | ||
| 1138 | |||
| 1139 | |||
| 1140 | typedef union _MPI2_SGE_IO_UNION | ||
| 1141 | { | ||
| 1142 | MPI2_SGE_SIMPLE_UNION MpiSimple; | ||
| 1143 | MPI2_SGE_CHAIN_UNION MpiChain; | ||
| 1144 | MPI2_IEEE_SGE_SIMPLE_UNION IeeeSimple; | ||
| 1145 | MPI2_IEEE_SGE_CHAIN_UNION IeeeChain; | ||
| 1146 | } MPI2_SGE_IO_UNION, MPI2_POINTER PTR_MPI2_SGE_IO_UNION, | ||
| 1147 | Mpi2SGEIOUnion_t, MPI2_POINTER pMpi2SGEIOUnion_t; | ||
| 1148 | |||
| 1149 | |||
| 1150 | /**************************************************************************** | ||
| 1151 | * | ||
| 1152 | * Values for SGLFlags field, used in many request messages with an SGL | ||
| 1153 | * | ||
| 1154 | ****************************************************************************/ | ||
| 1155 | |||
| 1156 | /* values for MPI SGL Data Location Address Space subfield */ | ||
| 1157 | #define MPI2_SGLFLAGS_ADDRESS_SPACE_MASK (0x0C) | ||
| 1158 | #define MPI2_SGLFLAGS_SYSTEM_ADDRESS_SPACE (0x00) | ||
| 1159 | #define MPI2_SGLFLAGS_IOCDDR_ADDRESS_SPACE (0x04) | ||
| 1160 | #define MPI2_SGLFLAGS_IOCPLB_ADDRESS_SPACE (0x08) | ||
| 1161 | #define MPI2_SGLFLAGS_IOCPLBNTA_ADDRESS_SPACE (0x0C) | ||
| 1162 | /* values for SGL Type subfield */ | ||
| 1163 | #define MPI2_SGLFLAGS_SGL_TYPE_MASK (0x03) | ||
| 1164 | #define MPI2_SGLFLAGS_SGL_TYPE_MPI (0x00) | ||
| 1165 | #define MPI2_SGLFLAGS_SGL_TYPE_IEEE32 (0x01) | ||
| 1166 | #define MPI2_SGLFLAGS_SGL_TYPE_IEEE64 (0x02) | ||
| 1167 | |||
| 1168 | |||
| 1169 | #endif | ||
| 1170 | |||
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h deleted file mode 100644 index ee8d2d695d55..000000000000 --- a/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h +++ /dev/null | |||
| @@ -1,3068 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2000-2014 LSI Corporation. | ||
| 3 | * | ||
| 4 | * | ||
| 5 | * Name: mpi2_cnfg.h | ||
| 6 | * Title: MPI Configuration messages and pages | ||
| 7 | * Creation Date: November 10, 2006 | ||
| 8 | * | ||
| 9 | * mpi2_cnfg.h Version: 02.00.29 | ||
| 10 | * | ||
| 11 | * Version History | ||
| 12 | * --------------- | ||
| 13 | * | ||
| 14 | * Date Version Description | ||
| 15 | * -------- -------- ------------------------------------------------------ | ||
| 16 | * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. | ||
| 17 | * 06-04-07 02.00.01 Added defines for SAS IO Unit Page 2 PhyFlags. | ||
| 18 | * Added Manufacturing Page 11. | ||
| 19 | * Added MPI2_SAS_EXPANDER0_FLAGS_CONNECTOR_END_DEVICE | ||
| 20 | * define. | ||
| 21 | * 06-26-07 02.00.02 Adding generic structure for product-specific | ||
| 22 | * Manufacturing pages: MPI2_CONFIG_PAGE_MANUFACTURING_PS. | ||
| 23 | * Rework of BIOS Page 2 configuration page. | ||
| 24 | * Fixed MPI2_BIOSPAGE2_BOOT_DEVICE to be a union of the | ||
| 25 | * forms. | ||
| 26 | * Added configuration pages IOC Page 8 and Driver | ||
| 27 | * Persistent Mapping Page 0. | ||
| 28 | * 08-31-07 02.00.03 Modified configuration pages dealing with Integrated | ||
| 29 | * RAID (Manufacturing Page 4, RAID Volume Pages 0 and 1, | ||
| 30 | * RAID Physical Disk Pages 0 and 1, RAID Configuration | ||
| 31 | * Page 0). | ||
| 32 | * Added new value for AccessStatus field of SAS Device | ||
| 33 | * Page 0 (_SATA_NEEDS_INITIALIZATION). | ||
| 34 | * 10-31-07 02.00.04 Added missing SEPDevHandle field to | ||
| 35 | * MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0. | ||
| 36 | * 12-18-07 02.00.05 Modified IO Unit Page 0 to use 32-bit version fields for | ||
| 37 | * NVDATA. | ||
| 38 | * Modified IOC Page 7 to use masks and added field for | ||
| 39 | * SASBroadcastPrimitiveMasks. | ||
| 40 | * Added MPI2_CONFIG_PAGE_BIOS_4. | ||
| 41 | * Added MPI2_CONFIG_PAGE_LOG_0. | ||
| 42 | * 02-29-08 02.00.06 Modified various names to make them 32-character unique. | ||
| 43 | * Added SAS Device IDs. | ||
| 44 | * Updated Integrated RAID configuration pages including | ||
| 45 | * Manufacturing Page 4, IOC Page 6, and RAID Configuration | ||
| 46 | * Page 0. | ||
| 47 | * 05-21-08 02.00.07 Added define MPI2_MANPAGE4_MIX_SSD_SAS_SATA. | ||
| 48 | * Added define MPI2_MANPAGE4_PHYSDISK_128MB_COERCION. | ||
| 49 | * Fixed define MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING. | ||
| 50 | * Added missing MaxNumRoutedSasAddresses field to | ||
| 51 | * MPI2_CONFIG_PAGE_EXPANDER_0. | ||
| 52 | * Added SAS Port Page 0. | ||
| 53 | * Modified structure layout for | ||
| 54 | * MPI2_CONFIG_PAGE_DRIVER_MAPPING_0. | ||
| 55 | * 06-27-08 02.00.08 Changed MPI2_CONFIG_PAGE_RD_PDISK_1 to use | ||
| 56 | * MPI2_RAID_PHYS_DISK1_PATH_MAX to size the array. | ||
| 57 | * 10-02-08 02.00.09 Changed MPI2_RAID_PGAD_CONFIGNUM_MASK from 0x0000FFFF | ||
| 58 | * to 0x000000FF. | ||
| 59 | * Added two new values for the Physical Disk Coercion Size | ||
| 60 | * bits in the Flags field of Manufacturing Page 4. | ||
| 61 | * Added product-specific Manufacturing pages 16 to 31. | ||
| 62 | * Modified Flags bits for controlling write cache on SATA | ||
| 63 | * drives in IO Unit Page 1. | ||
| 64 | * Added new bit to AdditionalControlFlags of SAS IO Unit | ||
| 65 | * Page 1 to control Invalid Topology Correction. | ||
| 66 | * Added additional defines for RAID Volume Page 0 | ||
| 67 | * VolumeStatusFlags field. | ||
| 68 | * Modified meaning of RAID Volume Page 0 VolumeSettings | ||
| 69 | * define for auto-configure of hot-swap drives. | ||
| 70 | * Added SupportedPhysDisks field to RAID Volume Page 1 and | ||
| 71 | * added related defines. | ||
| 72 | * Added PhysDiskAttributes field (and related defines) to | ||
| 73 | * RAID Physical Disk Page 0. | ||
| 74 | * Added MPI2_SAS_PHYINFO_PHY_VACANT define. | ||
| 75 | * Added three new DiscoveryStatus bits for SAS IO Unit | ||
| 76 | * Page 0 and SAS Expander Page 0. | ||
| 77 | * Removed multiplexing information from SAS IO Unit pages. | ||
| 78 | * Added BootDeviceWaitTime field to SAS IO Unit Page 4. | ||
| 79 | * Removed Zone Address Resolved bit from PhyInfo and from | ||
| 80 | * Expander Page 0 Flags field. | ||
| 81 | * Added two new AccessStatus values to SAS Device Page 0 | ||
| 82 | * for indicating routing problems. Added 3 reserved words | ||
| 83 | * to this page. | ||
| 84 | * 01-19-09 02.00.10 Fixed defines for GPIOVal field of IO Unit Page 3. | ||
| 85 | * Inserted missing reserved field into structure for IOC | ||
| 86 | * Page 6. | ||
| 87 | * Added more pending task bits to RAID Volume Page 0 | ||
| 88 | * VolumeStatusFlags defines. | ||
| 89 | * Added MPI2_PHYSDISK0_STATUS_FLAG_NOT_CERTIFIED define. | ||
| 90 | * Added a new DiscoveryStatus bit for SAS IO Unit Page 0 | ||
| 91 | * and SAS Expander Page 0 to flag a downstream initiator | ||
| 92 | * when in simplified routing mode. | ||
| 93 | * Removed SATA Init Failure defines for DiscoveryStatus | ||
| 94 | * fields of SAS IO Unit Page 0 and SAS Expander Page 0. | ||
| 95 | * Added MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED define. | ||
| 96 | * Added PortGroups, DmaGroup, and ControlGroup fields to | ||
| 97 | * SAS Device Page 0. | ||
| 98 | * 05-06-09 02.00.11 Added structures and defines for IO Unit Page 5 and IO | ||
| 99 | * Unit Page 6. | ||
| 100 | * Added expander reduced functionality data to SAS | ||
| 101 | * Expander Page 0. | ||
| 102 | * Added SAS PHY Page 2 and SAS PHY Page 3. | ||
| 103 | * 07-30-09 02.00.12 Added IO Unit Page 7. | ||
| 104 | * Added new device ids. | ||
| 105 | * Added SAS IO Unit Page 5. | ||
| 106 | * Added partial and slumber power management capable flags | ||
| 107 | * to SAS Device Page 0 Flags field. | ||
| 108 | * Added PhyInfo defines for power condition. | ||
| 109 | * Added Ethernet configuration pages. | ||
| 110 | * 10-28-09 02.00.13 Added MPI2_IOUNITPAGE1_ENABLE_HOST_BASED_DISCOVERY. | ||
| 111 | * Added SAS PHY Page 4 structure and defines. | ||
| 112 | * 02-10-10 02.00.14 Modified the comments for the configuration page | ||
| 113 | * structures that contain an array of data. The host | ||
| 114 | * should use the "count" field in the page data (e.g. the | ||
| 115 | * NumPhys field) to determine the number of valid elements | ||
| 116 | * in the array. | ||
| 117 | * Added/modified some MPI2_MFGPAGE_DEVID_SAS defines. | ||
| 118 | * Added PowerManagementCapabilities to IO Unit Page 7. | ||
| 119 | * Added PortWidthModGroup field to | ||
| 120 | * MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS. | ||
| 121 | * Added MPI2_CONFIG_PAGE_SASIOUNIT_6 and related defines. | ||
| 122 | * Added MPI2_CONFIG_PAGE_SASIOUNIT_7 and related defines. | ||
| 123 | * Added MPI2_CONFIG_PAGE_SASIOUNIT_8 and related defines. | ||
| 124 | * 05-12-10 02.00.15 Added MPI2_RAIDVOL0_STATUS_FLAG_VOL_NOT_CONSISTENT | ||
| 125 | * define. | ||
| 126 | * Added MPI2_PHYSDISK0_INCOMPATIBLE_MEDIA_TYPE define. | ||
| 127 | * Added MPI2_SAS_NEG_LINK_RATE_UNSUPPORTED_PHY define. | ||
| 128 | * 08-11-10 02.00.16 Removed IO Unit Page 1 device path (multi-pathing) | ||
| 129 | * defines. | ||
| 130 | * 11-10-10 02.00.17 Added ReceptacleID field (replacing Reserved1) to | ||
| 131 | * MPI2_MANPAGE7_CONNECTOR_INFO and reworked defines for | ||
| 132 | * the Pinout field. | ||
| 133 | * Added BoardTemperature and BoardTemperatureUnits fields | ||
| 134 | * to MPI2_CONFIG_PAGE_IO_UNIT_7. | ||
| 135 | * Added MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING define | ||
| 136 | * and MPI2_CONFIG_PAGE_EXT_MAN_PS structure. | ||
| 137 | * 02-23-11 02.00.18 Added ProxyVF_ID field to MPI2_CONFIG_REQUEST. | ||
| 138 | * Added IO Unit Page 8, IO Unit Page 9, | ||
| 139 | * and IO Unit Page 10. | ||
| 140 | * Added SASNotifyPrimitiveMasks field to | ||
| 141 | * MPI2_CONFIG_PAGE_IOC_7. | ||
| 142 | * 03-09-11 02.00.19 Fixed IO Unit Page 10 (to match the spec). | ||
| 143 | * 05-25-11 02.00.20 Cleaned up a few comments. | ||
| 144 | * 08-24-11 02.00.21 Marked the IO Unit Page 7 PowerManagementCapabilities | ||
| 145 | * for PCIe link as obsolete. | ||
| 146 | * Added SpinupFlags field containing a Disable Spin-up | ||
| 147 | * bit to the MPI2_SAS_IOUNIT4_SPINUP_GROUP fields of | ||
| 148 | * SAS IO Unit Page 4. | ||
| 149 | * 11-18-11 02.00.22 Added define MPI2_IOCPAGE6_CAP_FLAGS_4K_SECTORS_SUPPORT. | ||
| 150 | * Added UEFIVersion field to BIOS Page 1 and defined new | ||
| 151 | * BiosOptions bits. | ||
| 152 | * 11-27-12 02.00.23 Added MPI2_MANPAGE7_FLAG_EVENTREPLAY_SLOT_ORDER. | ||
| 153 | * Added MPI2_BIOSPAGE1_OPTIONS_MASK_OEM_ID. | ||
| 154 | * 12-20-12 02.00.24 Marked MPI2_SASIOUNIT1_CONTROL_CLEAR_AFFILIATION as | ||
| 155 | * obsolete for MPI v2.5 and later. | ||
| 156 | * Added some defines for 12G SAS speeds. | ||
| 157 | * 04-09-13 02.00.25 Added MPI2_IOUNITPAGE1_ATA_SECURITY_FREEZE_LOCK. | ||
| 158 | * Fixed MPI2_IOUNITPAGE5_DMA_CAP_MASK_MAX_REQUESTS to | ||
| 159 | * match the specification. | ||
| 160 | * 12-05-13 02.00.27 Added MPI2_MANPAGE7_FLAG_BASE_ENCLOSURE_LEVEL for | ||
| 161 | * MPI2_CONFIG_PAGE_MAN_7. | ||
| 162 | * Added EnclosureLevel and ConnectorName fields to | ||
| 163 | * MPI2_CONFIG_PAGE_SAS_DEV_0. | ||
| 164 | * Added MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID for | ||
| 165 | * MPI2_CONFIG_PAGE_SAS_DEV_0. | ||
| 166 | * Added EnclosureLevel field to | ||
| 167 | * MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0. | ||
| 168 | * Added MPI2_SAS_ENCLS0_FLAGS_ENCL_LEVEL_VALID for | ||
| 169 | * MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0. | ||
| 170 | * 01-08-14 02.00.28 Added more defines for the BiosOptions field of | ||
| 171 | * MPI2_CONFIG_PAGE_BIOS_1. | ||
| 172 | * 06-13-14 02.00.29 Added SSUTimeout field to MPI2_CONFIG_PAGE_BIOS_1, and | ||
| 173 | * more defines for the BiosOptions field. | ||
| 174 | * -------------------------------------------------------------------------- | ||
| 175 | */ | ||
| 176 | |||
| 177 | #ifndef MPI2_CNFG_H | ||
| 178 | #define MPI2_CNFG_H | ||
| 179 | |||
| 180 | /***************************************************************************** | ||
| 181 | * Configuration Page Header and defines | ||
| 182 | *****************************************************************************/ | ||
| 183 | |||
| 184 | /* Config Page Header */ | ||
| 185 | typedef struct _MPI2_CONFIG_PAGE_HEADER | ||
| 186 | { | ||
| 187 | U8 PageVersion; /* 0x00 */ | ||
| 188 | U8 PageLength; /* 0x01 */ | ||
| 189 | U8 PageNumber; /* 0x02 */ | ||
| 190 | U8 PageType; /* 0x03 */ | ||
| 191 | } MPI2_CONFIG_PAGE_HEADER, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_HEADER, | ||
| 192 | Mpi2ConfigPageHeader_t, MPI2_POINTER pMpi2ConfigPageHeader_t; | ||
| 193 | |||
| 194 | typedef union _MPI2_CONFIG_PAGE_HEADER_UNION | ||
| 195 | { | ||
| 196 | MPI2_CONFIG_PAGE_HEADER Struct; | ||
| 197 | U8 Bytes[4]; | ||
| 198 | U16 Word16[2]; | ||
| 199 | U32 Word32; | ||
| 200 | } MPI2_CONFIG_PAGE_HEADER_UNION, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_HEADER_UNION, | ||
| 201 | Mpi2ConfigPageHeaderUnion, MPI2_POINTER pMpi2ConfigPageHeaderUnion; | ||
| 202 | |||
| 203 | /* Extended Config Page Header */ | ||
| 204 | typedef struct _MPI2_CONFIG_EXTENDED_PAGE_HEADER | ||
| 205 | { | ||
| 206 | U8 PageVersion; /* 0x00 */ | ||
| 207 | U8 Reserved1; /* 0x01 */ | ||
| 208 | U8 PageNumber; /* 0x02 */ | ||
| 209 | U8 PageType; /* 0x03 */ | ||
| 210 | U16 ExtPageLength; /* 0x04 */ | ||
| 211 | U8 ExtPageType; /* 0x06 */ | ||
| 212 | U8 Reserved2; /* 0x07 */ | ||
| 213 | } MPI2_CONFIG_EXTENDED_PAGE_HEADER, | ||
| 214 | MPI2_POINTER PTR_MPI2_CONFIG_EXTENDED_PAGE_HEADER, | ||
| 215 | Mpi2ConfigExtendedPageHeader_t, MPI2_POINTER pMpi2ConfigExtendedPageHeader_t; | ||
| 216 | |||
| 217 | typedef union _MPI2_CONFIG_EXT_PAGE_HEADER_UNION | ||
| 218 | { | ||
| 219 | MPI2_CONFIG_PAGE_HEADER Struct; | ||
| 220 | MPI2_CONFIG_EXTENDED_PAGE_HEADER Ext; | ||
| 221 | U8 Bytes[8]; | ||
| 222 | U16 Word16[4]; | ||
| 223 | U32 Word32[2]; | ||
| 224 | } MPI2_CONFIG_EXT_PAGE_HEADER_UNION, MPI2_POINTER PTR_MPI2_CONFIG_EXT_PAGE_HEADER_UNION, | ||
| 225 | Mpi2ConfigPageExtendedHeaderUnion, MPI2_POINTER pMpi2ConfigPageExtendedHeaderUnion; | ||
| 226 | |||
| 227 | |||
| 228 | /* PageType field values */ | ||
| 229 | #define MPI2_CONFIG_PAGEATTR_READ_ONLY (0x00) | ||
| 230 | #define MPI2_CONFIG_PAGEATTR_CHANGEABLE (0x10) | ||
| 231 | #define MPI2_CONFIG_PAGEATTR_PERSISTENT (0x20) | ||
| 232 | #define MPI2_CONFIG_PAGEATTR_MASK (0xF0) | ||
| 233 | |||
| 234 | #define MPI2_CONFIG_PAGETYPE_IO_UNIT (0x00) | ||
| 235 | #define MPI2_CONFIG_PAGETYPE_IOC (0x01) | ||
| 236 | #define MPI2_CONFIG_PAGETYPE_BIOS (0x02) | ||
| 237 | #define MPI2_CONFIG_PAGETYPE_RAID_VOLUME (0x08) | ||
| 238 | #define MPI2_CONFIG_PAGETYPE_MANUFACTURING (0x09) | ||
| 239 | #define MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK (0x0A) | ||
| 240 | #define MPI2_CONFIG_PAGETYPE_EXTENDED (0x0F) | ||
| 241 | #define MPI2_CONFIG_PAGETYPE_MASK (0x0F) | ||
| 242 | |||
| 243 | #define MPI2_CONFIG_TYPENUM_MASK (0x0FFF) | ||
| 244 | |||
| 245 | |||
| 246 | /* ExtPageType field values */ | ||
| 247 | #define MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT (0x10) | ||
| 248 | #define MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER (0x11) | ||
| 249 | #define MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE (0x12) | ||
| 250 | #define MPI2_CONFIG_EXTPAGETYPE_SAS_PHY (0x13) | ||
| 251 | #define MPI2_CONFIG_EXTPAGETYPE_LOG (0x14) | ||
| 252 | #define MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE (0x15) | ||
| 253 | #define MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG (0x16) | ||
| 254 | #define MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING (0x17) | ||
| 255 | #define MPI2_CONFIG_EXTPAGETYPE_SAS_PORT (0x18) | ||
| 256 | #define MPI2_CONFIG_EXTPAGETYPE_ETHERNET (0x19) | ||
| 257 | #define MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING (0x1A) | ||
| 258 | |||
| 259 | |||
| 260 | /***************************************************************************** | ||
| 261 | * PageAddress defines | ||
| 262 | *****************************************************************************/ | ||
| 263 | |||
| 264 | /* RAID Volume PageAddress format */ | ||
| 265 | #define MPI2_RAID_VOLUME_PGAD_FORM_MASK (0xF0000000) | ||
| 266 | #define MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE (0x00000000) | ||
| 267 | #define MPI2_RAID_VOLUME_PGAD_FORM_HANDLE (0x10000000) | ||
| 268 | |||
| 269 | #define MPI2_RAID_VOLUME_PGAD_HANDLE_MASK (0x0000FFFF) | ||
| 270 | |||
| 271 | |||
| 272 | /* RAID Physical Disk PageAddress format */ | ||
| 273 | #define MPI2_PHYSDISK_PGAD_FORM_MASK (0xF0000000) | ||
| 274 | #define MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM (0x00000000) | ||
| 275 | #define MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM (0x10000000) | ||
| 276 | #define MPI2_PHYSDISK_PGAD_FORM_DEVHANDLE (0x20000000) | ||
| 277 | |||
| 278 | #define MPI2_PHYSDISK_PGAD_PHYSDISKNUM_MASK (0x000000FF) | ||
| 279 | #define MPI2_PHYSDISK_PGAD_DEVHANDLE_MASK (0x0000FFFF) | ||
| 280 | |||
| 281 | |||
| 282 | /* SAS Expander PageAddress format */ | ||
| 283 | #define MPI2_SAS_EXPAND_PGAD_FORM_MASK (0xF0000000) | ||
| 284 | #define MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL (0x00000000) | ||
| 285 | #define MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM (0x10000000) | ||
| 286 | #define MPI2_SAS_EXPAND_PGAD_FORM_HNDL (0x20000000) | ||
| 287 | |||
| 288 | #define MPI2_SAS_EXPAND_PGAD_HANDLE_MASK (0x0000FFFF) | ||
| 289 | #define MPI2_SAS_EXPAND_PGAD_PHYNUM_MASK (0x00FF0000) | ||
| 290 | #define MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT (16) | ||
| 291 | |||
| 292 | |||
| 293 | /* SAS Device PageAddress format */ | ||
| 294 | #define MPI2_SAS_DEVICE_PGAD_FORM_MASK (0xF0000000) | ||
| 295 | #define MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE (0x00000000) | ||
| 296 | #define MPI2_SAS_DEVICE_PGAD_FORM_HANDLE (0x20000000) | ||
| 297 | |||
| 298 | #define MPI2_SAS_DEVICE_PGAD_HANDLE_MASK (0x0000FFFF) | ||
| 299 | |||
| 300 | |||
| 301 | /* SAS PHY PageAddress format */ | ||
| 302 | #define MPI2_SAS_PHY_PGAD_FORM_MASK (0xF0000000) | ||
| 303 | #define MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER (0x00000000) | ||
| 304 | #define MPI2_SAS_PHY_PGAD_FORM_PHY_TBL_INDEX (0x10000000) | ||
| 305 | |||
| 306 | #define MPI2_SAS_PHY_PGAD_PHY_NUMBER_MASK (0x000000FF) | ||
| 307 | #define MPI2_SAS_PHY_PGAD_PHY_TBL_INDEX_MASK (0x0000FFFF) | ||
| 308 | |||
| 309 | |||
| 310 | /* SAS Port PageAddress format */ | ||
| 311 | #define MPI2_SASPORT_PGAD_FORM_MASK (0xF0000000) | ||
| 312 | #define MPI2_SASPORT_PGAD_FORM_GET_NEXT_PORT (0x00000000) | ||
| 313 | #define MPI2_SASPORT_PGAD_FORM_PORT_NUM (0x10000000) | ||
| 314 | |||
| 315 | #define MPI2_SASPORT_PGAD_PORTNUMBER_MASK (0x00000FFF) | ||
| 316 | |||
| 317 | |||
| 318 | /* SAS Enclosure PageAddress format */ | ||
| 319 | #define MPI2_SAS_ENCLOS_PGAD_FORM_MASK (0xF0000000) | ||
| 320 | #define MPI2_SAS_ENCLOS_PGAD_FORM_GET_NEXT_HANDLE (0x00000000) | ||
| 321 | #define MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE (0x10000000) | ||
| 322 | |||
| 323 | #define MPI2_SAS_ENCLOS_PGAD_HANDLE_MASK (0x0000FFFF) | ||
| 324 | |||
| 325 | |||
| 326 | /* RAID Configuration PageAddress format */ | ||
| 327 | #define MPI2_RAID_PGAD_FORM_MASK (0xF0000000) | ||
| 328 | #define MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM (0x00000000) | ||
| 329 | #define MPI2_RAID_PGAD_FORM_CONFIGNUM (0x10000000) | ||
| 330 | #define MPI2_RAID_PGAD_FORM_ACTIVE_CONFIG (0x20000000) | ||
| 331 | |||
| 332 | #define MPI2_RAID_PGAD_CONFIGNUM_MASK (0x000000FF) | ||
| 333 | |||
| 334 | |||
| 335 | /* Driver Persistent Mapping PageAddress format */ | ||
| 336 | #define MPI2_DPM_PGAD_FORM_MASK (0xF0000000) | ||
| 337 | #define MPI2_DPM_PGAD_FORM_ENTRY_RANGE (0x00000000) | ||
| 338 | |||
| 339 | #define MPI2_DPM_PGAD_ENTRY_COUNT_MASK (0x0FFF0000) | ||
| 340 | #define MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT (16) | ||
| 341 | #define MPI2_DPM_PGAD_START_ENTRY_MASK (0x0000FFFF) | ||
| 342 | |||
| 343 | |||
| 344 | /* Ethernet PageAddress format */ | ||
| 345 | #define MPI2_ETHERNET_PGAD_FORM_MASK (0xF0000000) | ||
| 346 | #define MPI2_ETHERNET_PGAD_FORM_IF_NUM (0x00000000) | ||
| 347 | |||
| 348 | #define MPI2_ETHERNET_PGAD_IF_NUMBER_MASK (0x000000FF) | ||
| 349 | |||
| 350 | |||
| 351 | |||
| 352 | /**************************************************************************** | ||
| 353 | * Configuration messages | ||
| 354 | ****************************************************************************/ | ||
| 355 | |||
| 356 | /* Configuration Request Message */ | ||
| 357 | typedef struct _MPI2_CONFIG_REQUEST | ||
| 358 | { | ||
| 359 | U8 Action; /* 0x00 */ | ||
| 360 | U8 SGLFlags; /* 0x01 */ | ||
| 361 | U8 ChainOffset; /* 0x02 */ | ||
| 362 | U8 Function; /* 0x03 */ | ||
| 363 | U16 ExtPageLength; /* 0x04 */ | ||
| 364 | U8 ExtPageType; /* 0x06 */ | ||
| 365 | U8 MsgFlags; /* 0x07 */ | ||
| 366 | U8 VP_ID; /* 0x08 */ | ||
| 367 | U8 VF_ID; /* 0x09 */ | ||
| 368 | U16 Reserved1; /* 0x0A */ | ||
| 369 | U8 Reserved2; /* 0x0C */ | ||
| 370 | U8 ProxyVF_ID; /* 0x0D */ | ||
| 371 | U16 Reserved4; /* 0x0E */ | ||
| 372 | U32 Reserved3; /* 0x10 */ | ||
| 373 | MPI2_CONFIG_PAGE_HEADER Header; /* 0x14 */ | ||
| 374 | U32 PageAddress; /* 0x18 */ | ||
| 375 | MPI2_SGE_IO_UNION PageBufferSGE; /* 0x1C */ | ||
| 376 | } MPI2_CONFIG_REQUEST, MPI2_POINTER PTR_MPI2_CONFIG_REQUEST, | ||
| 377 | Mpi2ConfigRequest_t, MPI2_POINTER pMpi2ConfigRequest_t; | ||
| 378 | |||
| 379 | /* values for the Action field */ | ||
| 380 | #define MPI2_CONFIG_ACTION_PAGE_HEADER (0x00) | ||
| 381 | #define MPI2_CONFIG_ACTION_PAGE_READ_CURRENT (0x01) | ||
| 382 | #define MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT (0x02) | ||
| 383 | #define MPI2_CONFIG_ACTION_PAGE_DEFAULT (0x03) | ||
| 384 | #define MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM (0x04) | ||
| 385 | #define MPI2_CONFIG_ACTION_PAGE_READ_DEFAULT (0x05) | ||
| 386 | #define MPI2_CONFIG_ACTION_PAGE_READ_NVRAM (0x06) | ||
| 387 | #define MPI2_CONFIG_ACTION_PAGE_GET_CHANGEABLE (0x07) | ||
| 388 | |||
| 389 | /* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */ | ||
| 390 | |||
| 391 | |||
| 392 | /* Config Reply Message */ | ||
| 393 | typedef struct _MPI2_CONFIG_REPLY | ||
| 394 | { | ||
| 395 | U8 Action; /* 0x00 */ | ||
| 396 | U8 SGLFlags; /* 0x01 */ | ||
| 397 | U8 MsgLength; /* 0x02 */ | ||
| 398 | U8 Function; /* 0x03 */ | ||
| 399 | U16 ExtPageLength; /* 0x04 */ | ||
| 400 | U8 ExtPageType; /* 0x06 */ | ||
| 401 | U8 MsgFlags; /* 0x07 */ | ||
| 402 | U8 VP_ID; /* 0x08 */ | ||
| 403 | U8 VF_ID; /* 0x09 */ | ||
| 404 | U16 Reserved1; /* 0x0A */ | ||
| 405 | U16 Reserved2; /* 0x0C */ | ||
| 406 | U16 IOCStatus; /* 0x0E */ | ||
| 407 | U32 IOCLogInfo; /* 0x10 */ | ||
| 408 | MPI2_CONFIG_PAGE_HEADER Header; /* 0x14 */ | ||
| 409 | } MPI2_CONFIG_REPLY, MPI2_POINTER PTR_MPI2_CONFIG_REPLY, | ||
| 410 | Mpi2ConfigReply_t, MPI2_POINTER pMpi2ConfigReply_t; | ||
| 411 | |||
| 412 | |||
| 413 | |||
| 414 | /***************************************************************************** | ||
| 415 | * | ||
| 416 | * C o n f i g u r a t i o n P a g e s | ||
| 417 | * | ||
| 418 | *****************************************************************************/ | ||
| 419 | |||
| 420 | /**************************************************************************** | ||
| 421 | * Manufacturing Config pages | ||
| 422 | ****************************************************************************/ | ||
| 423 | |||
| 424 | #define MPI2_MFGPAGE_VENDORID_LSI (0x1000) | ||
| 425 | |||
| 426 | /* SAS */ | ||
| 427 | #define MPI2_MFGPAGE_DEVID_SAS2004 (0x0070) | ||
| 428 | #define MPI2_MFGPAGE_DEVID_SAS2008 (0x0072) | ||
| 429 | #define MPI2_MFGPAGE_DEVID_SAS2108_1 (0x0074) | ||
| 430 | #define MPI2_MFGPAGE_DEVID_SAS2108_2 (0x0076) | ||
| 431 | #define MPI2_MFGPAGE_DEVID_SAS2108_3 (0x0077) | ||
| 432 | #define MPI2_MFGPAGE_DEVID_SAS2116_1 (0x0064) | ||
| 433 | #define MPI2_MFGPAGE_DEVID_SAS2116_2 (0x0065) | ||
| 434 | |||
| 435 | #define MPI2_MFGPAGE_DEVID_SSS6200 (0x007E) | ||
| 436 | |||
| 437 | #define MPI2_MFGPAGE_DEVID_SAS2208_1 (0x0080) | ||
| 438 | #define MPI2_MFGPAGE_DEVID_SAS2208_2 (0x0081) | ||
| 439 | #define MPI2_MFGPAGE_DEVID_SAS2208_3 (0x0082) | ||
| 440 | #define MPI2_MFGPAGE_DEVID_SAS2208_4 (0x0083) | ||
| 441 | #define MPI2_MFGPAGE_DEVID_SAS2208_5 (0x0084) | ||
| 442 | #define MPI2_MFGPAGE_DEVID_SAS2208_6 (0x0085) | ||
| 443 | #define MPI2_MFGPAGE_DEVID_SAS2308_1 (0x0086) | ||
| 444 | #define MPI2_MFGPAGE_DEVID_SAS2308_2 (0x0087) | ||
| 445 | #define MPI2_MFGPAGE_DEVID_SAS2308_3 (0x006E) | ||
| 446 | |||
| 447 | |||
| 448 | |||
| 449 | |||
| 450 | /* Manufacturing Page 0 */ | ||
| 451 | |||
| 452 | typedef struct _MPI2_CONFIG_PAGE_MAN_0 | ||
| 453 | { | ||
| 454 | MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ | ||
| 455 | U8 ChipName[16]; /* 0x04 */ | ||
| 456 | U8 ChipRevision[8]; /* 0x14 */ | ||
| 457 | U8 BoardName[16]; /* 0x1C */ | ||
| 458 | U8 BoardAssembly[16]; /* 0x2C */ | ||
| 459 | U8 BoardTracerNumber[16]; /* 0x3C */ | ||
| 460 | } MPI2_CONFIG_PAGE_MAN_0, | ||
| 461 | MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_0, | ||
| 462 | Mpi2ManufacturingPage0_t, MPI2_POINTER pMpi2ManufacturingPage0_t; | ||
| 463 | |||
| 464 | #define MPI2_MANUFACTURING0_PAGEVERSION (0x00) | ||
| 465 | |||
| 466 | |||
| 467 | /* Manufacturing Page 1 */ | ||
| 468 | |||
| 469 | typedef struct _MPI2_CONFIG_PAGE_MAN_1 | ||
| 470 | { | ||
| 471 | MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ | ||
| 472 | U8 VPD[256]; /* 0x04 */ | ||
| 473 | } MPI2_CONFIG_PAGE_MAN_1, | ||
| 474 | MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_1, | ||
| 475 | Mpi2ManufacturingPage1_t, MPI2_POINTER pMpi2ManufacturingPage1_t; | ||
| 476 | |||
| 477 | #define MPI2_MANUFACTURING1_PAGEVERSION (0x00) | ||
| 478 | |||
| 479 | |||
| 480 | typedef struct _MPI2_CHIP_REVISION_ID | ||
| 481 | { | ||
| 482 | U16 DeviceID; /* 0x00 */ | ||
| 483 | U8 PCIRevisionID; /* 0x02 */ | ||
| 484 | U8 Reserved; /* 0x03 */ | ||
| 485 | } MPI2_CHIP_REVISION_ID, MPI2_POINTER PTR_MPI2_CHIP_REVISION_ID, | ||
| 486 | Mpi2ChipRevisionId_t, MPI2_POINTER pMpi2ChipRevisionId_t; | ||
| 487 | |||
| 488 | |||
| 489 | /* Manufacturing Page 2 */ | ||
| 490 | |||
| 491 | /* | ||
| 492 | * Host code (drivers, BIOS, utilities, etc.) should leave this define set to | ||
| 493 | * one and check Header.PageLength at runtime. | ||
| 494 | */ | ||
| 495 | #ifndef MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS | ||
| 496 | #define MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS (1) | ||
| 497 | #endif | ||
| 498 | |||
| 499 | typedef struct _MPI2_CONFIG_PAGE_MAN_2 | ||
| 500 | { | ||
| 501 | MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ | ||
| 502 | MPI2_CHIP_REVISION_ID ChipId; /* 0x04 */ | ||
| 503 | U32 HwSettings[MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS];/* 0x08 */ | ||
| 504 | } MPI2_CONFIG_PAGE_MAN_2, | ||
| 505 | MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_2, | ||
| 506 | Mpi2ManufacturingPage2_t, MPI2_POINTER pMpi2ManufacturingPage2_t; | ||
| 507 | |||
| 508 | #define MPI2_MANUFACTURING2_PAGEVERSION (0x00) | ||
| 509 | |||
| 510 | |||
| 511 | /* Manufacturing Page 3 */ | ||
| 512 | |||
| 513 | /* | ||
| 514 | * Host code (drivers, BIOS, utilities, etc.) should leave this define set to | ||
| 515 | * one and check Header.PageLength at runtime. | ||
| 516 | */ | ||
| 517 | #ifndef MPI2_MAN_PAGE_3_INFO_WORDS | ||
| 518 | #define MPI2_MAN_PAGE_3_INFO_WORDS (1) | ||
| 519 | #endif | ||
| 520 | |||
| 521 | typedef struct _MPI2_CONFIG_PAGE_MAN_3 | ||
| 522 | { | ||
| 523 | MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ | ||
| 524 | MPI2_CHIP_REVISION_ID ChipId; /* 0x04 */ | ||
| 525 | U32 Info[MPI2_MAN_PAGE_3_INFO_WORDS];/* 0x08 */ | ||
| 526 | } MPI2_CONFIG_PAGE_MAN_3, | ||
| 527 | MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_3, | ||
| 528 | Mpi2ManufacturingPage3_t, MPI2_POINTER pMpi2ManufacturingPage3_t; | ||
| 529 | |||
| 530 | #define MPI2_MANUFACTURING3_PAGEVERSION (0x00) | ||
| 531 | |||
| 532 | |||
| 533 | /* Manufacturing Page 4 */ | ||
| 534 | |||
| 535 | typedef struct _MPI2_MANPAGE4_PWR_SAVE_SETTINGS | ||
| 536 | { | ||
| 537 | U8 PowerSaveFlags; /* 0x00 */ | ||
| 538 | U8 InternalOperationsSleepTime; /* 0x01 */ | ||
| 539 | U8 InternalOperationsRunTime; /* 0x02 */ | ||
| 540 | U8 HostIdleTime; /* 0x03 */ | ||
| 541 | } MPI2_MANPAGE4_PWR_SAVE_SETTINGS, | ||
| 542 | MPI2_POINTER PTR_MPI2_MANPAGE4_PWR_SAVE_SETTINGS, | ||
| 543 | Mpi2ManPage4PwrSaveSettings_t, MPI2_POINTER pMpi2ManPage4PwrSaveSettings_t; | ||
| 544 | |||
| 545 | /* defines for the PowerSaveFlags field */ | ||
| 546 | #define MPI2_MANPAGE4_MASK_POWERSAVE_MODE (0x03) | ||
| 547 | #define MPI2_MANPAGE4_POWERSAVE_MODE_DISABLED (0x00) | ||
| 548 | #define MPI2_MANPAGE4_CUSTOM_POWERSAVE_MODE (0x01) | ||
| 549 | #define MPI2_MANPAGE4_FULL_POWERSAVE_MODE (0x02) | ||
| 550 | |||
| 551 | typedef struct _MPI2_CONFIG_PAGE_MAN_4 | ||
| 552 | { | ||
| 553 | MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ | ||
| 554 | U32 Reserved1; /* 0x04 */ | ||
| 555 | U32 Flags; /* 0x08 */ | ||
| 556 | U8 InquirySize; /* 0x0C */ | ||
| 557 | U8 Reserved2; /* 0x0D */ | ||
| 558 | U16 Reserved3; /* 0x0E */ | ||
| 559 | U8 InquiryData[56]; /* 0x10 */ | ||
| 560 | U32 RAID0VolumeSettings; /* 0x48 */ | ||
| 561 | U32 RAID1EVolumeSettings; /* 0x4C */ | ||
| 562 | U32 RAID1VolumeSettings; /* 0x50 */ | ||
| 563 | U32 RAID10VolumeSettings; /* 0x54 */ | ||
| 564 | U32 Reserved4; /* 0x58 */ | ||
| 565 | U32 Reserved5; /* 0x5C */ | ||
| 566 | MPI2_MANPAGE4_PWR_SAVE_SETTINGS PowerSaveSettings; /* 0x60 */ | ||
| 567 | U8 MaxOCEDisks; /* 0x64 */ | ||
| 568 | U8 ResyncRate; /* 0x65 */ | ||
| 569 | U16 DataScrubDuration; /* 0x66 */ | ||
| 570 | U8 MaxHotSpares; /* 0x68 */ | ||
| 571 | U8 MaxPhysDisksPerVol; /* 0x69 */ | ||
| 572 | U8 MaxPhysDisks; /* 0x6A */ | ||
| 573 | U8 MaxVolumes; /* 0x6B */ | ||
| 574 | } MPI2_CONFIG_PAGE_MAN_4, | ||
| 575 | MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_4, | ||
| 576 | Mpi2ManufacturingPage4_t, MPI2_POINTER pMpi2ManufacturingPage4_t; | ||
| 577 | |||
| 578 | #define MPI2_MANUFACTURING4_PAGEVERSION (0x0A) | ||
| 579 | |||
| 580 | /* Manufacturing Page 4 Flags field */ | ||
| 581 | #define MPI2_MANPAGE4_METADATA_SIZE_MASK (0x00030000) | ||
| 582 | #define MPI2_MANPAGE4_METADATA_512MB (0x00000000) | ||
| 583 | |||
| 584 | #define MPI2_MANPAGE4_MIX_SSD_SAS_SATA (0x00008000) | ||
| 585 | #define MPI2_MANPAGE4_MIX_SSD_AND_NON_SSD (0x00004000) | ||
| 586 | #define MPI2_MANPAGE4_HIDE_PHYSDISK_NON_IR (0x00002000) | ||
| 587 | |||
| 588 | #define MPI2_MANPAGE4_MASK_PHYSDISK_COERCION (0x00001C00) | ||
| 589 | #define MPI2_MANPAGE4_PHYSDISK_COERCION_1GB (0x00000000) | ||
| 590 | #define MPI2_MANPAGE4_PHYSDISK_128MB_COERCION (0x00000400) | ||
| 591 | #define MPI2_MANPAGE4_PHYSDISK_ADAPTIVE_COERCION (0x00000800) | ||
| 592 | #define MPI2_MANPAGE4_PHYSDISK_ZERO_COERCION (0x00000C00) | ||
| 593 | |||
| 594 | #define MPI2_MANPAGE4_MASK_BAD_BLOCK_MARKING (0x00000300) | ||
| 595 | #define MPI2_MANPAGE4_DEFAULT_BAD_BLOCK_MARKING (0x00000000) | ||
| 596 | #define MPI2_MANPAGE4_TABLE_BAD_BLOCK_MARKING (0x00000100) | ||
| 597 | #define MPI2_MANPAGE4_WRITE_LONG_BAD_BLOCK_MARKING (0x00000200) | ||
| 598 | |||
| 599 | #define MPI2_MANPAGE4_FORCE_OFFLINE_FAILOVER (0x00000080) | ||
| 600 | #define MPI2_MANPAGE4_RAID10_DISABLE (0x00000040) | ||
| 601 | #define MPI2_MANPAGE4_RAID1E_DISABLE (0x00000020) | ||
| 602 | #define MPI2_MANPAGE4_RAID1_DISABLE (0x00000010) | ||
| 603 | #define MPI2_MANPAGE4_RAID0_DISABLE (0x00000008) | ||
| 604 | #define MPI2_MANPAGE4_IR_MODEPAGE8_DISABLE (0x00000004) | ||
| 605 | #define MPI2_MANPAGE4_IM_RESYNC_CACHE_ENABLE (0x00000002) | ||
| 606 | #define MPI2_MANPAGE4_IR_NO_MIX_SAS_SATA (0x00000001) | ||
| 607 | |||
| 608 | |||
| 609 | /* Manufacturing Page 5 */ | ||
| 610 | |||
| 611 | /* | ||
| 612 | * Host code (drivers, BIOS, utilities, etc.) should leave this define set to | ||
| 613 | * one and check the value returned for NumPhys at runtime. | ||
| 614 | */ | ||
| 615 | #ifndef MPI2_MAN_PAGE_5_PHY_ENTRIES | ||
| 616 | #define MPI2_MAN_PAGE_5_PHY_ENTRIES (1) | ||
| 617 | #endif | ||
| 618 | |||
| 619 | typedef struct _MPI2_MANUFACTURING5_ENTRY | ||
| 620 | { | ||
| 621 | U64 WWID; /* 0x00 */ | ||
| 622 | U64 DeviceName; /* 0x08 */ | ||
| 623 | } MPI2_MANUFACTURING5_ENTRY, MPI2_POINTER PTR_MPI2_MANUFACTURING5_ENTRY, | ||
| 624 | Mpi2Manufacturing5Entry_t, MPI2_POINTER pMpi2Manufacturing5Entry_t; | ||
| 625 | |||
| 626 | typedef struct _MPI2_CONFIG_PAGE_MAN_5 | ||
| 627 | { | ||
| 628 | MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ | ||
| 629 | U8 NumPhys; /* 0x04 */ | ||
| 630 | U8 Reserved1; /* 0x05 */ | ||
| 631 | U16 Reserved2; /* 0x06 */ | ||
| 632 | U32 Reserved3; /* 0x08 */ | ||
| 633 | U32 Reserved4; /* 0x0C */ | ||
| 634 | MPI2_MANUFACTURING5_ENTRY Phy[MPI2_MAN_PAGE_5_PHY_ENTRIES];/* 0x08 */ | ||
| 635 | } MPI2_CONFIG_PAGE_MAN_5, | ||
| 636 | MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_5, | ||
| 637 | Mpi2ManufacturingPage5_t, MPI2_POINTER pMpi2ManufacturingPage5_t; | ||
| 638 | |||
| 639 | #define MPI2_MANUFACTURING5_PAGEVERSION (0x03) | ||
| 640 | |||
| 641 | |||
| 642 | /* Manufacturing Page 6 */ | ||
| 643 | |||
| 644 | typedef struct _MPI2_CONFIG_PAGE_MAN_6 | ||
| 645 | { | ||
| 646 | MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ | ||
| 647 | U32 ProductSpecificInfo;/* 0x04 */ | ||
| 648 | } MPI2_CONFIG_PAGE_MAN_6, | ||
| 649 | MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_6, | ||
| 650 | Mpi2ManufacturingPage6_t, MPI2_POINTER pMpi2ManufacturingPage6_t; | ||
| 651 | |||
| 652 | #define MPI2_MANUFACTURING6_PAGEVERSION (0x00) | ||
| 653 | |||
| 654 | |||
| 655 | /* Manufacturing Page 7 */ | ||
| 656 | |||
| 657 | typedef struct _MPI2_MANPAGE7_CONNECTOR_INFO | ||
| 658 | { | ||
| 659 | U32 Pinout; /* 0x00 */ | ||
| 660 | U8 Connector[16]; /* 0x04 */ | ||
| 661 | U8 Location; /* 0x14 */ | ||
| 662 | U8 ReceptacleID; /* 0x15 */ | ||
| 663 | U16 Slot; /* 0x16 */ | ||
| 664 | U32 Reserved2; /* 0x18 */ | ||
| 665 | } MPI2_MANPAGE7_CONNECTOR_INFO, MPI2_POINTER PTR_MPI2_MANPAGE7_CONNECTOR_INFO, | ||
| 666 | Mpi2ManPage7ConnectorInfo_t, MPI2_POINTER pMpi2ManPage7ConnectorInfo_t; | ||
| 667 | |||
| 668 | /* defines for the Pinout field */ | ||
| 669 | #define MPI2_MANPAGE7_PINOUT_LANE_MASK (0x0000FF00) | ||
| 670 | #define MPI2_MANPAGE7_PINOUT_LANE_SHIFT (8) | ||
| 671 | |||
| 672 | #define MPI2_MANPAGE7_PINOUT_TYPE_MASK (0x000000FF) | ||
| 673 | #define MPI2_MANPAGE7_PINOUT_TYPE_UNKNOWN (0x00) | ||
| 674 | #define MPI2_MANPAGE7_PINOUT_SATA_SINGLE (0x01) | ||
| 675 | #define MPI2_MANPAGE7_PINOUT_SFF_8482 (0x02) | ||
| 676 | #define MPI2_MANPAGE7_PINOUT_SFF_8486 (0x03) | ||
| 677 | #define MPI2_MANPAGE7_PINOUT_SFF_8484 (0x04) | ||
| 678 | #define MPI2_MANPAGE7_PINOUT_SFF_8087 (0x05) | ||
| 679 | #define MPI2_MANPAGE7_PINOUT_SFF_8643_4I (0x06) | ||
| 680 | #define MPI2_MANPAGE7_PINOUT_SFF_8643_8I (0x07) | ||
| 681 | #define MPI2_MANPAGE7_PINOUT_SFF_8470 (0x08) | ||
| 682 | #define MPI2_MANPAGE7_PINOUT_SFF_8088 (0x09) | ||
| 683 | #define MPI2_MANPAGE7_PINOUT_SFF_8644_4X (0x0A) | ||
| 684 | #define MPI2_MANPAGE7_PINOUT_SFF_8644_8X (0x0B) | ||
| 685 | #define MPI2_MANPAGE7_PINOUT_SFF_8644_16X (0x0C) | ||
| 686 | #define MPI2_MANPAGE7_PINOUT_SFF_8436 (0x0D) | ||
| 687 | |||
| 688 | /* defines for the Location field */ | ||
| 689 | #define MPI2_MANPAGE7_LOCATION_UNKNOWN (0x01) | ||
| 690 | #define MPI2_MANPAGE7_LOCATION_INTERNAL (0x02) | ||
| 691 | #define MPI2_MANPAGE7_LOCATION_EXTERNAL (0x04) | ||
| 692 | #define MPI2_MANPAGE7_LOCATION_SWITCHABLE (0x08) | ||
| 693 | #define MPI2_MANPAGE7_LOCATION_AUTO (0x10) | ||
| 694 | #define MPI2_MANPAGE7_LOCATION_NOT_PRESENT (0x20) | ||
| 695 | #define MPI2_MANPAGE7_LOCATION_NOT_CONNECTED (0x80) | ||
| 696 | |||
| 697 | /* | ||
| 698 | * Host code (drivers, BIOS, utilities, etc.) should leave this define set to | ||
| 699 | * one and check the value returned for NumPhys at runtime. | ||
| 700 | */ | ||
| 701 | #ifndef MPI2_MANPAGE7_CONNECTOR_INFO_MAX | ||
| 702 | #define MPI2_MANPAGE7_CONNECTOR_INFO_MAX (1) | ||
| 703 | #endif | ||
| 704 | |||
| 705 | typedef struct _MPI2_CONFIG_PAGE_MAN_7 | ||
| 706 | { | ||
| 707 | MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ | ||
| 708 | U32 Reserved1; /* 0x04 */ | ||
| 709 | U32 Reserved2; /* 0x08 */ | ||
| 710 | U32 Flags; /* 0x0C */ | ||
| 711 | U8 EnclosureName[16]; /* 0x10 */ | ||
| 712 | U8 NumPhys; /* 0x20 */ | ||
| 713 | U8 Reserved3; /* 0x21 */ | ||
| 714 | U16 Reserved4; /* 0x22 */ | ||
| 715 | MPI2_MANPAGE7_CONNECTOR_INFO ConnectorInfo[MPI2_MANPAGE7_CONNECTOR_INFO_MAX]; /* 0x24 */ | ||
| 716 | } MPI2_CONFIG_PAGE_MAN_7, | ||
| 717 | MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_7, | ||
| 718 | Mpi2ManufacturingPage7_t, MPI2_POINTER pMpi2ManufacturingPage7_t; | ||
| 719 | |||
| 720 | #define MPI2_MANUFACTURING7_PAGEVERSION (0x01) | ||
| 721 | |||
| 722 | /* defines for the Flags field */ | ||
| 723 | #define MPI2_MANPAGE7_FLAG_BASE_ENCLOSURE_LEVEL (0x00000008) | ||
| 724 | #define MPI2_MANPAGE7_FLAG_EVENTREPLAY_SLOT_ORDER (0x00000002) | ||
| 725 | #define MPI2_MANPAGE7_FLAG_USE_SLOT_INFO (0x00000001) | ||
| 726 | |||
| 727 | |||
| 728 | /* | ||
| 729 | * Generic structure to use for product-specific manufacturing pages | ||
| 730 | * (currently Manufacturing Page 8 through Manufacturing Page 31). | ||
| 731 | */ | ||
| 732 | |||
| 733 | typedef struct _MPI2_CONFIG_PAGE_MAN_PS | ||
| 734 | { | ||
| 735 | MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ | ||
| 736 | U32 ProductSpecificInfo;/* 0x04 */ | ||
| 737 | } MPI2_CONFIG_PAGE_MAN_PS, | ||
| 738 | MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_PS, | ||
| 739 | Mpi2ManufacturingPagePS_t, MPI2_POINTER pMpi2ManufacturingPagePS_t; | ||
| 740 | |||
| 741 | #define MPI2_MANUFACTURING8_PAGEVERSION (0x00) | ||
| 742 | #define MPI2_MANUFACTURING9_PAGEVERSION (0x00) | ||
| 743 | #define MPI2_MANUFACTURING10_PAGEVERSION (0x00) | ||
| 744 | #define MPI2_MANUFACTURING11_PAGEVERSION (0x00) | ||
| 745 | #define MPI2_MANUFACTURING12_PAGEVERSION (0x00) | ||
| 746 | #define MPI2_MANUFACTURING13_PAGEVERSION (0x00) | ||
| 747 | #define MPI2_MANUFACTURING14_PAGEVERSION (0x00) | ||
| 748 | #define MPI2_MANUFACTURING15_PAGEVERSION (0x00) | ||
| 749 | #define MPI2_MANUFACTURING16_PAGEVERSION (0x00) | ||
| 750 | #define MPI2_MANUFACTURING17_PAGEVERSION (0x00) | ||
| 751 | #define MPI2_MANUFACTURING18_PAGEVERSION (0x00) | ||
| 752 | #define MPI2_MANUFACTURING19_PAGEVERSION (0x00) | ||
| 753 | #define MPI2_MANUFACTURING20_PAGEVERSION (0x00) | ||
| 754 | #define MPI2_MANUFACTURING21_PAGEVERSION (0x00) | ||
| 755 | #define MPI2_MANUFACTURING22_PAGEVERSION (0x00) | ||
| 756 | #define MPI2_MANUFACTURING23_PAGEVERSION (0x00) | ||
| 757 | #define MPI2_MANUFACTURING24_PAGEVERSION (0x00) | ||
| 758 | #define MPI2_MANUFACTURING25_PAGEVERSION (0x00) | ||
| 759 | #define MPI2_MANUFACTURING26_PAGEVERSION (0x00) | ||
| 760 | #define MPI2_MANUFACTURING27_PAGEVERSION (0x00) | ||
| 761 | #define MPI2_MANUFACTURING28_PAGEVERSION (0x00) | ||
| 762 | #define MPI2_MANUFACTURING29_PAGEVERSION (0x00) | ||
| 763 | #define MPI2_MANUFACTURING30_PAGEVERSION (0x00) | ||
| 764 | #define MPI2_MANUFACTURING31_PAGEVERSION (0x00) | ||
| 765 | |||
| 766 | |||
| 767 | /**************************************************************************** | ||
| 768 | * IO Unit Config Pages | ||
| 769 | ****************************************************************************/ | ||
| 770 | |||
| 771 | /* IO Unit Page 0 */ | ||
| 772 | |||
| 773 | typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_0 | ||
| 774 | { | ||
| 775 | MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ | ||
| 776 | U64 UniqueValue; /* 0x04 */ | ||
| 777 | MPI2_VERSION_UNION NvdataVersionDefault; /* 0x08 */ | ||
| 778 | MPI2_VERSION_UNION NvdataVersionPersistent; /* 0x0A */ | ||
| 779 | } MPI2_CONFIG_PAGE_IO_UNIT_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_0, | ||
| 780 | Mpi2IOUnitPage0_t, MPI2_POINTER pMpi2IOUnitPage0_t; | ||
| 781 | |||
| 782 | #define MPI2_IOUNITPAGE0_PAGEVERSION (0x02) | ||
| 783 | |||
| 784 | |||
| 785 | /* IO Unit Page 1 */ | ||
| 786 | |||
| 787 | typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_1 | ||
| 788 | { | ||
| 789 | MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ | ||
| 790 | U32 Flags; /* 0x04 */ | ||
| 791 | } MPI2_CONFIG_PAGE_IO_UNIT_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_1, | ||
| 792 | Mpi2IOUnitPage1_t, MPI2_POINTER pMpi2IOUnitPage1_t; | ||
| 793 | |||
| 794 | #define MPI2_IOUNITPAGE1_PAGEVERSION (0x04) | ||
| 795 | |||
| 796 | /* IO Unit Page 1 Flags defines */ | ||
| 797 | #define MPI2_IOUNITPAGE1_ATA_SECURITY_FREEZE_LOCK (0x00004000) | ||
| 798 | #define MPI2_IOUNITPAGE1_ENABLE_HOST_BASED_DISCOVERY (0x00000800) | ||
| 799 | #define MPI2_IOUNITPAGE1_MASK_SATA_WRITE_CACHE (0x00000600) | ||
| 800 | #define MPI2_IOUNITPAGE1_SATA_WRITE_CACHE_SHIFT (9) | ||
| 801 | #define MPI2_IOUNITPAGE1_ENABLE_SATA_WRITE_CACHE (0x00000000) | ||
| 802 | #define MPI2_IOUNITPAGE1_DISABLE_SATA_WRITE_CACHE (0x00000200) | ||
| 803 | #define MPI2_IOUNITPAGE1_UNCHANGED_SATA_WRITE_CACHE (0x00000400) | ||
| 804 | #define MPI2_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE (0x00000100) | ||
| 805 | #define MPI2_IOUNITPAGE1_DISABLE_IR (0x00000040) | ||
| 806 | #define MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING (0x00000020) | ||
| 807 | #define MPI2_IOUNITPAGE1_IR_USE_STATIC_VOLUME_ID (0x00000004) | ||
| 808 | |||
| 809 | |||
| 810 | /* IO Unit Page 3 */ | ||
| 811 | |||
| 812 | /* | ||
| 813 | * Host code (drivers, BIOS, utilities, etc.) should leave this define set to | ||
| 814 | * one and check the value returned for GPIOCount at runtime. | ||
| 815 | */ | ||
| 816 | #ifndef MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX | ||
| 817 | #define MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX (1) | ||
| 818 | #endif | ||
| 819 | |||
| 820 | typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_3 | ||
| 821 | { | ||
| 822 | MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ | ||
| 823 | U8 GPIOCount; /* 0x04 */ | ||
| 824 | U8 Reserved1; /* 0x05 */ | ||
| 825 | U16 Reserved2; /* 0x06 */ | ||
| 826 | U16 GPIOVal[MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX];/* 0x08 */ | ||
| 827 | } MPI2_CONFIG_PAGE_IO_UNIT_3, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_3, | ||
| 828 | Mpi2IOUnitPage3_t, MPI2_POINTER pMpi2IOUnitPage3_t; | ||
| 829 | |||
| 830 | #define MPI2_IOUNITPAGE3_PAGEVERSION (0x01) | ||
| 831 | |||
| 832 | /* defines for IO Unit Page 3 GPIOVal field */ | ||
| 833 | #define MPI2_IOUNITPAGE3_GPIO_FUNCTION_MASK (0xFFFC) | ||
| 834 | #define MPI2_IOUNITPAGE3_GPIO_FUNCTION_SHIFT (2) | ||
| 835 | #define MPI2_IOUNITPAGE3_GPIO_SETTING_OFF (0x0000) | ||
| 836 | #define MPI2_IOUNITPAGE3_GPIO_SETTING_ON (0x0001) | ||
| 837 | |||
| 838 | |||
| 839 | /* IO Unit Page 5 */ | ||
| 840 | |||
| 841 | /* | ||
| 842 | * Upper layer code (drivers, utilities, etc.) should leave this define set to | ||
| 843 | * one and check the value returned for NumDmaEngines at runtime. | ||
| 844 | */ | ||
| 845 | #ifndef MPI2_IOUNITPAGE5_DMAENGINE_ENTRIES | ||
| 846 | #define MPI2_IOUNITPAGE5_DMAENGINE_ENTRIES (1) | ||
| 847 | #endif | ||
| 848 | |||
| 849 | typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_5 { | ||
| 850 | MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ | ||
| 851 | U64 RaidAcceleratorBufferBaseAddress; /* 0x04 */ | ||
| 852 | U64 RaidAcceleratorBufferSize; /* 0x0C */ | ||
| 853 | U64 RaidAcceleratorControlBaseAddress; /* 0x14 */ | ||
| 854 | U8 RAControlSize; /* 0x1C */ | ||
| 855 | U8 NumDmaEngines; /* 0x1D */ | ||
| 856 | U8 RAMinControlSize; /* 0x1E */ | ||
| 857 | U8 RAMaxControlSize; /* 0x1F */ | ||
| 858 | U32 Reserved1; /* 0x20 */ | ||
| 859 | U32 Reserved2; /* 0x24 */ | ||
| 860 | U32 Reserved3; /* 0x28 */ | ||
| 861 | U32 DmaEngineCapabilities | ||
| 862 | [MPI2_IOUNITPAGE5_DMAENGINE_ENTRIES]; /* 0x2C */ | ||
| 863 | } MPI2_CONFIG_PAGE_IO_UNIT_5, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_5, | ||
| 864 | Mpi2IOUnitPage5_t, MPI2_POINTER pMpi2IOUnitPage5_t; | ||
| 865 | |||
| 866 | #define MPI2_IOUNITPAGE5_PAGEVERSION (0x00) | ||
| 867 | |||
| 868 | /* defines for IO Unit Page 5 DmaEngineCapabilities field */ | ||
| 869 | #define MPI2_IOUNITPAGE5_DMA_CAP_MASK_MAX_REQUESTS (0xFFFF0000) | ||
| 870 | #define MPI2_IOUNITPAGE5_DMA_CAP_SHIFT_MAX_REQUESTS (16) | ||
| 871 | |||
| 872 | #define MPI2_IOUNITPAGE5_DMA_CAP_EEDP (0x0008) | ||
| 873 | #define MPI2_IOUNITPAGE5_DMA_CAP_PARITY_GENERATION (0x0004) | ||
| 874 | #define MPI2_IOUNITPAGE5_DMA_CAP_HASHING (0x0002) | ||
| 875 | #define MPI2_IOUNITPAGE5_DMA_CAP_ENCRYPTION (0x0001) | ||
| 876 | |||
| 877 | |||
| 878 | /* IO Unit Page 6 */ | ||
| 879 | |||
| 880 | typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_6 { | ||
| 881 | MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ | ||
| 882 | U16 Flags; /* 0x04 */ | ||
| 883 | U8 RAHostControlSize; /* 0x06 */ | ||
| 884 | U8 Reserved0; /* 0x07 */ | ||
| 885 | U64 RaidAcceleratorHostControlBaseAddress; /* 0x08 */ | ||
| 886 | U32 Reserved1; /* 0x10 */ | ||
| 887 | U32 Reserved2; /* 0x14 */ | ||
| 888 | U32 Reserved3; /* 0x18 */ | ||
| 889 | } MPI2_CONFIG_PAGE_IO_UNIT_6, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_6, | ||
| 890 | Mpi2IOUnitPage6_t, MPI2_POINTER pMpi2IOUnitPage6_t; | ||
| 891 | |||
| 892 | #define MPI2_IOUNITPAGE6_PAGEVERSION (0x00) | ||
| 893 | |||
| 894 | /* defines for IO Unit Page 6 Flags field */ | ||
| 895 | #define MPI2_IOUNITPAGE6_FLAGS_ENABLE_RAID_ACCELERATOR (0x0001) | ||
| 896 | |||
| 897 | |||
| 898 | /* IO Unit Page 7 */ | ||
| 899 | |||
| 900 | typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_7 { | ||
| 901 | MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ | ||
| 902 | U16 Reserved1; /* 0x04 */ | ||
| 903 | U8 PCIeWidth; /* 0x06 */ | ||
| 904 | U8 PCIeSpeed; /* 0x07 */ | ||
| 905 | U32 ProcessorState; /* 0x08 */ | ||
| 906 | U32 PowerManagementCapabilities; /* 0x0C */ | ||
| 907 | U16 IOCTemperature; /* 0x10 */ | ||
| 908 | U8 IOCTemperatureUnits; /* 0x12 */ | ||
| 909 | U8 IOCSpeed; /* 0x13 */ | ||
| 910 | U16 BoardTemperature; /* 0x14 */ | ||
| 911 | U8 BoardTemperatureUnits; /* 0x16 */ | ||
| 912 | U8 Reserved3; /* 0x17 */ | ||
| 913 | U32 Reserved4; /* 0x18 */ | ||
| 914 | U32 Reserved5; /* 0x1C */ | ||
| 915 | U32 Reserved6; /* 0x20 */ | ||
| 916 | U32 Reserved7; /* 0x24 */ | ||
| 917 | } MPI2_CONFIG_PAGE_IO_UNIT_7, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_7, | ||
| 918 | Mpi2IOUnitPage7_t, MPI2_POINTER pMpi2IOUnitPage7_t; | ||
| 919 | |||
| 920 | #define MPI2_IOUNITPAGE7_PAGEVERSION (0x04) | ||
| 921 | |||
| 922 | /* defines for IO Unit Page 7 PCIeWidth field */ | ||
| 923 | #define MPI2_IOUNITPAGE7_PCIE_WIDTH_X1 (0x01) | ||
| 924 | #define MPI2_IOUNITPAGE7_PCIE_WIDTH_X2 (0x02) | ||
| 925 | #define MPI2_IOUNITPAGE7_PCIE_WIDTH_X4 (0x04) | ||
| 926 | #define MPI2_IOUNITPAGE7_PCIE_WIDTH_X8 (0x08) | ||
| 927 | |||
| 928 | /* defines for IO Unit Page 7 PCIeSpeed field */ | ||
| 929 | #define MPI2_IOUNITPAGE7_PCIE_SPEED_2_5_GBPS (0x00) | ||
| 930 | #define MPI2_IOUNITPAGE7_PCIE_SPEED_5_0_GBPS (0x01) | ||
| 931 | #define MPI2_IOUNITPAGE7_PCIE_SPEED_8_0_GBPS (0x02) | ||
| 932 | |||
| 933 | /* defines for IO Unit Page 7 ProcessorState field */ | ||
| 934 | #define MPI2_IOUNITPAGE7_PSTATE_MASK_SECOND (0x0000000F) | ||
| 935 | #define MPI2_IOUNITPAGE7_PSTATE_SHIFT_SECOND (0) | ||
| 936 | |||
| 937 | #define MPI2_IOUNITPAGE7_PSTATE_NOT_PRESENT (0x00) | ||
| 938 | #define MPI2_IOUNITPAGE7_PSTATE_DISABLED (0x01) | ||
| 939 | #define MPI2_IOUNITPAGE7_PSTATE_ENABLED (0x02) | ||
| 940 | |||
| 941 | /* defines for IO Unit Page 7 PowerManagementCapabilities field */ | ||
| 942 | #define MPI2_IOUNITPAGE7_PMCAP_12_5_PCT_IOCSPEED (0x00000400) | ||
| 943 | #define MPI2_IOUNITPAGE7_PMCAP_25_0_PCT_IOCSPEED (0x00000200) | ||
| 944 | #define MPI2_IOUNITPAGE7_PMCAP_50_0_PCT_IOCSPEED (0x00000100) | ||
| 945 | #define MPI2_IOUNITPAGE7_PMCAP_PCIE_WIDTH_CHANGE (0x00000008) /* obsolete */ | ||
| 946 | #define MPI2_IOUNITPAGE7_PMCAP_PCIE_SPEED_CHANGE (0x00000004) /* obsolete */ | ||
| 947 | |||
| 948 | /* defines for IO Unit Page 7 IOCTemperatureUnits field */ | ||
| 949 | #define MPI2_IOUNITPAGE7_IOC_TEMP_NOT_PRESENT (0x00) | ||
| 950 | #define MPI2_IOUNITPAGE7_IOC_TEMP_FAHRENHEIT (0x01) | ||
| 951 | #define MPI2_IOUNITPAGE7_IOC_TEMP_CELSIUS (0x02) | ||
| 952 | |||
| 953 | /* defines for IO Unit Page 7 IOCSpeed field */ | ||
| 954 | #define MPI2_IOUNITPAGE7_IOC_SPEED_FULL (0x01) | ||
| 955 | #define MPI2_IOUNITPAGE7_IOC_SPEED_HALF (0x02) | ||
| 956 | #define MPI2_IOUNITPAGE7_IOC_SPEED_QUARTER (0x04) | ||
| 957 | #define MPI2_IOUNITPAGE7_IOC_SPEED_EIGHTH (0x08) | ||
| 958 | |||
| 959 | /* defines for IO Unit Page 7 BoardTemperatureUnits field */ | ||
| 960 | #define MPI2_IOUNITPAGE7_BOARD_TEMP_NOT_PRESENT (0x00) | ||
| 961 | #define MPI2_IOUNITPAGE7_BOARD_TEMP_FAHRENHEIT (0x01) | ||
| 962 | #define MPI2_IOUNITPAGE7_BOARD_TEMP_CELSIUS (0x02) | ||
| 963 | |||
| 964 | /* IO Unit Page 8 */ | ||
| 965 | |||
| 966 | #define MPI2_IOUNIT8_NUM_THRESHOLDS (4) | ||
| 967 | |||
| 968 | typedef struct _MPI2_IOUNIT8_SENSOR { | ||
| 969 | U16 Flags; /* 0x00 */ | ||
| 970 | U16 Reserved1; /* 0x02 */ | ||
| 971 | U16 | ||
| 972 | Threshold[MPI2_IOUNIT8_NUM_THRESHOLDS]; /* 0x04 */ | ||
| 973 | U32 Reserved2; /* 0x0C */ | ||
| 974 | U32 Reserved3; /* 0x10 */ | ||
| 975 | U32 Reserved4; /* 0x14 */ | ||
| 976 | } MPI2_IOUNIT8_SENSOR, MPI2_POINTER PTR_MPI2_IOUNIT8_SENSOR, | ||
| 977 | Mpi2IOUnit8Sensor_t, MPI2_POINTER pMpi2IOUnit8Sensor_t; | ||
| 978 | |||
| 979 | /* defines for IO Unit Page 8 Sensor Flags field */ | ||
| 980 | #define MPI2_IOUNIT8_SENSOR_FLAGS_T3_ENABLE (0x0008) | ||
| 981 | #define MPI2_IOUNIT8_SENSOR_FLAGS_T2_ENABLE (0x0004) | ||
| 982 | #define MPI2_IOUNIT8_SENSOR_FLAGS_T1_ENABLE (0x0002) | ||
| 983 | #define MPI2_IOUNIT8_SENSOR_FLAGS_T0_ENABLE (0x0001) | ||
| 984 | |||
| 985 | /* | ||
| 986 | * Host code (drivers, BIOS, utilities, etc.) should leave this define set to | ||
| 987 | * one and check the value returned for NumSensors at runtime. | ||
| 988 | */ | ||
| 989 | #ifndef MPI2_IOUNITPAGE8_SENSOR_ENTRIES | ||
| 990 | #define MPI2_IOUNITPAGE8_SENSOR_ENTRIES (1) | ||
| 991 | #endif | ||
| 992 | |||
| 993 | typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_8 { | ||
| 994 | MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ | ||
| 995 | U32 Reserved1; /* 0x04 */ | ||
| 996 | U32 Reserved2; /* 0x08 */ | ||
| 997 | U8 NumSensors; /* 0x0C */ | ||
| 998 | U8 PollingInterval; /* 0x0D */ | ||
| 999 | U16 Reserved3; /* 0x0E */ | ||
| 1000 | MPI2_IOUNIT8_SENSOR | ||
| 1001 | Sensor[MPI2_IOUNITPAGE8_SENSOR_ENTRIES];/* 0x10 */ | ||
| 1002 | } MPI2_CONFIG_PAGE_IO_UNIT_8, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_8, | ||
| 1003 | Mpi2IOUnitPage8_t, MPI2_POINTER pMpi2IOUnitPage8_t; | ||
| 1004 | |||
| 1005 | #define MPI2_IOUNITPAGE8_PAGEVERSION (0x00) | ||
| 1006 | |||
| 1007 | |||
| 1008 | /* IO Unit Page 9 */ | ||
| 1009 | |||
| 1010 | typedef struct _MPI2_IOUNIT9_SENSOR { | ||
| 1011 | U16 CurrentTemperature; /* 0x00 */ | ||
| 1012 | U16 Reserved1; /* 0x02 */ | ||
| 1013 | U8 Flags; /* 0x04 */ | ||
| 1014 | U8 Reserved2; /* 0x05 */ | ||
| 1015 | U16 Reserved3; /* 0x06 */ | ||
| 1016 | U32 Reserved4; /* 0x08 */ | ||
| 1017 | U32 Reserved5; /* 0x0C */ | ||
| 1018 | } MPI2_IOUNIT9_SENSOR, MPI2_POINTER PTR_MPI2_IOUNIT9_SENSOR, | ||
| 1019 | Mpi2IOUnit9Sensor_t, MPI2_POINTER pMpi2IOUnit9Sensor_t; | ||
| 1020 | |||
| 1021 | /* defines for IO Unit Page 9 Sensor Flags field */ | ||
| 1022 | #define MPI2_IOUNIT9_SENSOR_FLAGS_TEMP_VALID (0x01) | ||
| 1023 | |||
| 1024 | /* | ||
| 1025 | * Host code (drivers, BIOS, utilities, etc.) should leave this define set to | ||
| 1026 | * one and check the value returned for NumSensors at runtime. | ||
| 1027 | */ | ||
| 1028 | #ifndef MPI2_IOUNITPAGE9_SENSOR_ENTRIES | ||
| 1029 | #define MPI2_IOUNITPAGE9_SENSOR_ENTRIES (1) | ||
| 1030 | #endif | ||
| 1031 | |||
| 1032 | typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_9 { | ||
| 1033 | MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ | ||
| 1034 | U32 Reserved1; /* 0x04 */ | ||
| 1035 | U32 Reserved2; /* 0x08 */ | ||
| 1036 | U8 NumSensors; /* 0x0C */ | ||
| 1037 | U8 Reserved4; /* 0x0D */ | ||
| 1038 | U16 Reserved3; /* 0x0E */ | ||
| 1039 | MPI2_IOUNIT9_SENSOR | ||
| 1040 | Sensor[MPI2_IOUNITPAGE9_SENSOR_ENTRIES];/* 0x10 */ | ||
| 1041 | } MPI2_CONFIG_PAGE_IO_UNIT_9, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_9, | ||
| 1042 | Mpi2IOUnitPage9_t, MPI2_POINTER pMpi2IOUnitPage9_t; | ||
| 1043 | |||
| 1044 | #define MPI2_IOUNITPAGE9_PAGEVERSION (0x00) | ||
| 1045 | |||
| 1046 | |||
| 1047 | /* IO Unit Page 10 */ | ||
| 1048 | |||
| 1049 | typedef struct _MPI2_IOUNIT10_FUNCTION { | ||
| 1050 | U8 CreditPercent; /* 0x00 */ | ||
| 1051 | U8 Reserved1; /* 0x01 */ | ||
| 1052 | U16 Reserved2; /* 0x02 */ | ||
| 1053 | } MPI2_IOUNIT10_FUNCTION, MPI2_POINTER PTR_MPI2_IOUNIT10_FUNCTION, | ||
| 1054 | Mpi2IOUnit10Function_t, MPI2_POINTER pMpi2IOUnit10Function_t; | ||
| 1055 | |||
| 1056 | /* | ||
| 1057 | * Host code (drivers, BIOS, utilities, etc.) should leave this define set to | ||
| 1058 | * one and check the value returned for NumFunctions at runtime. | ||
| 1059 | */ | ||
| 1060 | #ifndef MPI2_IOUNITPAGE10_FUNCTION_ENTRIES | ||
| 1061 | #define MPI2_IOUNITPAGE10_FUNCTION_ENTRIES (1) | ||
| 1062 | #endif | ||
| 1063 | |||
| 1064 | typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_10 { | ||
| 1065 | MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ | ||
| 1066 | U8 NumFunctions; /* 0x04 */ | ||
| 1067 | U8 Reserved1; /* 0x05 */ | ||
| 1068 | U16 Reserved2; /* 0x06 */ | ||
| 1069 | U32 Reserved3; /* 0x08 */ | ||
| 1070 | U32 Reserved4; /* 0x0C */ | ||
| 1071 | MPI2_IOUNIT10_FUNCTION | ||
| 1072 | Function[MPI2_IOUNITPAGE10_FUNCTION_ENTRIES];/* 0x10 */ | ||
| 1073 | } MPI2_CONFIG_PAGE_IO_UNIT_10, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_10, | ||
| 1074 | Mpi2IOUnitPage10_t, MPI2_POINTER pMpi2IOUnitPage10_t; | ||
| 1075 | |||
| 1076 | #define MPI2_IOUNITPAGE10_PAGEVERSION (0x01) | ||
| 1077 | |||
| 1078 | |||
| 1079 | |||
| 1080 | /**************************************************************************** | ||
| 1081 | * IOC Config Pages | ||
| 1082 | ****************************************************************************/ | ||
| 1083 | |||
| 1084 | /* IOC Page 0 */ | ||
| 1085 | |||
| 1086 | typedef struct _MPI2_CONFIG_PAGE_IOC_0 | ||
| 1087 | { | ||
| 1088 | MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ | ||
| 1089 | U32 Reserved1; /* 0x04 */ | ||
| 1090 | U32 Reserved2; /* 0x08 */ | ||
| 1091 | U16 VendorID; /* 0x0C */ | ||
| 1092 | U16 DeviceID; /* 0x0E */ | ||
| 1093 | U8 RevisionID; /* 0x10 */ | ||
| 1094 | U8 Reserved3; /* 0x11 */ | ||
| 1095 | U16 Reserved4; /* 0x12 */ | ||
| 1096 | U32 ClassCode; /* 0x14 */ | ||
| 1097 | U16 SubsystemVendorID; /* 0x18 */ | ||
| 1098 | U16 SubsystemID; /* 0x1A */ | ||
| 1099 | } MPI2_CONFIG_PAGE_IOC_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_0, | ||
| 1100 | Mpi2IOCPage0_t, MPI2_POINTER pMpi2IOCPage0_t; | ||
| 1101 | |||
| 1102 | #define MPI2_IOCPAGE0_PAGEVERSION (0x02) | ||
| 1103 | |||
| 1104 | |||
| 1105 | /* IOC Page 1 */ | ||
| 1106 | |||
| 1107 | typedef struct _MPI2_CONFIG_PAGE_IOC_1 | ||
| 1108 | { | ||
| 1109 | MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ | ||
| 1110 | U32 Flags; /* 0x04 */ | ||
| 1111 | U32 CoalescingTimeout; /* 0x08 */ | ||
| 1112 | U8 CoalescingDepth; /* 0x0C */ | ||
| 1113 | U8 PCISlotNum; /* 0x0D */ | ||
| 1114 | U8 PCIBusNum; /* 0x0E */ | ||
| 1115 | U8 PCIDomainSegment; /* 0x0F */ | ||
| 1116 | U32 Reserved1; /* 0x10 */ | ||
| 1117 | U32 Reserved2; /* 0x14 */ | ||
| 1118 | } MPI2_CONFIG_PAGE_IOC_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_1, | ||
| 1119 | Mpi2IOCPage1_t, MPI2_POINTER pMpi2IOCPage1_t; | ||
| 1120 | |||
| 1121 | #define MPI2_IOCPAGE1_PAGEVERSION (0x05) | ||
| 1122 | |||
| 1123 | /* defines for IOC Page 1 Flags field */ | ||
| 1124 | #define MPI2_IOCPAGE1_REPLY_COALESCING (0x00000001) | ||
| 1125 | |||
| 1126 | #define MPI2_IOCPAGE1_PCISLOTNUM_UNKNOWN (0xFF) | ||
| 1127 | #define MPI2_IOCPAGE1_PCIBUSNUM_UNKNOWN (0xFF) | ||
| 1128 | #define MPI2_IOCPAGE1_PCIDOMAIN_UNKNOWN (0xFF) | ||
| 1129 | |||
| 1130 | /* IOC Page 6 */ | ||
| 1131 | |||
| 1132 | typedef struct _MPI2_CONFIG_PAGE_IOC_6 | ||
| 1133 | { | ||
| 1134 | MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ | ||
| 1135 | U32 CapabilitiesFlags; /* 0x04 */ | ||
| 1136 | U8 MaxDrivesRAID0; /* 0x08 */ | ||
| 1137 | U8 MaxDrivesRAID1; /* 0x09 */ | ||
| 1138 | U8 MaxDrivesRAID1E; /* 0x0A */ | ||
| 1139 | U8 MaxDrivesRAID10; /* 0x0B */ | ||
| 1140 | U8 MinDrivesRAID0; /* 0x0C */ | ||
| 1141 | U8 MinDrivesRAID1; /* 0x0D */ | ||
| 1142 | U8 MinDrivesRAID1E; /* 0x0E */ | ||
| 1143 | U8 MinDrivesRAID10; /* 0x0F */ | ||
| 1144 | U32 Reserved1; /* 0x10 */ | ||
| 1145 | U8 MaxGlobalHotSpares; /* 0x14 */ | ||
| 1146 | U8 MaxPhysDisks; /* 0x15 */ | ||
| 1147 | U8 MaxVolumes; /* 0x16 */ | ||
| 1148 | U8 MaxConfigs; /* 0x17 */ | ||
| 1149 | U8 MaxOCEDisks; /* 0x18 */ | ||
| 1150 | U8 Reserved2; /* 0x19 */ | ||
| 1151 | U16 Reserved3; /* 0x1A */ | ||
| 1152 | U32 SupportedStripeSizeMapRAID0; /* 0x1C */ | ||
| 1153 | U32 SupportedStripeSizeMapRAID1E; /* 0x20 */ | ||
| 1154 | U32 SupportedStripeSizeMapRAID10; /* 0x24 */ | ||
| 1155 | U32 Reserved4; /* 0x28 */ | ||
| 1156 | U32 Reserved5; /* 0x2C */ | ||
| 1157 | U16 DefaultMetadataSize; /* 0x30 */ | ||
| 1158 | U16 Reserved6; /* 0x32 */ | ||
| 1159 | U16 MaxBadBlockTableEntries; /* 0x34 */ | ||
| 1160 | U16 Reserved7; /* 0x36 */ | ||
| 1161 | U32 IRNvsramVersion; /* 0x38 */ | ||
| 1162 | } MPI2_CONFIG_PAGE_IOC_6, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_6, | ||
| 1163 | Mpi2IOCPage6_t, MPI2_POINTER pMpi2IOCPage6_t; | ||
| 1164 | |||
| 1165 | #define MPI2_IOCPAGE6_PAGEVERSION (0x05) | ||
| 1166 | |||
| 1167 | /* defines for IOC Page 6 CapabilitiesFlags */ | ||
| 1168 | #define MPI2_IOCPAGE6_CAP_FLAGS_4K_SECTORS_SUPPORT (0x00000020) | ||
| 1169 | #define MPI2_IOCPAGE6_CAP_FLAGS_RAID10_SUPPORT (0x00000010) | ||
| 1170 | #define MPI2_IOCPAGE6_CAP_FLAGS_RAID1_SUPPORT (0x00000008) | ||
| 1171 | #define MPI2_IOCPAGE6_CAP_FLAGS_RAID1E_SUPPORT (0x00000004) | ||
| 1172 | #define MPI2_IOCPAGE6_CAP_FLAGS_RAID0_SUPPORT (0x00000002) | ||
| 1173 | #define MPI2_IOCPAGE6_CAP_FLAGS_GLOBAL_HOT_SPARE (0x00000001) | ||
| 1174 | |||
| 1175 | |||
| 1176 | /* IOC Page 7 */ | ||
| 1177 | |||
| 1178 | #define MPI2_IOCPAGE7_EVENTMASK_WORDS (4) | ||
| 1179 | |||
| 1180 | typedef struct _MPI2_CONFIG_PAGE_IOC_7 | ||
| 1181 | { | ||
| 1182 | MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ | ||
| 1183 | U32 Reserved1; /* 0x04 */ | ||
| 1184 | U32 EventMasks[MPI2_IOCPAGE7_EVENTMASK_WORDS];/* 0x08 */ | ||
| 1185 | U16 SASBroadcastPrimitiveMasks; /* 0x18 */ | ||
| 1186 | U16 SASNotifyPrimitiveMasks; /* 0x1A */ | ||
| 1187 | U32 Reserved3; /* 0x1C */ | ||
| 1188 | } MPI2_CONFIG_PAGE_IOC_7, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_7, | ||
| 1189 | Mpi2IOCPage7_t, MPI2_POINTER pMpi2IOCPage7_t; | ||
| 1190 | |||
| 1191 | #define MPI2_IOCPAGE7_PAGEVERSION (0x02) | ||
| 1192 | |||
| 1193 | |||
| 1194 | /* IOC Page 8 */ | ||
| 1195 | |||
| 1196 | typedef struct _MPI2_CONFIG_PAGE_IOC_8 | ||
| 1197 | { | ||
| 1198 | MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ | ||
| 1199 | U8 NumDevsPerEnclosure; /* 0x04 */ | ||
| 1200 | U8 Reserved1; /* 0x05 */ | ||
| 1201 | U16 Reserved2; /* 0x06 */ | ||
| 1202 | U16 MaxPersistentEntries; /* 0x08 */ | ||
| 1203 | U16 MaxNumPhysicalMappedIDs; /* 0x0A */ | ||
| 1204 | U16 Flags; /* 0x0C */ | ||
| 1205 | U16 Reserved3; /* 0x0E */ | ||
| 1206 | U16 IRVolumeMappingFlags; /* 0x10 */ | ||
| 1207 | U16 Reserved4; /* 0x12 */ | ||
| 1208 | U32 Reserved5; /* 0x14 */ | ||
| 1209 | } MPI2_CONFIG_PAGE_IOC_8, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_8, | ||
| 1210 | Mpi2IOCPage8_t, MPI2_POINTER pMpi2IOCPage8_t; | ||
| 1211 | |||
| 1212 | #define MPI2_IOCPAGE8_PAGEVERSION (0x00) | ||
| 1213 | |||
| 1214 | /* defines for IOC Page 8 Flags field */ | ||
| 1215 | #define MPI2_IOCPAGE8_FLAGS_DA_START_SLOT_1 (0x00000020) | ||
| 1216 | #define MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0 (0x00000010) | ||
| 1217 | |||
| 1218 | #define MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE (0x0000000E) | ||
| 1219 | #define MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING (0x00000000) | ||
| 1220 | #define MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING (0x00000002) | ||
| 1221 | |||
| 1222 | #define MPI2_IOCPAGE8_FLAGS_DISABLE_PERSISTENT_MAPPING (0x00000001) | ||
| 1223 | #define MPI2_IOCPAGE8_FLAGS_ENABLE_PERSISTENT_MAPPING (0x00000000) | ||
| 1224 | |||
| 1225 | /* defines for IOC Page 8 IRVolumeMappingFlags */ | ||
| 1226 | #define MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE (0x00000003) | ||
| 1227 | #define MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING (0x00000000) | ||
| 1228 | #define MPI2_IOCPAGE8_IRFLAGS_HIGH_VOLUME_MAPPING (0x00000001) | ||
| 1229 | |||
| 1230 | |||
| 1231 | /**************************************************************************** | ||
| 1232 | * BIOS Config Pages | ||
| 1233 | ****************************************************************************/ | ||
| 1234 | |||
| 1235 | /* BIOS Page 1 */ | ||
| 1236 | |||
| 1237 | typedef struct _MPI2_CONFIG_PAGE_BIOS_1 | ||
| 1238 | { | ||
| 1239 | MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ | ||
| 1240 | U32 BiosOptions; /* 0x04 */ | ||
| 1241 | U32 IOCSettings; /* 0x08 */ | ||
| 1242 | U8 SSUTimeout; /* 0x0C */ | ||
| 1243 | U8 Reserved1; /* 0x0D */ | ||
| 1244 | U16 Reserved2; /* 0x0E */ | ||
| 1245 | U32 DeviceSettings; /* 0x10 */ | ||
| 1246 | U16 NumberOfDevices; /* 0x14 */ | ||
| 1247 | U16 UEFIVersion; /* 0x16 */ | ||
| 1248 | U16 IOTimeoutBlockDevicesNonRM; /* 0x18 */ | ||
| 1249 | U16 IOTimeoutSequential; /* 0x1A */ | ||
| 1250 | U16 IOTimeoutOther; /* 0x1C */ | ||
| 1251 | U16 IOTimeoutBlockDevicesRM; /* 0x1E */ | ||
| 1252 | } MPI2_CONFIG_PAGE_BIOS_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_BIOS_1, | ||
| 1253 | Mpi2BiosPage1_t, MPI2_POINTER pMpi2BiosPage1_t; | ||
| 1254 | |||
| 1255 | #define MPI2_BIOSPAGE1_PAGEVERSION (0x07) | ||
| 1256 | |||
| 1257 | /* values for BIOS Page 1 BiosOptions field */ | ||
| 1258 | #define MPI2_BIOSPAGE1_OPTIONS_PNS_MASK (0x00003800) | ||
| 1259 | #define MPI2_BIOSPAGE1_OPTIONS_PNS_PBDHL (0x00000000) | ||
| 1260 | #define MPI2_BIOSPAGE1_OPTIONS_PNS_ENCSLOSURE (0x00000800) | ||
| 1261 | #define MPI2_BIOSPAGE1_OPTIONS_PNS_LWWID (0x00001000) | ||
| 1262 | #define MPI2_BIOSPAGE1_OPTIONS_PNS_PSENS (0x00001800) | ||
| 1263 | #define MPI2_BIOSPAGE1_OPTIONS_PNS_ESPHY (0x00002000) | ||
| 1264 | |||
| 1265 | #define MPI2_BIOSPAGE1_OPTIONS_X86_DISABLE_BIOS (0x00000400) | ||
| 1266 | |||
| 1267 | #define MPI2_BIOSPAGE1_OPTIONS_MASK_REGISTRATION_UEFI_BSD (0x00000300) | ||
| 1268 | #define MPI2_BIOSPAGE1_OPTIONS_USE_BIT0_REGISTRATION_UEFI_BSD (0x00000000) | ||
| 1269 | #define MPI2_BIOSPAGE1_OPTIONS_FULL_REGISTRATION_UEFI_BSD (0x00000100) | ||
| 1270 | #define MPI2_BIOSPAGE1_OPTIONS_ADAPTER_REGISTRATION_UEFI_BSD (0x00000200) | ||
| 1271 | #define MPI2_BIOSPAGE1_OPTIONS_DISABLE_REGISTRATION_UEFI_BSD (0x00000300) | ||
| 1272 | |||
| 1273 | #define MPI2_BIOSPAGE1_OPTIONS_MASK_OEM_ID (0x000000F0) | ||
| 1274 | #define MPI2_BIOSPAGE1_OPTIONS_LSI_OEM_ID (0x00000000) | ||
| 1275 | |||
| 1276 | #define MPI2_BIOSPAGE1_OPTIONS_MASK_UEFI_HII_REGISTRATION (0x00000006) | ||
| 1277 | #define MPI2_BIOSPAGE1_OPTIONS_ENABLE_UEFI_HII (0x00000000) | ||
| 1278 | #define MPI2_BIOSPAGE1_OPTIONS_DISABLE_UEFI_HII (0x00000002) | ||
| 1279 | #define MPI2_BIOSPAGE1_OPTIONS_VERSION_CHECK_UEFI_HII (0x00000004) | ||
| 1280 | |||
| 1281 | #define MPI2_BIOSPAGE1_OPTIONS_DISABLE_BIOS (0x00000001) | ||
| 1282 | |||
| 1283 | /* values for BIOS Page 1 IOCSettings field */ | ||
| 1284 | #define MPI2_BIOSPAGE1_IOCSET_MASK_BOOT_PREFERENCE (0x00030000) | ||
| 1285 | #define MPI2_BIOSPAGE1_IOCSET_ENCLOSURE_SLOT_BOOT (0x00000000) | ||
| 1286 | #define MPI2_BIOSPAGE1_IOCSET_SAS_ADDRESS_BOOT (0x00010000) | ||
| 1287 | |||
| 1288 | #define MPI2_BIOSPAGE1_IOCSET_MASK_RM_SETTING (0x000000C0) | ||
| 1289 | #define MPI2_BIOSPAGE1_IOCSET_NONE_RM_SETTING (0x00000000) | ||
| 1290 | #define MPI2_BIOSPAGE1_IOCSET_BOOT_RM_SETTING (0x00000040) | ||
| 1291 | #define MPI2_BIOSPAGE1_IOCSET_MEDIA_RM_SETTING (0x00000080) | ||
| 1292 | |||
| 1293 | #define MPI2_BIOSPAGE1_IOCSET_MASK_ADAPTER_SUPPORT (0x00000030) | ||
| 1294 | #define MPI2_BIOSPAGE1_IOCSET_NO_SUPPORT (0x00000000) | ||
| 1295 | #define MPI2_BIOSPAGE1_IOCSET_BIOS_SUPPORT (0x00000010) | ||
| 1296 | #define MPI2_BIOSPAGE1_IOCSET_OS_SUPPORT (0x00000020) | ||
| 1297 | #define MPI2_BIOSPAGE1_IOCSET_ALL_SUPPORT (0x00000030) | ||
| 1298 | |||
| 1299 | #define MPI2_BIOSPAGE1_IOCSET_ALTERNATE_CHS (0x00000008) | ||
| 1300 | |||
| 1301 | /* values for BIOS Page 1 DeviceSettings field */ | ||
| 1302 | #define MPI2_BIOSPAGE1_DEVSET_DISABLE_SMART_POLLING (0x00000010) | ||
| 1303 | #define MPI2_BIOSPAGE1_DEVSET_DISABLE_SEQ_LUN (0x00000008) | ||
| 1304 | #define MPI2_BIOSPAGE1_DEVSET_DISABLE_RM_LUN (0x00000004) | ||
| 1305 | #define MPI2_BIOSPAGE1_DEVSET_DISABLE_NON_RM_LUN (0x00000002) | ||
| 1306 | #define MPI2_BIOSPAGE1_DEVSET_DISABLE_OTHER_LUN (0x00000001) | ||
| 1307 | |||
| 1308 | /* defines for BIOS Page 1 UEFIVersion field */ | ||
| 1309 | #define MPI2_BIOSPAGE1_UEFI_VER_MAJOR_MASK (0xFF00) | ||
| 1310 | #define MPI2_BIOSPAGE1_UEFI_VER_MAJOR_SHIFT (8) | ||
| 1311 | #define MPI2_BIOSPAGE1_UEFI_VER_MINOR_MASK (0x00FF) | ||
| 1312 | #define MPI2_BIOSPAGE1_UEFI_VER_MINOR_SHIFT (0) | ||
| 1313 | |||
| 1314 | |||
| 1315 | |||
| 1316 | /* BIOS Page 2 */ | ||
| 1317 | |||
| 1318 | typedef struct _MPI2_BOOT_DEVICE_ADAPTER_ORDER | ||
| 1319 | { | ||
| 1320 | U32 Reserved1; /* 0x00 */ | ||
| 1321 | U32 Reserved2; /* 0x04 */ | ||
| 1322 | U32 Reserved3; /* 0x08 */ | ||
| 1323 | U32 Reserved4; /* 0x0C */ | ||
| 1324 | U32 Reserved5; /* 0x10 */ | ||
| 1325 | U32 Reserved6; /* 0x14 */ | ||
| 1326 | } MPI2_BOOT_DEVICE_ADAPTER_ORDER, | ||
| 1327 | MPI2_POINTER PTR_MPI2_BOOT_DEVICE_ADAPTER_ORDER, | ||
| 1328 | Mpi2BootDeviceAdapterOrder_t, MPI2_POINTER pMpi2BootDeviceAdapterOrder_t; | ||
| 1329 | |||
| 1330 | typedef struct _MPI2_BOOT_DEVICE_SAS_WWID | ||
| 1331 | { | ||
| 1332 | U64 SASAddress; /* 0x00 */ | ||
| 1333 | U8 LUN[8]; /* 0x08 */ | ||
| 1334 | U32 Reserved1; /* 0x10 */ | ||
| 1335 | U32 Reserved2; /* 0x14 */ | ||
| 1336 | } MPI2_BOOT_DEVICE_SAS_WWID, MPI2_POINTER PTR_MPI2_BOOT_DEVICE_SAS_WWID, | ||
| 1337 | Mpi2BootDeviceSasWwid_t, MPI2_POINTER pMpi2BootDeviceSasWwid_t; | ||
| 1338 | |||
| 1339 | typedef struct _MPI2_BOOT_DEVICE_ENCLOSURE_SLOT | ||
| 1340 | { | ||
| 1341 | U64 EnclosureLogicalID; /* 0x00 */ | ||
| 1342 | U32 Reserved1; /* 0x08 */ | ||
| 1343 | U32 Reserved2; /* 0x0C */ | ||
| 1344 | U16 SlotNumber; /* 0x10 */ | ||
| 1345 | U16 Reserved3; /* 0x12 */ | ||
| 1346 | U32 Reserved4; /* 0x14 */ | ||
| 1347 | } MPI2_BOOT_DEVICE_ENCLOSURE_SLOT, | ||
| 1348 | MPI2_POINTER PTR_MPI2_BOOT_DEVICE_ENCLOSURE_SLOT, | ||
| 1349 | Mpi2BootDeviceEnclosureSlot_t, MPI2_POINTER pMpi2BootDeviceEnclosureSlot_t; | ||
| 1350 | |||
| 1351 | typedef struct _MPI2_BOOT_DEVICE_DEVICE_NAME | ||
| 1352 | { | ||
| 1353 | U64 DeviceName; /* 0x00 */ | ||
| 1354 | U8 LUN[8]; /* 0x08 */ | ||
| 1355 | U32 Reserved1; /* 0x10 */ | ||
| 1356 | U32 Reserved2; /* 0x14 */ | ||
| 1357 | } MPI2_BOOT_DEVICE_DEVICE_NAME, MPI2_POINTER PTR_MPI2_BOOT_DEVICE_DEVICE_NAME, | ||
| 1358 | Mpi2BootDeviceDeviceName_t, MPI2_POINTER pMpi2BootDeviceDeviceName_t; | ||
| 1359 | |||
| 1360 | typedef union _MPI2_MPI2_BIOSPAGE2_BOOT_DEVICE | ||
| 1361 | { | ||
| 1362 | MPI2_BOOT_DEVICE_ADAPTER_ORDER AdapterOrder; | ||
| 1363 | MPI2_BOOT_DEVICE_SAS_WWID SasWwid; | ||
| 1364 | MPI2_BOOT_DEVICE_ENCLOSURE_SLOT EnclosureSlot; | ||
| 1365 | MPI2_BOOT_DEVICE_DEVICE_NAME DeviceName; | ||
| 1366 | } MPI2_BIOSPAGE2_BOOT_DEVICE, MPI2_POINTER PTR_MPI2_BIOSPAGE2_BOOT_DEVICE, | ||
| 1367 | Mpi2BiosPage2BootDevice_t, MPI2_POINTER pMpi2BiosPage2BootDevice_t; | ||
| 1368 | |||
| 1369 | typedef struct _MPI2_CONFIG_PAGE_BIOS_2 | ||
| 1370 | { | ||
| 1371 | MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ | ||
| 1372 | U32 Reserved1; /* 0x04 */ | ||
| 1373 | U32 Reserved2; /* 0x08 */ | ||
| 1374 | U32 Reserved3; /* 0x0C */ | ||
| 1375 | U32 Reserved4; /* 0x10 */ | ||
| 1376 | U32 Reserved5; /* 0x14 */ | ||
| 1377 | U32 Reserved6; /* 0x18 */ | ||
| 1378 | U8 ReqBootDeviceForm; /* 0x1C */ | ||
| 1379 | U8 Reserved7; /* 0x1D */ | ||
| 1380 | U16 Reserved8; /* 0x1E */ | ||
| 1381 | MPI2_BIOSPAGE2_BOOT_DEVICE RequestedBootDevice; /* 0x20 */ | ||
| 1382 | U8 ReqAltBootDeviceForm; /* 0x38 */ | ||
| 1383 | U8 Reserved9; /* 0x39 */ | ||
| 1384 | U16 Reserved10; /* 0x3A */ | ||
| 1385 | MPI2_BIOSPAGE2_BOOT_DEVICE RequestedAltBootDevice; /* 0x3C */ | ||
| 1386 | U8 CurrentBootDeviceForm; /* 0x58 */ | ||
| 1387 | U8 Reserved11; /* 0x59 */ | ||
| 1388 | U16 Reserved12; /* 0x5A */ | ||
| 1389 | MPI2_BIOSPAGE2_BOOT_DEVICE CurrentBootDevice; /* 0x58 */ | ||
| 1390 | } MPI2_CONFIG_PAGE_BIOS_2, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_BIOS_2, | ||
| 1391 | Mpi2BiosPage2_t, MPI2_POINTER pMpi2BiosPage2_t; | ||
| 1392 | |||
| 1393 | #define MPI2_BIOSPAGE2_PAGEVERSION (0x04) | ||
| 1394 | |||
| 1395 | /* values for BIOS Page 2 BootDeviceForm fields */ | ||
| 1396 | #define MPI2_BIOSPAGE2_FORM_MASK (0x0F) | ||
| 1397 | #define MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED (0x00) | ||
| 1398 | #define MPI2_BIOSPAGE2_FORM_SAS_WWID (0x05) | ||
| 1399 | #define MPI2_BIOSPAGE2_FORM_ENCLOSURE_SLOT (0x06) | ||
| 1400 | #define MPI2_BIOSPAGE2_FORM_DEVICE_NAME (0x07) | ||
| 1401 | |||
| 1402 | |||
| 1403 | /* BIOS Page 3 */ | ||
| 1404 | |||
| 1405 | typedef struct _MPI2_ADAPTER_INFO | ||
| 1406 | { | ||
| 1407 | U8 PciBusNumber; /* 0x00 */ | ||
| 1408 | U8 PciDeviceAndFunctionNumber; /* 0x01 */ | ||
| 1409 | U16 AdapterFlags; /* 0x02 */ | ||
| 1410 | } MPI2_ADAPTER_INFO, MPI2_POINTER PTR_MPI2_ADAPTER_INFO, | ||
| 1411 | Mpi2AdapterInfo_t, MPI2_POINTER pMpi2AdapterInfo_t; | ||
| 1412 | |||
| 1413 | #define MPI2_ADAPTER_INFO_FLAGS_EMBEDDED (0x0001) | ||
| 1414 | #define MPI2_ADAPTER_INFO_FLAGS_INIT_STATUS (0x0002) | ||
| 1415 | |||
| 1416 | typedef struct _MPI2_CONFIG_PAGE_BIOS_3 | ||
| 1417 | { | ||
| 1418 | MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ | ||
| 1419 | U32 GlobalFlags; /* 0x04 */ | ||
| 1420 | U32 BiosVersion; /* 0x08 */ | ||
| 1421 | MPI2_ADAPTER_INFO AdapterOrder[4]; /* 0x0C */ | ||
| 1422 | U32 Reserved1; /* 0x1C */ | ||
| 1423 | } MPI2_CONFIG_PAGE_BIOS_3, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_BIOS_3, | ||
| 1424 | Mpi2BiosPage3_t, MPI2_POINTER pMpi2BiosPage3_t; | ||
| 1425 | |||
| 1426 | #define MPI2_BIOSPAGE3_PAGEVERSION (0x00) | ||
| 1427 | |||
| 1428 | /* values for BIOS Page 3 GlobalFlags */ | ||
| 1429 | #define MPI2_BIOSPAGE3_FLAGS_PAUSE_ON_ERROR (0x00000002) | ||
| 1430 | #define MPI2_BIOSPAGE3_FLAGS_VERBOSE_ENABLE (0x00000004) | ||
| 1431 | #define MPI2_BIOSPAGE3_FLAGS_HOOK_INT_40_DISABLE (0x00000010) | ||
| 1432 | |||
| 1433 | #define MPI2_BIOSPAGE3_FLAGS_DEV_LIST_DISPLAY_MASK (0x000000E0) | ||
| 1434 | #define MPI2_BIOSPAGE3_FLAGS_INSTALLED_DEV_DISPLAY (0x00000000) | ||
| 1435 | #define MPI2_BIOSPAGE3_FLAGS_ADAPTER_DISPLAY (0x00000020) | ||
| 1436 | #define MPI2_BIOSPAGE3_FLAGS_ADAPTER_DEV_DISPLAY (0x00000040) | ||
| 1437 | |||
| 1438 | |||
| 1439 | /* BIOS Page 4 */ | ||
| 1440 | |||
| 1441 | /* | ||
| 1442 | * Host code (drivers, BIOS, utilities, etc.) should leave this define set to | ||
| 1443 | * one and check the value returned for NumPhys at runtime. | ||
| 1444 | */ | ||
| 1445 | #ifndef MPI2_BIOS_PAGE_4_PHY_ENTRIES | ||
| 1446 | #define MPI2_BIOS_PAGE_4_PHY_ENTRIES (1) | ||
| 1447 | #endif | ||
| 1448 | |||
| 1449 | typedef struct _MPI2_BIOS4_ENTRY | ||
| 1450 | { | ||
| 1451 | U64 ReassignmentWWID; /* 0x00 */ | ||
| 1452 | U64 ReassignmentDeviceName; /* 0x08 */ | ||
| 1453 | } MPI2_BIOS4_ENTRY, MPI2_POINTER PTR_MPI2_BIOS4_ENTRY, | ||
| 1454 | Mpi2MBios4Entry_t, MPI2_POINTER pMpi2Bios4Entry_t; | ||
| 1455 | |||
| 1456 | typedef struct _MPI2_CONFIG_PAGE_BIOS_4 | ||
| 1457 | { | ||
| 1458 | MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ | ||
| 1459 | U8 NumPhys; /* 0x04 */ | ||
| 1460 | U8 Reserved1; /* 0x05 */ | ||
| 1461 | U16 Reserved2; /* 0x06 */ | ||
| 1462 | MPI2_BIOS4_ENTRY Phy[MPI2_BIOS_PAGE_4_PHY_ENTRIES]; /* 0x08 */ | ||
| 1463 | } MPI2_CONFIG_PAGE_BIOS_4, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_BIOS_4, | ||
| 1464 | Mpi2BiosPage4_t, MPI2_POINTER pMpi2BiosPage4_t; | ||
| 1465 | |||
| 1466 | #define MPI2_BIOSPAGE4_PAGEVERSION (0x01) | ||
| 1467 | |||
| 1468 | |||
| 1469 | /**************************************************************************** | ||
| 1470 | * RAID Volume Config Pages | ||
| 1471 | ****************************************************************************/ | ||
| 1472 | |||
| 1473 | /* RAID Volume Page 0 */ | ||
| 1474 | |||
| 1475 | typedef struct _MPI2_RAIDVOL0_PHYS_DISK | ||
| 1476 | { | ||
| 1477 | U8 RAIDSetNum; /* 0x00 */ | ||
| 1478 | U8 PhysDiskMap; /* 0x01 */ | ||
| 1479 | U8 PhysDiskNum; /* 0x02 */ | ||
| 1480 | U8 Reserved; /* 0x03 */ | ||
| 1481 | } MPI2_RAIDVOL0_PHYS_DISK, MPI2_POINTER PTR_MPI2_RAIDVOL0_PHYS_DISK, | ||
| 1482 | Mpi2RaidVol0PhysDisk_t, MPI2_POINTER pMpi2RaidVol0PhysDisk_t; | ||
| 1483 | |||
| 1484 | /* defines for the PhysDiskMap field */ | ||
| 1485 | #define MPI2_RAIDVOL0_PHYSDISK_PRIMARY (0x01) | ||
| 1486 | #define MPI2_RAIDVOL0_PHYSDISK_SECONDARY (0x02) | ||
| 1487 | |||
| 1488 | typedef struct _MPI2_RAIDVOL0_SETTINGS | ||
| 1489 | { | ||
| 1490 | U16 Settings; /* 0x00 */ | ||
| 1491 | U8 HotSparePool; /* 0x01 */ | ||
| 1492 | U8 Reserved; /* 0x02 */ | ||
| 1493 | } MPI2_RAIDVOL0_SETTINGS, MPI2_POINTER PTR_MPI2_RAIDVOL0_SETTINGS, | ||
| 1494 | Mpi2RaidVol0Settings_t, MPI2_POINTER pMpi2RaidVol0Settings_t; | ||
| 1495 | |||
| 1496 | /* RAID Volume Page 0 HotSparePool defines, also used in RAID Physical Disk */ | ||
| 1497 | #define MPI2_RAID_HOT_SPARE_POOL_0 (0x01) | ||
| 1498 | #define MPI2_RAID_HOT_SPARE_POOL_1 (0x02) | ||
| 1499 | #define MPI2_RAID_HOT_SPARE_POOL_2 (0x04) | ||
| 1500 | #define MPI2_RAID_HOT_SPARE_POOL_3 (0x08) | ||
| 1501 | #define MPI2_RAID_HOT_SPARE_POOL_4 (0x10) | ||
| 1502 | #define MPI2_RAID_HOT_SPARE_POOL_5 (0x20) | ||
| 1503 | #define MPI2_RAID_HOT_SPARE_POOL_6 (0x40) | ||
| 1504 | #define MPI2_RAID_HOT_SPARE_POOL_7 (0x80) | ||
| 1505 | |||
| 1506 | /* RAID Volume Page 0 VolumeSettings defines */ | ||
| 1507 | #define MPI2_RAIDVOL0_SETTING_USE_PRODUCT_ID_SUFFIX (0x0008) | ||
| 1508 | #define MPI2_RAIDVOL0_SETTING_AUTO_CONFIG_HSWAP_DISABLE (0x0004) | ||
| 1509 | |||
| 1510 | #define MPI2_RAIDVOL0_SETTING_MASK_WRITE_CACHING (0x0003) | ||
| 1511 | #define MPI2_RAIDVOL0_SETTING_UNCHANGED (0x0000) | ||
| 1512 | #define MPI2_RAIDVOL0_SETTING_DISABLE_WRITE_CACHING (0x0001) | ||
| 1513 | #define MPI2_RAIDVOL0_SETTING_ENABLE_WRITE_CACHING (0x0002) | ||
| 1514 | |||
| 1515 | /* | ||
| 1516 | * Host code (drivers, BIOS, utilities, etc.) should leave this define set to | ||
| 1517 | * one and check the value returned for NumPhysDisks at runtime. | ||
| 1518 | */ | ||
| 1519 | #ifndef MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX | ||
| 1520 | #define MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX (1) | ||
| 1521 | #endif | ||
| 1522 | |||
| 1523 | typedef struct _MPI2_CONFIG_PAGE_RAID_VOL_0 | ||
| 1524 | { | ||
| 1525 | MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ | ||
| 1526 | U16 DevHandle; /* 0x04 */ | ||
| 1527 | U8 VolumeState; /* 0x06 */ | ||
| 1528 | U8 VolumeType; /* 0x07 */ | ||
| 1529 | U32 VolumeStatusFlags; /* 0x08 */ | ||
| 1530 | MPI2_RAIDVOL0_SETTINGS VolumeSettings; /* 0x0C */ | ||
| 1531 | U64 MaxLBA; /* 0x10 */ | ||
| 1532 | U32 StripeSize; /* 0x18 */ | ||
| 1533 | U16 BlockSize; /* 0x1C */ | ||
| 1534 | U16 Reserved1; /* 0x1E */ | ||
| 1535 | U8 SupportedPhysDisks; /* 0x20 */ | ||
| 1536 | U8 ResyncRate; /* 0x21 */ | ||
| 1537 | U16 DataScrubDuration; /* 0x22 */ | ||
| 1538 | U8 NumPhysDisks; /* 0x24 */ | ||
| 1539 | U8 Reserved2; /* 0x25 */ | ||
| 1540 | U8 Reserved3; /* 0x26 */ | ||
| 1541 | U8 InactiveStatus; /* 0x27 */ | ||
| 1542 | MPI2_RAIDVOL0_PHYS_DISK PhysDisk[MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX]; /* 0x28 */ | ||
| 1543 | } MPI2_CONFIG_PAGE_RAID_VOL_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RAID_VOL_0, | ||
| 1544 | Mpi2RaidVolPage0_t, MPI2_POINTER pMpi2RaidVolPage0_t; | ||
| 1545 | |||
| 1546 | #define MPI2_RAIDVOLPAGE0_PAGEVERSION (0x0A) | ||
| 1547 | |||
| 1548 | /* values for RAID VolumeState */ | ||
| 1549 | #define MPI2_RAID_VOL_STATE_MISSING (0x00) | ||
| 1550 | #define MPI2_RAID_VOL_STATE_FAILED (0x01) | ||
| 1551 | #define MPI2_RAID_VOL_STATE_INITIALIZING (0x02) | ||
| 1552 | #define MPI2_RAID_VOL_STATE_ONLINE (0x03) | ||
| 1553 | #define MPI2_RAID_VOL_STATE_DEGRADED (0x04) | ||
| 1554 | #define MPI2_RAID_VOL_STATE_OPTIMAL (0x05) | ||
| 1555 | |||
| 1556 | /* values for RAID VolumeType */ | ||
| 1557 | #define MPI2_RAID_VOL_TYPE_RAID0 (0x00) | ||
| 1558 | #define MPI2_RAID_VOL_TYPE_RAID1E (0x01) | ||
| 1559 | #define MPI2_RAID_VOL_TYPE_RAID1 (0x02) | ||
| 1560 | #define MPI2_RAID_VOL_TYPE_RAID10 (0x05) | ||
| 1561 | #define MPI2_RAID_VOL_TYPE_UNKNOWN (0xFF) | ||
| 1562 | |||
| 1563 | /* values for RAID Volume Page 0 VolumeStatusFlags field */ | ||
| 1564 | #define MPI2_RAIDVOL0_STATUS_FLAG_PENDING_RESYNC (0x02000000) | ||
| 1565 | #define MPI2_RAIDVOL0_STATUS_FLAG_BACKG_INIT_PENDING (0x01000000) | ||
| 1566 | #define MPI2_RAIDVOL0_STATUS_FLAG_MDC_PENDING (0x00800000) | ||
| 1567 | #define MPI2_RAIDVOL0_STATUS_FLAG_USER_CONSIST_PENDING (0x00400000) | ||
| 1568 | #define MPI2_RAIDVOL0_STATUS_FLAG_MAKE_DATA_CONSISTENT (0x00200000) | ||
| 1569 | #define MPI2_RAIDVOL0_STATUS_FLAG_DATA_SCRUB (0x00100000) | ||
| 1570 | #define MPI2_RAIDVOL0_STATUS_FLAG_CONSISTENCY_CHECK (0x00080000) | ||
| 1571 | #define MPI2_RAIDVOL0_STATUS_FLAG_CAPACITY_EXPANSION (0x00040000) | ||
| 1572 | #define MPI2_RAIDVOL0_STATUS_FLAG_BACKGROUND_INIT (0x00020000) | ||
| 1573 | #define MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS (0x00010000) | ||
| 1574 | #define MPI2_RAIDVOL0_STATUS_FLAG_VOL_NOT_CONSISTENT (0x00000080) | ||
| 1575 | #define MPI2_RAIDVOL0_STATUS_FLAG_OCE_ALLOWED (0x00000040) | ||
| 1576 | #define MPI2_RAIDVOL0_STATUS_FLAG_BGI_COMPLETE (0x00000020) | ||
| 1577 | #define MPI2_RAIDVOL0_STATUS_FLAG_1E_OFFSET_MIRROR (0x00000000) | ||
| 1578 | #define MPI2_RAIDVOL0_STATUS_FLAG_1E_ADJACENT_MIRROR (0x00000010) | ||
| 1579 | #define MPI2_RAIDVOL0_STATUS_FLAG_BAD_BLOCK_TABLE_FULL (0x00000008) | ||
| 1580 | #define MPI2_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE (0x00000004) | ||
| 1581 | #define MPI2_RAIDVOL0_STATUS_FLAG_QUIESCED (0x00000002) | ||
| 1582 | #define MPI2_RAIDVOL0_STATUS_FLAG_ENABLED (0x00000001) | ||
| 1583 | |||
| 1584 | /* values for RAID Volume Page 0 SupportedPhysDisks field */ | ||
| 1585 | #define MPI2_RAIDVOL0_SUPPORT_SOLID_STATE_DISKS (0x08) | ||
| 1586 | #define MPI2_RAIDVOL0_SUPPORT_HARD_DISKS (0x04) | ||
| 1587 | #define MPI2_RAIDVOL0_SUPPORT_SAS_PROTOCOL (0x02) | ||
| 1588 | #define MPI2_RAIDVOL0_SUPPORT_SATA_PROTOCOL (0x01) | ||
| 1589 | |||
| 1590 | /* values for RAID Volume Page 0 InactiveStatus field */ | ||
| 1591 | #define MPI2_RAIDVOLPAGE0_UNKNOWN_INACTIVE (0x00) | ||
| 1592 | #define MPI2_RAIDVOLPAGE0_STALE_METADATA_INACTIVE (0x01) | ||
| 1593 | #define MPI2_RAIDVOLPAGE0_FOREIGN_VOLUME_INACTIVE (0x02) | ||
| 1594 | #define MPI2_RAIDVOLPAGE0_INSUFFICIENT_RESOURCE_INACTIVE (0x03) | ||
| 1595 | #define MPI2_RAIDVOLPAGE0_CLONE_VOLUME_INACTIVE (0x04) | ||
| 1596 | #define MPI2_RAIDVOLPAGE0_INSUFFICIENT_METADATA_INACTIVE (0x05) | ||
| 1597 | #define MPI2_RAIDVOLPAGE0_PREVIOUSLY_DELETED (0x06) | ||
| 1598 | |||
| 1599 | |||
| 1600 | /* RAID Volume Page 1 */ | ||
| 1601 | |||
| 1602 | typedef struct _MPI2_CONFIG_PAGE_RAID_VOL_1 | ||
| 1603 | { | ||
| 1604 | MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ | ||
| 1605 | U16 DevHandle; /* 0x04 */ | ||
| 1606 | U16 Reserved0; /* 0x06 */ | ||
| 1607 | U8 GUID[24]; /* 0x08 */ | ||
| 1608 | U8 Name[16]; /* 0x20 */ | ||
| 1609 | U64 WWID; /* 0x30 */ | ||
| 1610 | U32 Reserved1; /* 0x38 */ | ||
| 1611 | U32 Reserved2; /* 0x3C */ | ||
| 1612 | } MPI2_CONFIG_PAGE_RAID_VOL_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RAID_VOL_1, | ||
| 1613 | Mpi2RaidVolPage1_t, MPI2_POINTER pMpi2RaidVolPage1_t; | ||
| 1614 | |||
| 1615 | #define MPI2_RAIDVOLPAGE1_PAGEVERSION (0x03) | ||
| 1616 | |||
| 1617 | |||
| 1618 | /**************************************************************************** | ||
| 1619 | * RAID Physical Disk Config Pages | ||
| 1620 | ****************************************************************************/ | ||
| 1621 | |||
| 1622 | /* RAID Physical Disk Page 0 */ | ||
| 1623 | |||
| 1624 | typedef struct _MPI2_RAIDPHYSDISK0_SETTINGS | ||
| 1625 | { | ||
| 1626 | U16 Reserved1; /* 0x00 */ | ||
| 1627 | U8 HotSparePool; /* 0x02 */ | ||
| 1628 | U8 Reserved2; /* 0x03 */ | ||
| 1629 | } MPI2_RAIDPHYSDISK0_SETTINGS, MPI2_POINTER PTR_MPI2_RAIDPHYSDISK0_SETTINGS, | ||
| 1630 | Mpi2RaidPhysDisk0Settings_t, MPI2_POINTER pMpi2RaidPhysDisk0Settings_t; | ||
| 1631 | |||
| 1632 | /* use MPI2_RAID_HOT_SPARE_POOL_ defines for the HotSparePool field */ | ||
| 1633 | |||
| 1634 | typedef struct _MPI2_RAIDPHYSDISK0_INQUIRY_DATA | ||
| 1635 | { | ||
| 1636 | U8 VendorID[8]; /* 0x00 */ | ||
| 1637 | U8 ProductID[16]; /* 0x08 */ | ||
| 1638 | U8 ProductRevLevel[4]; /* 0x18 */ | ||
| 1639 | U8 SerialNum[32]; /* 0x1C */ | ||
| 1640 | } MPI2_RAIDPHYSDISK0_INQUIRY_DATA, | ||
| 1641 | MPI2_POINTER PTR_MPI2_RAIDPHYSDISK0_INQUIRY_DATA, | ||
| 1642 | Mpi2RaidPhysDisk0InquiryData_t, MPI2_POINTER pMpi2RaidPhysDisk0InquiryData_t; | ||
| 1643 | |||
| 1644 | typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_0 | ||
| 1645 | { | ||
| 1646 | MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ | ||
| 1647 | U16 DevHandle; /* 0x04 */ | ||
| 1648 | U8 Reserved1; /* 0x06 */ | ||
| 1649 | U8 PhysDiskNum; /* 0x07 */ | ||
| 1650 | MPI2_RAIDPHYSDISK0_SETTINGS PhysDiskSettings; /* 0x08 */ | ||
| 1651 | U32 Reserved2; /* 0x0C */ | ||
| 1652 | MPI2_RAIDPHYSDISK0_INQUIRY_DATA InquiryData; /* 0x10 */ | ||
| 1653 | U32 Reserved3; /* 0x4C */ | ||
| 1654 | U8 PhysDiskState; /* 0x50 */ | ||
| 1655 | U8 OfflineReason; /* 0x51 */ | ||
| 1656 | U8 IncompatibleReason; /* 0x52 */ | ||
| 1657 | U8 PhysDiskAttributes; /* 0x53 */ | ||
| 1658 | U32 PhysDiskStatusFlags; /* 0x54 */ | ||
| 1659 | U64 DeviceMaxLBA; /* 0x58 */ | ||
| 1660 | U64 HostMaxLBA; /* 0x60 */ | ||
| 1661 | U64 CoercedMaxLBA; /* 0x68 */ | ||
| 1662 | U16 BlockSize; /* 0x70 */ | ||
| 1663 | U16 Reserved5; /* 0x72 */ | ||
| 1664 | U32 Reserved6; /* 0x74 */ | ||
| 1665 | } MPI2_CONFIG_PAGE_RD_PDISK_0, | ||
| 1666 | MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RD_PDISK_0, | ||
| 1667 | Mpi2RaidPhysDiskPage0_t, MPI2_POINTER pMpi2RaidPhysDiskPage0_t; | ||
| 1668 | |||
| 1669 | #define MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION (0x05) | ||
| 1670 | |||
| 1671 | /* PhysDiskState defines */ | ||
| 1672 | #define MPI2_RAID_PD_STATE_NOT_CONFIGURED (0x00) | ||
| 1673 | #define MPI2_RAID_PD_STATE_NOT_COMPATIBLE (0x01) | ||
| 1674 | #define MPI2_RAID_PD_STATE_OFFLINE (0x02) | ||
| 1675 | #define MPI2_RAID_PD_STATE_ONLINE (0x03) | ||
| 1676 | #define MPI2_RAID_PD_STATE_HOT_SPARE (0x04) | ||
| 1677 | #define MPI2_RAID_PD_STATE_DEGRADED (0x05) | ||
| 1678 | #define MPI2_RAID_PD_STATE_REBUILDING (0x06) | ||
| 1679 | #define MPI2_RAID_PD_STATE_OPTIMAL (0x07) | ||
| 1680 | |||
| 1681 | /* OfflineReason defines */ | ||
| 1682 | #define MPI2_PHYSDISK0_ONLINE (0x00) | ||
| 1683 | #define MPI2_PHYSDISK0_OFFLINE_MISSING (0x01) | ||
| 1684 | #define MPI2_PHYSDISK0_OFFLINE_FAILED (0x03) | ||
| 1685 | #define MPI2_PHYSDISK0_OFFLINE_INITIALIZING (0x04) | ||
| 1686 | #define MPI2_PHYSDISK0_OFFLINE_REQUESTED (0x05) | ||
| 1687 | #define MPI2_PHYSDISK0_OFFLINE_FAILED_REQUESTED (0x06) | ||
| 1688 | #define MPI2_PHYSDISK0_OFFLINE_OTHER (0xFF) | ||
| 1689 | |||
| 1690 | /* IncompatibleReason defines */ | ||
| 1691 | #define MPI2_PHYSDISK0_COMPATIBLE (0x00) | ||
| 1692 | #define MPI2_PHYSDISK0_INCOMPATIBLE_PROTOCOL (0x01) | ||
| 1693 | #define MPI2_PHYSDISK0_INCOMPATIBLE_BLOCKSIZE (0x02) | ||
| 1694 | #define MPI2_PHYSDISK0_INCOMPATIBLE_MAX_LBA (0x03) | ||
| 1695 | #define MPI2_PHYSDISK0_INCOMPATIBLE_SATA_EXTENDED_CMD (0x04) | ||
| 1696 | #define MPI2_PHYSDISK0_INCOMPATIBLE_REMOVEABLE_MEDIA (0x05) | ||
| 1697 | #define MPI2_PHYSDISK0_INCOMPATIBLE_MEDIA_TYPE (0x06) | ||
| 1698 | #define MPI2_PHYSDISK0_INCOMPATIBLE_UNKNOWN (0xFF) | ||
| 1699 | |||
| 1700 | /* PhysDiskAttributes defines */ | ||
| 1701 | #define MPI2_PHYSDISK0_ATTRIB_MEDIA_MASK (0x0C) | ||
| 1702 | #define MPI2_PHYSDISK0_ATTRIB_SOLID_STATE_DRIVE (0x08) | ||
| 1703 | #define MPI2_PHYSDISK0_ATTRIB_HARD_DISK_DRIVE (0x04) | ||
| 1704 | |||
| 1705 | #define MPI2_PHYSDISK0_ATTRIB_PROTOCOL_MASK (0x03) | ||
| 1706 | #define MPI2_PHYSDISK0_ATTRIB_SAS_PROTOCOL (0x02) | ||
| 1707 | #define MPI2_PHYSDISK0_ATTRIB_SATA_PROTOCOL (0x01) | ||
| 1708 | |||
| 1709 | /* PhysDiskStatusFlags defines */ | ||
| 1710 | #define MPI2_PHYSDISK0_STATUS_FLAG_NOT_CERTIFIED (0x00000040) | ||
| 1711 | #define MPI2_PHYSDISK0_STATUS_FLAG_OCE_TARGET (0x00000020) | ||
| 1712 | #define MPI2_PHYSDISK0_STATUS_FLAG_WRITE_CACHE_ENABLED (0x00000010) | ||
| 1713 | #define MPI2_PHYSDISK0_STATUS_FLAG_OPTIMAL_PREVIOUS (0x00000000) | ||
| 1714 | #define MPI2_PHYSDISK0_STATUS_FLAG_NOT_OPTIMAL_PREVIOUS (0x00000008) | ||
| 1715 | #define MPI2_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME (0x00000004) | ||
| 1716 | #define MPI2_PHYSDISK0_STATUS_FLAG_QUIESCED (0x00000002) | ||
| 1717 | #define MPI2_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC (0x00000001) | ||
| 1718 | |||
| 1719 | |||
| 1720 | /* RAID Physical Disk Page 1 */ | ||
| 1721 | |||
| 1722 | /* | ||
| 1723 | * Host code (drivers, BIOS, utilities, etc.) should leave this define set to | ||
| 1724 | * one and check the value returned for NumPhysDiskPaths at runtime. | ||
| 1725 | */ | ||
| 1726 | #ifndef MPI2_RAID_PHYS_DISK1_PATH_MAX | ||
| 1727 | #define MPI2_RAID_PHYS_DISK1_PATH_MAX (1) | ||
| 1728 | #endif | ||
| 1729 | |||
| 1730 | typedef struct _MPI2_RAIDPHYSDISK1_PATH | ||
| 1731 | { | ||
| 1732 | U16 DevHandle; /* 0x00 */ | ||
| 1733 | U16 Reserved1; /* 0x02 */ | ||
| 1734 | U64 WWID; /* 0x04 */ | ||
| 1735 | U64 OwnerWWID; /* 0x0C */ | ||
| 1736 | U8 OwnerIdentifier; /* 0x14 */ | ||
| 1737 | U8 Reserved2; /* 0x15 */ | ||
| 1738 | U16 Flags; /* 0x16 */ | ||
| 1739 | } MPI2_RAIDPHYSDISK1_PATH, MPI2_POINTER PTR_MPI2_RAIDPHYSDISK1_PATH, | ||
| 1740 | Mpi2RaidPhysDisk1Path_t, MPI2_POINTER pMpi2RaidPhysDisk1Path_t; | ||
| 1741 | |||
| 1742 | /* RAID Physical Disk Page 1 Physical Disk Path Flags field defines */ | ||
| 1743 | #define MPI2_RAID_PHYSDISK1_FLAG_PRIMARY (0x0004) | ||
| 1744 | #define MPI2_RAID_PHYSDISK1_FLAG_BROKEN (0x0002) | ||
| 1745 | #define MPI2_RAID_PHYSDISK1_FLAG_INVALID (0x0001) | ||
| 1746 | |||
| 1747 | typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_1 | ||
| 1748 | { | ||
| 1749 | MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ | ||
| 1750 | U8 NumPhysDiskPaths; /* 0x04 */ | ||
| 1751 | U8 PhysDiskNum; /* 0x05 */ | ||
| 1752 | U16 Reserved1; /* 0x06 */ | ||
| 1753 | U32 Reserved2; /* 0x08 */ | ||
| 1754 | MPI2_RAIDPHYSDISK1_PATH PhysicalDiskPath[MPI2_RAID_PHYS_DISK1_PATH_MAX];/* 0x0C */ | ||
| 1755 | } MPI2_CONFIG_PAGE_RD_PDISK_1, | ||
| 1756 | MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RD_PDISK_1, | ||
| 1757 | Mpi2RaidPhysDiskPage1_t, MPI2_POINTER pMpi2RaidPhysDiskPage1_t; | ||
| 1758 | |||
| 1759 | #define MPI2_RAIDPHYSDISKPAGE1_PAGEVERSION (0x02) | ||
| 1760 | |||
| 1761 | |||
| 1762 | /**************************************************************************** | ||
| 1763 | * values for fields used by several types of SAS Config Pages | ||
| 1764 | ****************************************************************************/ | ||
| 1765 | |||
| 1766 | /* values for NegotiatedLinkRates fields */ | ||
| 1767 | #define MPI2_SAS_NEG_LINK_RATE_MASK_LOGICAL (0xF0) | ||
| 1768 | #define MPI2_SAS_NEG_LINK_RATE_SHIFT_LOGICAL (4) | ||
| 1769 | #define MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL (0x0F) | ||
| 1770 | /* link rates used for Negotiated Physical and Logical Link Rate */ | ||
| 1771 | #define MPI2_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE (0x00) | ||
| 1772 | #define MPI2_SAS_NEG_LINK_RATE_PHY_DISABLED (0x01) | ||
| 1773 | #define MPI2_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED (0x02) | ||
| 1774 | #define MPI2_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE (0x03) | ||
| 1775 | #define MPI2_SAS_NEG_LINK_RATE_PORT_SELECTOR (0x04) | ||
| 1776 | #define MPI2_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS (0x05) | ||
| 1777 | #define MPI2_SAS_NEG_LINK_RATE_UNSUPPORTED_PHY (0x06) | ||
| 1778 | #define MPI2_SAS_NEG_LINK_RATE_1_5 (0x08) | ||
| 1779 | #define MPI2_SAS_NEG_LINK_RATE_3_0 (0x09) | ||
| 1780 | #define MPI2_SAS_NEG_LINK_RATE_6_0 (0x0A) | ||
| 1781 | |||
| 1782 | |||
| 1783 | /* values for AttachedPhyInfo fields */ | ||
| 1784 | #define MPI2_SAS_APHYINFO_INSIDE_ZPSDS_PERSISTENT (0x00000040) | ||
| 1785 | #define MPI2_SAS_APHYINFO_REQUESTED_INSIDE_ZPSDS (0x00000020) | ||
| 1786 | #define MPI2_SAS_APHYINFO_BREAK_REPLY_CAPABLE (0x00000010) | ||
| 1787 | |||
| 1788 | #define MPI2_SAS_APHYINFO_REASON_MASK (0x0000000F) | ||
| 1789 | #define MPI2_SAS_APHYINFO_REASON_UNKNOWN (0x00000000) | ||
| 1790 | #define MPI2_SAS_APHYINFO_REASON_POWER_ON (0x00000001) | ||
| 1791 | #define MPI2_SAS_APHYINFO_REASON_HARD_RESET (0x00000002) | ||
| 1792 | #define MPI2_SAS_APHYINFO_REASON_SMP_PHY_CONTROL (0x00000003) | ||
| 1793 | #define MPI2_SAS_APHYINFO_REASON_LOSS_OF_SYNC (0x00000004) | ||
| 1794 | #define MPI2_SAS_APHYINFO_REASON_MULTIPLEXING_SEQ (0x00000005) | ||
| 1795 | #define MPI2_SAS_APHYINFO_REASON_IT_NEXUS_LOSS_TIMER (0x00000006) | ||
| 1796 | #define MPI2_SAS_APHYINFO_REASON_BREAK_TIMEOUT (0x00000007) | ||
| 1797 | #define MPI2_SAS_APHYINFO_REASON_PHY_TEST_STOPPED (0x00000008) | ||
| 1798 | |||
| 1799 | |||
| 1800 | /* values for PhyInfo fields */ | ||
| 1801 | #define MPI2_SAS_PHYINFO_PHY_VACANT (0x80000000) | ||
| 1802 | |||
| 1803 | #define MPI2_SAS_PHYINFO_PHY_POWER_CONDITION_MASK (0x18000000) | ||
| 1804 | #define MPI2_SAS_PHYINFO_SHIFT_PHY_POWER_CONDITION (27) | ||
| 1805 | #define MPI2_SAS_PHYINFO_PHY_POWER_ACTIVE (0x00000000) | ||
| 1806 | #define MPI2_SAS_PHYINFO_PHY_POWER_PARTIAL (0x08000000) | ||
| 1807 | #define MPI2_SAS_PHYINFO_PHY_POWER_SLUMBER (0x10000000) | ||
| 1808 | |||
| 1809 | #define MPI2_SAS_PHYINFO_CHANGED_REQ_INSIDE_ZPSDS (0x04000000) | ||
| 1810 | #define MPI2_SAS_PHYINFO_INSIDE_ZPSDS_PERSISTENT (0x02000000) | ||
| 1811 | #define MPI2_SAS_PHYINFO_REQ_INSIDE_ZPSDS (0x01000000) | ||
| 1812 | #define MPI2_SAS_PHYINFO_ZONE_GROUP_PERSISTENT (0x00400000) | ||
| 1813 | #define MPI2_SAS_PHYINFO_INSIDE_ZPSDS (0x00200000) | ||
| 1814 | #define MPI2_SAS_PHYINFO_ZONING_ENABLED (0x00100000) | ||
| 1815 | |||
| 1816 | #define MPI2_SAS_PHYINFO_REASON_MASK (0x000F0000) | ||
| 1817 | #define MPI2_SAS_PHYINFO_REASON_UNKNOWN (0x00000000) | ||
| 1818 | #define MPI2_SAS_PHYINFO_REASON_POWER_ON (0x00010000) | ||
| 1819 | #define MPI2_SAS_PHYINFO_REASON_HARD_RESET (0x00020000) | ||
| 1820 | #define MPI2_SAS_PHYINFO_REASON_SMP_PHY_CONTROL (0x00030000) | ||
| 1821 | #define MPI2_SAS_PHYINFO_REASON_LOSS_OF_SYNC (0x00040000) | ||
| 1822 | #define MPI2_SAS_PHYINFO_REASON_MULTIPLEXING_SEQ (0x00050000) | ||
| 1823 | #define MPI2_SAS_PHYINFO_REASON_IT_NEXUS_LOSS_TIMER (0x00060000) | ||
| 1824 | #define MPI2_SAS_PHYINFO_REASON_BREAK_TIMEOUT (0x00070000) | ||
| 1825 | #define MPI2_SAS_PHYINFO_REASON_PHY_TEST_STOPPED (0x00080000) | ||
| 1826 | |||
| 1827 | #define MPI2_SAS_PHYINFO_MULTIPLEXING_SUPPORTED (0x00008000) | ||
| 1828 | #define MPI2_SAS_PHYINFO_SATA_PORT_ACTIVE (0x00004000) | ||
| 1829 | #define MPI2_SAS_PHYINFO_SATA_PORT_SELECTOR_PRESENT (0x00002000) | ||
| 1830 | #define MPI2_SAS_PHYINFO_VIRTUAL_PHY (0x00001000) | ||
| 1831 | |||
| 1832 | #define MPI2_SAS_PHYINFO_MASK_PARTIAL_PATHWAY_TIME (0x00000F00) | ||
| 1833 | #define MPI2_SAS_PHYINFO_SHIFT_PARTIAL_PATHWAY_TIME (8) | ||
| 1834 | |||
| 1835 | #define MPI2_SAS_PHYINFO_MASK_ROUTING_ATTRIBUTE (0x000000F0) | ||
| 1836 | #define MPI2_SAS_PHYINFO_DIRECT_ROUTING (0x00000000) | ||
| 1837 | #define MPI2_SAS_PHYINFO_SUBTRACTIVE_ROUTING (0x00000010) | ||
| 1838 | #define MPI2_SAS_PHYINFO_TABLE_ROUTING (0x00000020) | ||
| 1839 | |||
| 1840 | |||
| 1841 | /* values for SAS ProgrammedLinkRate fields */ | ||
| 1842 | #define MPI2_SAS_PRATE_MAX_RATE_MASK (0xF0) | ||
| 1843 | #define MPI2_SAS_PRATE_MAX_RATE_NOT_PROGRAMMABLE (0x00) | ||
| 1844 | #define MPI2_SAS_PRATE_MAX_RATE_1_5 (0x80) | ||
| 1845 | #define MPI2_SAS_PRATE_MAX_RATE_3_0 (0x90) | ||
| 1846 | #define MPI2_SAS_PRATE_MAX_RATE_6_0 (0xA0) | ||
| 1847 | #define MPI25_SAS_PRATE_MAX_RATE_12_0 (0xB0) | ||
| 1848 | #define MPI2_SAS_PRATE_MIN_RATE_MASK (0x0F) | ||
| 1849 | #define MPI2_SAS_PRATE_MIN_RATE_NOT_PROGRAMMABLE (0x00) | ||
| 1850 | #define MPI2_SAS_PRATE_MIN_RATE_1_5 (0x08) | ||
| 1851 | #define MPI2_SAS_PRATE_MIN_RATE_3_0 (0x09) | ||
| 1852 | #define MPI2_SAS_PRATE_MIN_RATE_6_0 (0x0A) | ||
| 1853 | |||
| 1854 | |||
| 1855 | /* values for SAS HwLinkRate fields */ | ||
| 1856 | #define MPI2_SAS_HWRATE_MAX_RATE_MASK (0xF0) | ||
| 1857 | #define MPI2_SAS_HWRATE_MAX_RATE_1_5 (0x80) | ||
| 1858 | #define MPI2_SAS_HWRATE_MAX_RATE_3_0 (0x90) | ||
| 1859 | #define MPI2_SAS_HWRATE_MAX_RATE_6_0 (0xA0) | ||
| 1860 | #define MPI25_SAS_HWRATE_MAX_RATE_12_0 (0xB0) | ||
| 1861 | #define MPI2_SAS_HWRATE_MIN_RATE_MASK (0x0F) | ||
| 1862 | #define MPI2_SAS_HWRATE_MIN_RATE_1_5 (0x08) | ||
| 1863 | #define MPI2_SAS_HWRATE_MIN_RATE_3_0 (0x09) | ||
| 1864 | #define MPI2_SAS_HWRATE_MIN_RATE_6_0 (0x0A) | ||
| 1865 | |||
| 1866 | |||
| 1867 | |||
| 1868 | /**************************************************************************** | ||
| 1869 | * SAS IO Unit Config Pages | ||
| 1870 | ****************************************************************************/ | ||
| 1871 | |||
| 1872 | /* SAS IO Unit Page 0 */ | ||
| 1873 | |||
| 1874 | typedef struct _MPI2_SAS_IO_UNIT0_PHY_DATA | ||
| 1875 | { | ||
| 1876 | U8 Port; /* 0x00 */ | ||
| 1877 | U8 PortFlags; /* 0x01 */ | ||
| 1878 | U8 PhyFlags; /* 0x02 */ | ||
| 1879 | U8 NegotiatedLinkRate; /* 0x03 */ | ||
| 1880 | U32 ControllerPhyDeviceInfo;/* 0x04 */ | ||
| 1881 | U16 AttachedDevHandle; /* 0x08 */ | ||
| 1882 | U16 ControllerDevHandle; /* 0x0A */ | ||
| 1883 | U32 DiscoveryStatus; /* 0x0C */ | ||
| 1884 | U32 Reserved; /* 0x10 */ | ||
| 1885 | } MPI2_SAS_IO_UNIT0_PHY_DATA, MPI2_POINTER PTR_MPI2_SAS_IO_UNIT0_PHY_DATA, | ||
| 1886 | Mpi2SasIOUnit0PhyData_t, MPI2_POINTER pMpi2SasIOUnit0PhyData_t; | ||
| 1887 | |||
| 1888 | /* | ||
| 1889 | * Host code (drivers, BIOS, utilities, etc.) should leave this define set to | ||
| 1890 | * one and check the value returned for NumPhys at runtime. | ||
| 1891 | */ | ||
| 1892 | #ifndef MPI2_SAS_IOUNIT0_PHY_MAX | ||
| 1893 | #define MPI2_SAS_IOUNIT0_PHY_MAX (1) | ||
| 1894 | #endif | ||
| 1895 | |||
| 1896 | typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_0 | ||
| 1897 | { | ||
| 1898 | MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ | ||
| 1899 | U32 Reserved1; /* 0x08 */ | ||
| 1900 | U8 NumPhys; /* 0x0C */ | ||
| 1901 | U8 Reserved2; /* 0x0D */ | ||
| 1902 | U16 Reserved3; /* 0x0E */ | ||
| 1903 | MPI2_SAS_IO_UNIT0_PHY_DATA PhyData[MPI2_SAS_IOUNIT0_PHY_MAX]; /* 0x10 */ | ||
| 1904 | } MPI2_CONFIG_PAGE_SASIOUNIT_0, | ||
| 1905 | MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_0, | ||
| 1906 | Mpi2SasIOUnitPage0_t, MPI2_POINTER pMpi2SasIOUnitPage0_t; | ||
| 1907 | |||
| 1908 | #define MPI2_SASIOUNITPAGE0_PAGEVERSION (0x05) | ||
| 1909 | |||
| 1910 | /* values for SAS IO Unit Page 0 PortFlags */ | ||
| 1911 | #define MPI2_SASIOUNIT0_PORTFLAGS_DISCOVERY_IN_PROGRESS (0x08) | ||
| 1912 | #define MPI2_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG (0x01) | ||
| 1913 | |||
| 1914 | /* values for SAS IO Unit Page 0 PhyFlags */ | ||
| 1915 | #define MPI2_SASIOUNIT0_PHYFLAGS_ZONING_ENABLED (0x10) | ||
| 1916 | #define MPI2_SASIOUNIT0_PHYFLAGS_PHY_DISABLED (0x08) | ||
| 1917 | |||
| 1918 | /* use MPI2_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */ | ||
| 1919 | |||
| 1920 | /* see mpi2_sas.h for values for SAS IO Unit Page 0 ControllerPhyDeviceInfo values */ | ||
| 1921 | |||
| 1922 | /* values for SAS IO Unit Page 0 DiscoveryStatus */ | ||
| 1923 | #define MPI2_SASIOUNIT0_DS_MAX_ENCLOSURES_EXCEED (0x80000000) | ||
| 1924 | #define MPI2_SASIOUNIT0_DS_MAX_EXPANDERS_EXCEED (0x40000000) | ||
| 1925 | #define MPI2_SASIOUNIT0_DS_MAX_DEVICES_EXCEED (0x20000000) | ||
| 1926 | #define MPI2_SASIOUNIT0_DS_MAX_TOPO_PHYS_EXCEED (0x10000000) | ||
| 1927 | #define MPI2_SASIOUNIT0_DS_DOWNSTREAM_INITIATOR (0x08000000) | ||
| 1928 | #define MPI2_SASIOUNIT0_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE (0x00008000) | ||
| 1929 | #define MPI2_SASIOUNIT0_DS_EXP_MULTI_SUBTRACTIVE (0x00004000) | ||
| 1930 | #define MPI2_SASIOUNIT0_DS_MULTI_PORT_DOMAIN (0x00002000) | ||
| 1931 | #define MPI2_SASIOUNIT0_DS_TABLE_TO_SUBTRACTIVE_LINK (0x00001000) | ||
| 1932 | #define MPI2_SASIOUNIT0_DS_UNSUPPORTED_DEVICE (0x00000800) | ||
| 1933 | #define MPI2_SASIOUNIT0_DS_TABLE_LINK (0x00000400) | ||
| 1934 | #define MPI2_SASIOUNIT0_DS_SUBTRACTIVE_LINK (0x00000200) | ||
| 1935 | #define MPI2_SASIOUNIT0_DS_SMP_CRC_ERROR (0x00000100) | ||
| 1936 | #define MPI2_SASIOUNIT0_DS_SMP_FUNCTION_FAILED (0x00000080) | ||
| 1937 | #define MPI2_SASIOUNIT0_DS_INDEX_NOT_EXIST (0x00000040) | ||
| 1938 | #define MPI2_SASIOUNIT0_DS_OUT_ROUTE_ENTRIES (0x00000020) | ||
| 1939 | #define MPI2_SASIOUNIT0_DS_SMP_TIMEOUT (0x00000010) | ||
| 1940 | #define MPI2_SASIOUNIT0_DS_MULTIPLE_PORTS (0x00000004) | ||
| 1941 | #define MPI2_SASIOUNIT0_DS_UNADDRESSABLE_DEVICE (0x00000002) | ||
| 1942 | #define MPI2_SASIOUNIT0_DS_LOOP_DETECTED (0x00000001) | ||
| 1943 | |||
| 1944 | |||
| 1945 | /* SAS IO Unit Page 1 */ | ||
| 1946 | |||
| 1947 | typedef struct _MPI2_SAS_IO_UNIT1_PHY_DATA | ||
| 1948 | { | ||
| 1949 | U8 Port; /* 0x00 */ | ||
| 1950 | U8 PortFlags; /* 0x01 */ | ||
| 1951 | U8 PhyFlags; /* 0x02 */ | ||
| 1952 | U8 MaxMinLinkRate; /* 0x03 */ | ||
| 1953 | U32 ControllerPhyDeviceInfo; /* 0x04 */ | ||
| 1954 | U16 MaxTargetPortConnectTime; /* 0x08 */ | ||
| 1955 | U16 Reserved1; /* 0x0A */ | ||
| 1956 | } MPI2_SAS_IO_UNIT1_PHY_DATA, MPI2_POINTER PTR_MPI2_SAS_IO_UNIT1_PHY_DATA, | ||
| 1957 | Mpi2SasIOUnit1PhyData_t, MPI2_POINTER pMpi2SasIOUnit1PhyData_t; | ||
| 1958 | |||
| 1959 | /* | ||
| 1960 | * Host code (drivers, BIOS, utilities, etc.) should leave this define set to | ||
| 1961 | * one and check the value returned for NumPhys at runtime. | ||
| 1962 | */ | ||
| 1963 | #ifndef MPI2_SAS_IOUNIT1_PHY_MAX | ||
| 1964 | #define MPI2_SAS_IOUNIT1_PHY_MAX (1) | ||
| 1965 | #endif | ||
| 1966 | |||
| 1967 | typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_1 | ||
| 1968 | { | ||
| 1969 | MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ | ||
| 1970 | U16 ControlFlags; /* 0x08 */ | ||
| 1971 | U16 SASNarrowMaxQueueDepth; /* 0x0A */ | ||
| 1972 | U16 AdditionalControlFlags; /* 0x0C */ | ||
| 1973 | U16 SASWideMaxQueueDepth; /* 0x0E */ | ||
| 1974 | U8 NumPhys; /* 0x10 */ | ||
| 1975 | U8 SATAMaxQDepth; /* 0x11 */ | ||
| 1976 | U8 ReportDeviceMissingDelay; /* 0x12 */ | ||
| 1977 | U8 IODeviceMissingDelay; /* 0x13 */ | ||
| 1978 | MPI2_SAS_IO_UNIT1_PHY_DATA PhyData[MPI2_SAS_IOUNIT1_PHY_MAX]; /* 0x14 */ | ||
| 1979 | } MPI2_CONFIG_PAGE_SASIOUNIT_1, | ||
| 1980 | MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_1, | ||
| 1981 | Mpi2SasIOUnitPage1_t, MPI2_POINTER pMpi2SasIOUnitPage1_t; | ||
| 1982 | |||
| 1983 | #define MPI2_SASIOUNITPAGE1_PAGEVERSION (0x09) | ||
| 1984 | |||
| 1985 | /* values for SAS IO Unit Page 1 ControlFlags */ | ||
| 1986 | #define MPI2_SASIOUNIT1_CONTROL_DEVICE_SELF_TEST (0x8000) | ||
| 1987 | #define MPI2_SASIOUNIT1_CONTROL_SATA_3_0_MAX (0x4000) | ||
| 1988 | #define MPI2_SASIOUNIT1_CONTROL_SATA_1_5_MAX (0x2000) | ||
| 1989 | #define MPI2_SASIOUNIT1_CONTROL_SATA_SW_PRESERVE (0x1000) | ||
| 1990 | |||
| 1991 | #define MPI2_SASIOUNIT1_CONTROL_MASK_DEV_SUPPORT (0x0600) | ||
| 1992 | #define MPI2_SASIOUNIT1_CONTROL_SHIFT_DEV_SUPPORT (9) | ||
| 1993 | #define MPI2_SASIOUNIT1_CONTROL_DEV_SUPPORT_BOTH (0x0) | ||
| 1994 | #define MPI2_SASIOUNIT1_CONTROL_DEV_SAS_SUPPORT (0x1) | ||
| 1995 | #define MPI2_SASIOUNIT1_CONTROL_DEV_SATA_SUPPORT (0x2) | ||
| 1996 | |||
| 1997 | #define MPI2_SASIOUNIT1_CONTROL_SATA_48BIT_LBA_REQUIRED (0x0080) | ||
| 1998 | #define MPI2_SASIOUNIT1_CONTROL_SATA_SMART_REQUIRED (0x0040) | ||
| 1999 | #define MPI2_SASIOUNIT1_CONTROL_SATA_NCQ_REQUIRED (0x0020) | ||
| 2000 | #define MPI2_SASIOUNIT1_CONTROL_SATA_FUA_REQUIRED (0x0010) | ||
| 2001 | #define MPI2_SASIOUNIT1_CONTROL_TABLE_SUBTRACTIVE_ILLEGAL (0x0008) | ||
| 2002 | #define MPI2_SASIOUNIT1_CONTROL_SUBTRACTIVE_ILLEGAL (0x0004) | ||
| 2003 | #define MPI2_SASIOUNIT1_CONTROL_FIRST_LVL_DISC_ONLY (0x0002) | ||
| 2004 | #define MPI2_SASIOUNIT1_CONTROL_CLEAR_AFFILIATION (0x0001) | ||
| 2005 | |||
| 2006 | /* values for SAS IO Unit Page 1 AdditionalControlFlags */ | ||
| 2007 | #define MPI2_SASIOUNIT1_ACONTROL_MULTI_PORT_DOMAIN_ILLEGAL (0x0080) | ||
| 2008 | #define MPI2_SASIOUNIT1_ACONTROL_SATA_ASYNCHROUNOUS_NOTIFICATION (0x0040) | ||
| 2009 | #define MPI2_SASIOUNIT1_ACONTROL_INVALID_TOPOLOGY_CORRECTION (0x0020) | ||
| 2010 | #define MPI2_SASIOUNIT1_ACONTROL_PORT_ENABLE_ONLY_SATA_LINK_RESET (0x0010) | ||
| 2011 | #define MPI2_SASIOUNIT1_ACONTROL_OTHER_AFFILIATION_SATA_LINK_RESET (0x0008) | ||
| 2012 | #define MPI2_SASIOUNIT1_ACONTROL_SELF_AFFILIATION_SATA_LINK_RESET (0x0004) | ||
| 2013 | #define MPI2_SASIOUNIT1_ACONTROL_NO_AFFILIATION_SATA_LINK_RESET (0x0002) | ||
| 2014 | #define MPI2_SASIOUNIT1_ACONTROL_ALLOW_TABLE_TO_TABLE (0x0001) | ||
| 2015 | |||
| 2016 | /* defines for SAS IO Unit Page 1 ReportDeviceMissingDelay */ | ||
| 2017 | #define MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK (0x7F) | ||
| 2018 | #define MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16 (0x80) | ||
| 2019 | |||
| 2020 | /* values for SAS IO Unit Page 1 PortFlags */ | ||
| 2021 | #define MPI2_SASIOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG (0x01) | ||
| 2022 | |||
| 2023 | /* values for SAS IO Unit Page 1 PhyFlags */ | ||
| 2024 | #define MPI2_SASIOUNIT1_PHYFLAGS_ZONING_ENABLE (0x10) | ||
| 2025 | #define MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE (0x08) | ||
| 2026 | |||
| 2027 | /* values for SAS IO Unit Page 1 MaxMinLinkRate */ | ||
| 2028 | #define MPI2_SASIOUNIT1_MAX_RATE_MASK (0xF0) | ||
| 2029 | #define MPI2_SASIOUNIT1_MAX_RATE_1_5 (0x80) | ||
| 2030 | #define MPI2_SASIOUNIT1_MAX_RATE_3_0 (0x90) | ||
| 2031 | #define MPI2_SASIOUNIT1_MAX_RATE_6_0 (0xA0) | ||
| 2032 | #define MPI2_SASIOUNIT1_MIN_RATE_MASK (0x0F) | ||
| 2033 | #define MPI2_SASIOUNIT1_MIN_RATE_1_5 (0x08) | ||
| 2034 | #define MPI2_SASIOUNIT1_MIN_RATE_3_0 (0x09) | ||
| 2035 | #define MPI2_SASIOUNIT1_MIN_RATE_6_0 (0x0A) | ||
| 2036 | |||
| 2037 | /* see mpi2_sas.h for values for SAS IO Unit Page 1 ControllerPhyDeviceInfo values */ | ||
| 2038 | |||
| 2039 | |||
| 2040 | /* SAS IO Unit Page 4 */ | ||
| 2041 | |||
| 2042 | typedef struct _MPI2_SAS_IOUNIT4_SPINUP_GROUP | ||
| 2043 | { | ||
| 2044 | U8 MaxTargetSpinup; /* 0x00 */ | ||
| 2045 | U8 SpinupDelay; /* 0x01 */ | ||
| 2046 | U8 SpinupFlags; /* 0x02 */ | ||
| 2047 | U8 Reserved1; /* 0x03 */ | ||
| 2048 | } MPI2_SAS_IOUNIT4_SPINUP_GROUP, MPI2_POINTER PTR_MPI2_SAS_IOUNIT4_SPINUP_GROUP, | ||
| 2049 | Mpi2SasIOUnit4SpinupGroup_t, MPI2_POINTER pMpi2SasIOUnit4SpinupGroup_t; | ||
| 2050 | |||
| 2051 | /* defines for SAS IO Unit Page 4 SpinupFlags */ | ||
| 2052 | #define MPI2_SASIOUNIT4_SPINUP_DISABLE_FLAG (0x01) | ||
| 2053 | |||
| 2054 | /* | ||
| 2055 | * Host code (drivers, BIOS, utilities, etc.) should leave this define set to | ||
| 2056 | * one and check the value returned for NumPhys at runtime. | ||
| 2057 | */ | ||
| 2058 | #ifndef MPI2_SAS_IOUNIT4_PHY_MAX | ||
| 2059 | #define MPI2_SAS_IOUNIT4_PHY_MAX (4) | ||
| 2060 | #endif | ||
| 2061 | |||
| 2062 | typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_4 | ||
| 2063 | { | ||
| 2064 | MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ | ||
| 2065 | MPI2_SAS_IOUNIT4_SPINUP_GROUP SpinupGroupParameters[4]; /* 0x08 */ | ||
| 2066 | U32 Reserved1; /* 0x18 */ | ||
| 2067 | U32 Reserved2; /* 0x1C */ | ||
| 2068 | U32 Reserved3; /* 0x20 */ | ||
| 2069 | U8 BootDeviceWaitTime; /* 0x24 */ | ||
| 2070 | U8 Reserved4; /* 0x25 */ | ||
| 2071 | U16 Reserved5; /* 0x26 */ | ||
| 2072 | U8 NumPhys; /* 0x28 */ | ||
| 2073 | U8 PEInitialSpinupDelay; /* 0x29 */ | ||
| 2074 | U8 PEReplyDelay; /* 0x2A */ | ||
| 2075 | U8 Flags; /* 0x2B */ | ||
| 2076 | U8 PHY[MPI2_SAS_IOUNIT4_PHY_MAX]; /* 0x2C */ | ||
| 2077 | } MPI2_CONFIG_PAGE_SASIOUNIT_4, | ||
| 2078 | MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_4, | ||
| 2079 | Mpi2SasIOUnitPage4_t, MPI2_POINTER pMpi2SasIOUnitPage4_t; | ||
| 2080 | |||
| 2081 | #define MPI2_SASIOUNITPAGE4_PAGEVERSION (0x02) | ||
| 2082 | |||
| 2083 | /* defines for Flags field */ | ||
| 2084 | #define MPI2_SASIOUNIT4_FLAGS_AUTO_PORTENABLE (0x01) | ||
| 2085 | |||
| 2086 | /* defines for PHY field */ | ||
| 2087 | #define MPI2_SASIOUNIT4_PHY_SPINUP_GROUP_MASK (0x03) | ||
| 2088 | |||
| 2089 | |||
| 2090 | /* SAS IO Unit Page 5 */ | ||
| 2091 | |||
| 2092 | typedef struct _MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS { | ||
| 2093 | U8 ControlFlags; /* 0x00 */ | ||
| 2094 | U8 PortWidthModGroup; /* 0x01 */ | ||
| 2095 | U16 InactivityTimerExponent; /* 0x02 */ | ||
| 2096 | U8 SATAPartialTimeout; /* 0x04 */ | ||
| 2097 | U8 Reserved2; /* 0x05 */ | ||
| 2098 | U8 SATASlumberTimeout; /* 0x06 */ | ||
| 2099 | U8 Reserved3; /* 0x07 */ | ||
| 2100 | U8 SASPartialTimeout; /* 0x08 */ | ||
| 2101 | U8 Reserved4; /* 0x09 */ | ||
| 2102 | U8 SASSlumberTimeout; /* 0x0A */ | ||
| 2103 | U8 Reserved5; /* 0x0B */ | ||
| 2104 | } MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS, | ||
| 2105 | MPI2_POINTER PTR_MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS, | ||
| 2106 | Mpi2SasIOUnit5PhyPmSettings_t, MPI2_POINTER pMpi2SasIOUnit5PhyPmSettings_t; | ||
| 2107 | |||
| 2108 | /* defines for ControlFlags field */ | ||
| 2109 | #define MPI2_SASIOUNIT5_CONTROL_SAS_SLUMBER_ENABLE (0x08) | ||
| 2110 | #define MPI2_SASIOUNIT5_CONTROL_SAS_PARTIAL_ENABLE (0x04) | ||
| 2111 | #define MPI2_SASIOUNIT5_CONTROL_SATA_SLUMBER_ENABLE (0x02) | ||
| 2112 | #define MPI2_SASIOUNIT5_CONTROL_SATA_PARTIAL_ENABLE (0x01) | ||
| 2113 | |||
| 2114 | /* defines for PortWidthModeGroup field */ | ||
| 2115 | #define MPI2_SASIOUNIT5_PWMG_DISABLE (0xFF) | ||
| 2116 | |||
| 2117 | /* defines for InactivityTimerExponent field */ | ||
| 2118 | #define MPI2_SASIOUNIT5_ITE_MASK_SAS_SLUMBER (0x7000) | ||
| 2119 | #define MPI2_SASIOUNIT5_ITE_SHIFT_SAS_SLUMBER (12) | ||
| 2120 | #define MPI2_SASIOUNIT5_ITE_MASK_SAS_PARTIAL (0x0700) | ||
| 2121 | #define MPI2_SASIOUNIT5_ITE_SHIFT_SAS_PARTIAL (8) | ||
| 2122 | #define MPI2_SASIOUNIT5_ITE_MASK_SATA_SLUMBER (0x0070) | ||
| 2123 | #define MPI2_SASIOUNIT5_ITE_SHIFT_SATA_SLUMBER (4) | ||
| 2124 | #define MPI2_SASIOUNIT5_ITE_MASK_SATA_PARTIAL (0x0007) | ||
| 2125 | #define MPI2_SASIOUNIT5_ITE_SHIFT_SATA_PARTIAL (0) | ||
| 2126 | |||
| 2127 | #define MPI2_SASIOUNIT5_ITE_TEN_SECONDS (7) | ||
| 2128 | #define MPI2_SASIOUNIT5_ITE_ONE_SECOND (6) | ||
| 2129 | #define MPI2_SASIOUNIT5_ITE_HUNDRED_MILLISECONDS (5) | ||
| 2130 | #define MPI2_SASIOUNIT5_ITE_TEN_MILLISECONDS (4) | ||
| 2131 | #define MPI2_SASIOUNIT5_ITE_ONE_MILLISECOND (3) | ||
| 2132 | #define MPI2_SASIOUNIT5_ITE_HUNDRED_MICROSECONDS (2) | ||
| 2133 | #define MPI2_SASIOUNIT5_ITE_TEN_MICROSECONDS (1) | ||
| 2134 | #define MPI2_SASIOUNIT5_ITE_ONE_MICROSECOND (0) | ||
| 2135 | |||
| 2136 | /* | ||
| 2137 | * Host code (drivers, BIOS, utilities, etc.) should leave this define set to | ||
| 2138 | * one and check the value returned for NumPhys at runtime. | ||
| 2139 | */ | ||
| 2140 | #ifndef MPI2_SAS_IOUNIT5_PHY_MAX | ||
| 2141 | #define MPI2_SAS_IOUNIT5_PHY_MAX (1) | ||
| 2142 | #endif | ||
| 2143 | |||
| 2144 | typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_5 { | ||
| 2145 | MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ | ||
| 2146 | U8 NumPhys; /* 0x08 */ | ||
| 2147 | U8 Reserved1; /* 0x09 */ | ||
| 2148 | U16 Reserved2; /* 0x0A */ | ||
| 2149 | U32 Reserved3; /* 0x0C */ | ||
| 2150 | MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS SASPhyPowerManagementSettings | ||
| 2151 | [MPI2_SAS_IOUNIT5_PHY_MAX]; /* 0x10 */ | ||
| 2152 | } MPI2_CONFIG_PAGE_SASIOUNIT_5, | ||
| 2153 | MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_5, | ||
| 2154 | Mpi2SasIOUnitPage5_t, MPI2_POINTER pMpi2SasIOUnitPage5_t; | ||
| 2155 | |||
| 2156 | #define MPI2_SASIOUNITPAGE5_PAGEVERSION (0x01) | ||
| 2157 | |||
| 2158 | |||
| 2159 | /* SAS IO Unit Page 6 */ | ||
| 2160 | |||
| 2161 | typedef struct _MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS { | ||
| 2162 | U8 CurrentStatus; /* 0x00 */ | ||
| 2163 | U8 CurrentModulation; /* 0x01 */ | ||
| 2164 | U8 CurrentUtilization; /* 0x02 */ | ||
| 2165 | U8 Reserved1; /* 0x03 */ | ||
| 2166 | U32 Reserved2; /* 0x04 */ | ||
| 2167 | } MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS, | ||
| 2168 | MPI2_POINTER PTR_MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS, | ||
| 2169 | Mpi2SasIOUnit6PortWidthModGroupStatus_t, | ||
| 2170 | MPI2_POINTER pMpi2SasIOUnit6PortWidthModGroupStatus_t; | ||
| 2171 | |||
| 2172 | /* defines for CurrentStatus field */ | ||
| 2173 | #define MPI2_SASIOUNIT6_STATUS_UNAVAILABLE (0x00) | ||
| 2174 | #define MPI2_SASIOUNIT6_STATUS_UNCONFIGURED (0x01) | ||
| 2175 | #define MPI2_SASIOUNIT6_STATUS_INVALID_CONFIG (0x02) | ||
| 2176 | #define MPI2_SASIOUNIT6_STATUS_LINK_DOWN (0x03) | ||
| 2177 | #define MPI2_SASIOUNIT6_STATUS_OBSERVATION_ONLY (0x04) | ||
| 2178 | #define MPI2_SASIOUNIT6_STATUS_INACTIVE (0x05) | ||
| 2179 | #define MPI2_SASIOUNIT6_STATUS_ACTIVE_IOUNIT (0x06) | ||
| 2180 | #define MPI2_SASIOUNIT6_STATUS_ACTIVE_HOST (0x07) | ||
| 2181 | |||
| 2182 | /* defines for CurrentModulation field */ | ||
| 2183 | #define MPI2_SASIOUNIT6_MODULATION_25_PERCENT (0x00) | ||
| 2184 | #define MPI2_SASIOUNIT6_MODULATION_50_PERCENT (0x01) | ||
| 2185 | #define MPI2_SASIOUNIT6_MODULATION_75_PERCENT (0x02) | ||
| 2186 | #define MPI2_SASIOUNIT6_MODULATION_100_PERCENT (0x03) | ||
| 2187 | |||
| 2188 | /* | ||
| 2189 | * Host code (drivers, BIOS, utilities, etc.) should leave this define set to | ||
| 2190 | * one and check the value returned for NumGroups at runtime. | ||
| 2191 | */ | ||
| 2192 | #ifndef MPI2_SAS_IOUNIT6_GROUP_MAX | ||
| 2193 | #define MPI2_SAS_IOUNIT6_GROUP_MAX (1) | ||
| 2194 | #endif | ||
| 2195 | |||
| 2196 | typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_6 { | ||
| 2197 | MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ | ||
| 2198 | U32 Reserved1; /* 0x08 */ | ||
| 2199 | U32 Reserved2; /* 0x0C */ | ||
| 2200 | U8 NumGroups; /* 0x10 */ | ||
| 2201 | U8 Reserved3; /* 0x11 */ | ||
| 2202 | U16 Reserved4; /* 0x12 */ | ||
| 2203 | MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS | ||
| 2204 | PortWidthModulationGroupStatus[MPI2_SAS_IOUNIT6_GROUP_MAX]; /* 0x14 */ | ||
| 2205 | } MPI2_CONFIG_PAGE_SASIOUNIT_6, | ||
| 2206 | MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_6, | ||
| 2207 | Mpi2SasIOUnitPage6_t, MPI2_POINTER pMpi2SasIOUnitPage6_t; | ||
| 2208 | |||
| 2209 | #define MPI2_SASIOUNITPAGE6_PAGEVERSION (0x00) | ||
| 2210 | |||
| 2211 | |||
| 2212 | /* SAS IO Unit Page 7 */ | ||
| 2213 | |||
| 2214 | typedef struct _MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS { | ||
| 2215 | U8 Flags; /* 0x00 */ | ||
| 2216 | U8 Reserved1; /* 0x01 */ | ||
| 2217 | U16 Reserved2; /* 0x02 */ | ||
| 2218 | U8 Threshold75Pct; /* 0x04 */ | ||
| 2219 | U8 Threshold50Pct; /* 0x05 */ | ||
| 2220 | U8 Threshold25Pct; /* 0x06 */ | ||
| 2221 | U8 Reserved3; /* 0x07 */ | ||
| 2222 | } MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS, | ||
| 2223 | MPI2_POINTER PTR_MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS, | ||
| 2224 | Mpi2SasIOUnit7PortWidthModGroupSettings_t, | ||
| 2225 | MPI2_POINTER pMpi2SasIOUnit7PortWidthModGroupSettings_t; | ||
| 2226 | |||
| 2227 | /* defines for Flags field */ | ||
| 2228 | #define MPI2_SASIOUNIT7_FLAGS_ENABLE_PORT_WIDTH_MODULATION (0x01) | ||
| 2229 | |||
| 2230 | |||
| 2231 | /* | ||
| 2232 | * Host code (drivers, BIOS, utilities, etc.) should leave this define set to | ||
| 2233 | * one and check the value returned for NumGroups at runtime. | ||
| 2234 | */ | ||
| 2235 | #ifndef MPI2_SAS_IOUNIT7_GROUP_MAX | ||
| 2236 | #define MPI2_SAS_IOUNIT7_GROUP_MAX (1) | ||
| 2237 | #endif | ||
| 2238 | |||
| 2239 | typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_7 { | ||
| 2240 | MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ | ||
| 2241 | U8 SamplingInterval; /* 0x08 */ | ||
| 2242 | U8 WindowLength; /* 0x09 */ | ||
| 2243 | U16 Reserved1; /* 0x0A */ | ||
| 2244 | U32 Reserved2; /* 0x0C */ | ||
| 2245 | U32 Reserved3; /* 0x10 */ | ||
| 2246 | U8 NumGroups; /* 0x14 */ | ||
| 2247 | U8 Reserved4; /* 0x15 */ | ||
| 2248 | U16 Reserved5; /* 0x16 */ | ||
| 2249 | MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS | ||
| 2250 | PortWidthModulationGroupSettings[MPI2_SAS_IOUNIT7_GROUP_MAX]; /* 0x18 */ | ||
| 2251 | } MPI2_CONFIG_PAGE_SASIOUNIT_7, | ||
| 2252 | MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_7, | ||
| 2253 | Mpi2SasIOUnitPage7_t, MPI2_POINTER pMpi2SasIOUnitPage7_t; | ||
| 2254 | |||
| 2255 | #define MPI2_SASIOUNITPAGE7_PAGEVERSION (0x00) | ||
| 2256 | |||
| 2257 | |||
| 2258 | /* SAS IO Unit Page 8 */ | ||
| 2259 | |||
| 2260 | typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_8 { | ||
| 2261 | MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ | ||
| 2262 | U32 Reserved1; /* 0x08 */ | ||
| 2263 | U32 PowerManagementCapabilities;/* 0x0C */ | ||
| 2264 | U32 Reserved2; /* 0x10 */ | ||
| 2265 | } MPI2_CONFIG_PAGE_SASIOUNIT_8, | ||
| 2266 | MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_8, | ||
| 2267 | Mpi2SasIOUnitPage8_t, MPI2_POINTER pMpi2SasIOUnitPage8_t; | ||
| 2268 | |||
| 2269 | #define MPI2_SASIOUNITPAGE8_PAGEVERSION (0x00) | ||
| 2270 | |||
| 2271 | /* defines for PowerManagementCapabilities field */ | ||
| 2272 | #define MPI2_SASIOUNIT8_PM_HOST_PORT_WIDTH_MOD (0x00001000) | ||
| 2273 | #define MPI2_SASIOUNIT8_PM_HOST_SAS_SLUMBER_MODE (0x00000800) | ||
| 2274 | #define MPI2_SASIOUNIT8_PM_HOST_SAS_PARTIAL_MODE (0x00000400) | ||
| 2275 | #define MPI2_SASIOUNIT8_PM_HOST_SATA_SLUMBER_MODE (0x00000200) | ||
| 2276 | #define MPI2_SASIOUNIT8_PM_HOST_SATA_PARTIAL_MODE (0x00000100) | ||
| 2277 | #define MPI2_SASIOUNIT8_PM_IOUNIT_PORT_WIDTH_MOD (0x00000010) | ||
| 2278 | #define MPI2_SASIOUNIT8_PM_IOUNIT_SAS_SLUMBER_MODE (0x00000008) | ||
| 2279 | #define MPI2_SASIOUNIT8_PM_IOUNIT_SAS_PARTIAL_MODE (0x00000004) | ||
| 2280 | #define MPI2_SASIOUNIT8_PM_IOUNIT_SATA_SLUMBER_MODE (0x00000002) | ||
| 2281 | #define MPI2_SASIOUNIT8_PM_IOUNIT_SATA_PARTIAL_MODE (0x00000001) | ||
| 2282 | |||
| 2283 | |||
| 2284 | |||
| 2285 | /* SAS IO Unit Page 16 */ | ||
| 2286 | |||
| 2287 | typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT16 { | ||
| 2288 | MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ | ||
| 2289 | U64 TimeStamp; /* 0x08 */ | ||
| 2290 | U32 Reserved1; /* 0x10 */ | ||
| 2291 | U32 Reserved2; /* 0x14 */ | ||
| 2292 | U32 FastPathPendedRequests; /* 0x18 */ | ||
| 2293 | U32 FastPathUnPendedRequests; /* 0x1C */ | ||
| 2294 | U32 FastPathHostRequestStarts; /* 0x20 */ | ||
| 2295 | U32 FastPathFirmwareRequestStarts; /* 0x24 */ | ||
| 2296 | U32 FastPathHostCompletions; /* 0x28 */ | ||
| 2297 | U32 FastPathFirmwareCompletions; /* 0x2C */ | ||
| 2298 | U32 NonFastPathRequestStarts; /* 0x30 */ | ||
| 2299 | U32 NonFastPathHostCompletions; /* 0x30 */ | ||
| 2300 | } MPI2_CONFIG_PAGE_SASIOUNIT16, | ||
| 2301 | MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT16, | ||
| 2302 | Mpi2SasIOUnitPage16_t, MPI2_POINTER pMpi2SasIOUnitPage16_t; | ||
| 2303 | |||
| 2304 | #define MPI2_SASIOUNITPAGE16_PAGEVERSION (0x00) | ||
| 2305 | |||
| 2306 | |||
| 2307 | /**************************************************************************** | ||
| 2308 | * SAS Expander Config Pages | ||
| 2309 | ****************************************************************************/ | ||
| 2310 | |||
| 2311 | /* SAS Expander Page 0 */ | ||
| 2312 | |||
| 2313 | typedef struct _MPI2_CONFIG_PAGE_EXPANDER_0 | ||
| 2314 | { | ||
| 2315 | MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ | ||
| 2316 | U8 PhysicalPort; /* 0x08 */ | ||
| 2317 | U8 ReportGenLength; /* 0x09 */ | ||
| 2318 | U16 EnclosureHandle; /* 0x0A */ | ||
| 2319 | U64 SASAddress; /* 0x0C */ | ||
| 2320 | U32 DiscoveryStatus; /* 0x14 */ | ||
| 2321 | U16 DevHandle; /* 0x18 */ | ||
| 2322 | U16 ParentDevHandle; /* 0x1A */ | ||
| 2323 | U16 ExpanderChangeCount; /* 0x1C */ | ||
| 2324 | U16 ExpanderRouteIndexes; /* 0x1E */ | ||
| 2325 | U8 NumPhys; /* 0x20 */ | ||
| 2326 | U8 SASLevel; /* 0x21 */ | ||
| 2327 | U16 Flags; /* 0x22 */ | ||
| 2328 | U16 STPBusInactivityTimeLimit; /* 0x24 */ | ||
| 2329 | U16 STPMaxConnectTimeLimit; /* 0x26 */ | ||
| 2330 | U16 STP_SMP_NexusLossTime; /* 0x28 */ | ||
| 2331 | U16 MaxNumRoutedSasAddresses; /* 0x2A */ | ||
| 2332 | U64 ActiveZoneManagerSASAddress;/* 0x2C */ | ||
| 2333 | U16 ZoneLockInactivityLimit; /* 0x34 */ | ||
| 2334 | U16 Reserved1; /* 0x36 */ | ||
| 2335 | U8 TimeToReducedFunc; /* 0x38 */ | ||
| 2336 | U8 InitialTimeToReducedFunc; /* 0x39 */ | ||
| 2337 | U8 MaxReducedFuncTime; /* 0x3A */ | ||
| 2338 | U8 Reserved2; /* 0x3B */ | ||
| 2339 | } MPI2_CONFIG_PAGE_EXPANDER_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_EXPANDER_0, | ||
| 2340 | Mpi2ExpanderPage0_t, MPI2_POINTER pMpi2ExpanderPage0_t; | ||
| 2341 | |||
| 2342 | #define MPI2_SASEXPANDER0_PAGEVERSION (0x06) | ||
| 2343 | |||
| 2344 | /* values for SAS Expander Page 0 DiscoveryStatus field */ | ||
| 2345 | #define MPI2_SAS_EXPANDER0_DS_MAX_ENCLOSURES_EXCEED (0x80000000) | ||
| 2346 | #define MPI2_SAS_EXPANDER0_DS_MAX_EXPANDERS_EXCEED (0x40000000) | ||
| 2347 | #define MPI2_SAS_EXPANDER0_DS_MAX_DEVICES_EXCEED (0x20000000) | ||
| 2348 | #define MPI2_SAS_EXPANDER0_DS_MAX_TOPO_PHYS_EXCEED (0x10000000) | ||
| 2349 | #define MPI2_SAS_EXPANDER0_DS_DOWNSTREAM_INITIATOR (0x08000000) | ||
| 2350 | #define MPI2_SAS_EXPANDER0_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE (0x00008000) | ||
| 2351 | #define MPI2_SAS_EXPANDER0_DS_EXP_MULTI_SUBTRACTIVE (0x00004000) | ||
| 2352 | #define MPI2_SAS_EXPANDER0_DS_MULTI_PORT_DOMAIN (0x00002000) | ||
| 2353 | #define MPI2_SAS_EXPANDER0_DS_TABLE_TO_SUBTRACTIVE_LINK (0x00001000) | ||
| 2354 | #define MPI2_SAS_EXPANDER0_DS_UNSUPPORTED_DEVICE (0x00000800) | ||
| 2355 | #define MPI2_SAS_EXPANDER0_DS_TABLE_LINK (0x00000400) | ||
| 2356 | #define MPI2_SAS_EXPANDER0_DS_SUBTRACTIVE_LINK (0x00000200) | ||
| 2357 | #define MPI2_SAS_EXPANDER0_DS_SMP_CRC_ERROR (0x00000100) | ||
| 2358 | #define MPI2_SAS_EXPANDER0_DS_SMP_FUNCTION_FAILED (0x00000080) | ||
| 2359 | #define MPI2_SAS_EXPANDER0_DS_INDEX_NOT_EXIST (0x00000040) | ||
| 2360 | #define MPI2_SAS_EXPANDER0_DS_OUT_ROUTE_ENTRIES (0x00000020) | ||
| 2361 | #define MPI2_SAS_EXPANDER0_DS_SMP_TIMEOUT (0x00000010) | ||
| 2362 | #define MPI2_SAS_EXPANDER0_DS_MULTIPLE_PORTS (0x00000004) | ||
| 2363 | #define MPI2_SAS_EXPANDER0_DS_UNADDRESSABLE_DEVICE (0x00000002) | ||
| 2364 | #define MPI2_SAS_EXPANDER0_DS_LOOP_DETECTED (0x00000001) | ||
| 2365 | |||
| 2366 | /* values for SAS Expander Page 0 Flags field */ | ||
| 2367 | #define MPI2_SAS_EXPANDER0_FLAGS_REDUCED_FUNCTIONALITY (0x2000) | ||
| 2368 | #define MPI2_SAS_EXPANDER0_FLAGS_ZONE_LOCKED (0x1000) | ||
| 2369 | #define MPI2_SAS_EXPANDER0_FLAGS_SUPPORTED_PHYSICAL_PRES (0x0800) | ||
| 2370 | #define MPI2_SAS_EXPANDER0_FLAGS_ASSERTED_PHYSICAL_PRES (0x0400) | ||
| 2371 | #define MPI2_SAS_EXPANDER0_FLAGS_ZONING_SUPPORT (0x0200) | ||
| 2372 | #define MPI2_SAS_EXPANDER0_FLAGS_ENABLED_ZONING (0x0100) | ||
| 2373 | #define MPI2_SAS_EXPANDER0_FLAGS_TABLE_TO_TABLE_SUPPORT (0x0080) | ||
| 2374 | #define MPI2_SAS_EXPANDER0_FLAGS_CONNECTOR_END_DEVICE (0x0010) | ||
| 2375 | #define MPI2_SAS_EXPANDER0_FLAGS_OTHERS_CONFIG (0x0004) | ||
| 2376 | #define MPI2_SAS_EXPANDER0_FLAGS_CONFIG_IN_PROGRESS (0x0002) | ||
| 2377 | #define MPI2_SAS_EXPANDER0_FLAGS_ROUTE_TABLE_CONFIG (0x0001) | ||
| 2378 | |||
| 2379 | |||
| 2380 | /* SAS Expander Page 1 */ | ||
| 2381 | |||
| 2382 | typedef struct _MPI2_CONFIG_PAGE_EXPANDER_1 | ||
| 2383 | { | ||
| 2384 | MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ | ||
| 2385 | U8 PhysicalPort; /* 0x08 */ | ||
| 2386 | U8 Reserved1; /* 0x09 */ | ||
| 2387 | U16 Reserved2; /* 0x0A */ | ||
| 2388 | U8 NumPhys; /* 0x0C */ | ||
| 2389 | U8 Phy; /* 0x0D */ | ||
| 2390 | U16 NumTableEntriesProgrammed; /* 0x0E */ | ||
| 2391 | U8 ProgrammedLinkRate; /* 0x10 */ | ||
| 2392 | U8 HwLinkRate; /* 0x11 */ | ||
| 2393 | U16 AttachedDevHandle; /* 0x12 */ | ||
| 2394 | U32 PhyInfo; /* 0x14 */ | ||
| 2395 | U32 AttachedDeviceInfo; /* 0x18 */ | ||
| 2396 | U16 ExpanderDevHandle; /* 0x1C */ | ||
| 2397 | U8 ChangeCount; /* 0x1E */ | ||
| 2398 | U8 NegotiatedLinkRate; /* 0x1F */ | ||
| 2399 | U8 PhyIdentifier; /* 0x20 */ | ||
| 2400 | U8 AttachedPhyIdentifier; /* 0x21 */ | ||
| 2401 | U8 Reserved3; /* 0x22 */ | ||
| 2402 | U8 DiscoveryInfo; /* 0x23 */ | ||
| 2403 | U32 AttachedPhyInfo; /* 0x24 */ | ||
| 2404 | U8 ZoneGroup; /* 0x28 */ | ||
| 2405 | U8 SelfConfigStatus; /* 0x29 */ | ||
| 2406 | U16 Reserved4; /* 0x2A */ | ||
| 2407 | } MPI2_CONFIG_PAGE_EXPANDER_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_EXPANDER_1, | ||
| 2408 | Mpi2ExpanderPage1_t, MPI2_POINTER pMpi2ExpanderPage1_t; | ||
| 2409 | |||
| 2410 | #define MPI2_SASEXPANDER1_PAGEVERSION (0x02) | ||
| 2411 | |||
| 2412 | /* use MPI2_SAS_PRATE_ defines for the ProgrammedLinkRate field */ | ||
| 2413 | |||
| 2414 | /* use MPI2_SAS_HWRATE_ defines for the HwLinkRate field */ | ||
| 2415 | |||
| 2416 | /* use MPI2_SAS_PHYINFO_ for the PhyInfo field */ | ||
| 2417 | |||
| 2418 | /* see mpi2_sas.h for the MPI2_SAS_DEVICE_INFO_ defines used for the AttachedDeviceInfo field */ | ||
| 2419 | |||
| 2420 | /* use MPI2_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */ | ||
| 2421 | |||
| 2422 | /* values for SAS Expander Page 1 DiscoveryInfo field */ | ||
| 2423 | #define MPI2_SAS_EXPANDER1_DISCINFO_BAD_PHY_DISABLED (0x04) | ||
| 2424 | #define MPI2_SAS_EXPANDER1_DISCINFO_LINK_STATUS_CHANGE (0x02) | ||
| 2425 | #define MPI2_SAS_EXPANDER1_DISCINFO_NO_ROUTING_ENTRIES (0x01) | ||
| 2426 | |||
| 2427 | /* use MPI2_SAS_APHYINFO_ defines for AttachedPhyInfo field */ | ||
| 2428 | |||
| 2429 | /**************************************************************************** | ||
| 2430 | * SAS Device Config Pages | ||
| 2431 | ****************************************************************************/ | ||
| 2432 | |||
| 2433 | /* SAS Device Page 0 */ | ||
| 2434 | |||
| 2435 | typedef struct _MPI2_CONFIG_PAGE_SAS_DEV_0 | ||
| 2436 | { | ||
| 2437 | MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ | ||
| 2438 | U16 Slot; /* 0x08 */ | ||
| 2439 | U16 EnclosureHandle; /* 0x0A */ | ||
| 2440 | U64 SASAddress; /* 0x0C */ | ||
| 2441 | U16 ParentDevHandle; /* 0x14 */ | ||
| 2442 | U8 PhyNum; /* 0x16 */ | ||
| 2443 | U8 AccessStatus; /* 0x17 */ | ||
| 2444 | U16 DevHandle; /* 0x18 */ | ||
| 2445 | U8 AttachedPhyIdentifier; /* 0x1A */ | ||
| 2446 | U8 ZoneGroup; /* 0x1B */ | ||
| 2447 | U32 DeviceInfo; /* 0x1C */ | ||
| 2448 | U16 Flags; /* 0x20 */ | ||
| 2449 | U8 PhysicalPort; /* 0x22 */ | ||
| 2450 | U8 MaxPortConnections; /* 0x23 */ | ||
| 2451 | U64 DeviceName; /* 0x24 */ | ||
| 2452 | U8 PortGroups; /* 0x2C */ | ||
| 2453 | U8 DmaGroup; /* 0x2D */ | ||
| 2454 | U8 ControlGroup; /* 0x2E */ | ||
| 2455 | U8 EnclosureLevel; /* 0x2F */ | ||
| 2456 | U8 ConnectorName[4]; /* 0x30 */ | ||
| 2457 | U32 Reserved3; /* 0x34 */ | ||
| 2458 | } MPI2_CONFIG_PAGE_SAS_DEV_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_DEV_0, | ||
| 2459 | Mpi2SasDevicePage0_t, MPI2_POINTER pMpi2SasDevicePage0_t; | ||
| 2460 | |||
| 2461 | #define MPI2_SASDEVICE0_PAGEVERSION (0x09) | ||
| 2462 | |||
| 2463 | /* values for SAS Device Page 0 AccessStatus field */ | ||
| 2464 | #define MPI2_SAS_DEVICE0_ASTATUS_NO_ERRORS (0x00) | ||
| 2465 | #define MPI2_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED (0x01) | ||
| 2466 | #define MPI2_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED (0x02) | ||
| 2467 | #define MPI2_SAS_DEVICE0_ASTATUS_SATA_AFFILIATION_CONFLICT (0x03) | ||
| 2468 | #define MPI2_SAS_DEVICE0_ASTATUS_SATA_NEEDS_INITIALIZATION (0x04) | ||
| 2469 | #define MPI2_SAS_DEVICE0_ASTATUS_ROUTE_NOT_ADDRESSABLE (0x05) | ||
| 2470 | #define MPI2_SAS_DEVICE0_ASTATUS_SMP_ERROR_NOT_ADDRESSABLE (0x06) | ||
| 2471 | #define MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED (0x07) | ||
| 2472 | /* specific values for SATA Init failures */ | ||
| 2473 | #define MPI2_SAS_DEVICE0_ASTATUS_SIF_UNKNOWN (0x10) | ||
| 2474 | #define MPI2_SAS_DEVICE0_ASTATUS_SIF_AFFILIATION_CONFLICT (0x11) | ||
| 2475 | #define MPI2_SAS_DEVICE0_ASTATUS_SIF_DIAG (0x12) | ||
| 2476 | #define MPI2_SAS_DEVICE0_ASTATUS_SIF_IDENTIFICATION (0x13) | ||
| 2477 | #define MPI2_SAS_DEVICE0_ASTATUS_SIF_CHECK_POWER (0x14) | ||
| 2478 | #define MPI2_SAS_DEVICE0_ASTATUS_SIF_PIO_SN (0x15) | ||
| 2479 | #define MPI2_SAS_DEVICE0_ASTATUS_SIF_MDMA_SN (0x16) | ||
| 2480 | #define MPI2_SAS_DEVICE0_ASTATUS_SIF_UDMA_SN (0x17) | ||
| 2481 | #define MPI2_SAS_DEVICE0_ASTATUS_SIF_ZONING_VIOLATION (0x18) | ||
| 2482 | #define MPI2_SAS_DEVICE0_ASTATUS_SIF_NOT_ADDRESSABLE (0x19) | ||
| 2483 | #define MPI2_SAS_DEVICE0_ASTATUS_SIF_MAX (0x1F) | ||
| 2484 | |||
| 2485 | /* see mpi2_sas.h for values for SAS Device Page 0 DeviceInfo values */ | ||
| 2486 | |||
| 2487 | /* values for SAS Device Page 0 Flags field */ | ||
| 2488 | #define MPI2_SAS_DEVICE0_FLAGS_UNAUTHORIZED_DEVICE (0x8000) | ||
| 2489 | #define MPI2_SAS_DEVICE0_FLAGS_SLUMBER_PM_CAPABLE (0x1000) | ||
| 2490 | #define MPI2_SAS_DEVICE0_FLAGS_PARTIAL_PM_CAPABLE (0x0800) | ||
| 2491 | #define MPI2_SAS_DEVICE0_FLAGS_SATA_ASYNCHRONOUS_NOTIFY (0x0400) | ||
| 2492 | #define MPI2_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE (0x0200) | ||
| 2493 | #define MPI2_SAS_DEVICE0_FLAGS_UNSUPPORTED_DEVICE (0x0100) | ||
| 2494 | #define MPI2_SAS_DEVICE0_FLAGS_SATA_48BIT_LBA_SUPPORTED (0x0080) | ||
| 2495 | #define MPI2_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED (0x0040) | ||
| 2496 | #define MPI2_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED (0x0020) | ||
| 2497 | #define MPI2_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED (0x0010) | ||
| 2498 | #define MPI2_SAS_DEVICE0_FLAGS_PORT_SELECTOR_ATTACH (0x0008) | ||
| 2499 | #define MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID (0x0002) | ||
| 2500 | #define MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT (0x0001) | ||
| 2501 | |||
| 2502 | |||
| 2503 | /* SAS Device Page 1 */ | ||
| 2504 | |||
| 2505 | typedef struct _MPI2_CONFIG_PAGE_SAS_DEV_1 | ||
| 2506 | { | ||
| 2507 | MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ | ||
| 2508 | U32 Reserved1; /* 0x08 */ | ||
| 2509 | U64 SASAddress; /* 0x0C */ | ||
| 2510 | U32 Reserved2; /* 0x14 */ | ||
| 2511 | U16 DevHandle; /* 0x18 */ | ||
| 2512 | U16 Reserved3; /* 0x1A */ | ||
| 2513 | U8 InitialRegDeviceFIS[20];/* 0x1C */ | ||
| 2514 | } MPI2_CONFIG_PAGE_SAS_DEV_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_DEV_1, | ||
| 2515 | Mpi2SasDevicePage1_t, MPI2_POINTER pMpi2SasDevicePage1_t; | ||
| 2516 | |||
| 2517 | #define MPI2_SASDEVICE1_PAGEVERSION (0x01) | ||
| 2518 | |||
| 2519 | |||
| 2520 | /**************************************************************************** | ||
| 2521 | * SAS PHY Config Pages | ||
| 2522 | ****************************************************************************/ | ||
| 2523 | |||
| 2524 | /* SAS PHY Page 0 */ | ||
| 2525 | |||
| 2526 | typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_0 | ||
| 2527 | { | ||
| 2528 | MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ | ||
| 2529 | U16 OwnerDevHandle; /* 0x08 */ | ||
| 2530 | U16 Reserved1; /* 0x0A */ | ||
| 2531 | U16 AttachedDevHandle; /* 0x0C */ | ||
| 2532 | U8 AttachedPhyIdentifier; /* 0x0E */ | ||
| 2533 | U8 Reserved2; /* 0x0F */ | ||
| 2534 | U32 AttachedPhyInfo; /* 0x10 */ | ||
| 2535 | U8 ProgrammedLinkRate; /* 0x14 */ | ||
| 2536 | U8 HwLinkRate; /* 0x15 */ | ||
| 2537 | U8 ChangeCount; /* 0x16 */ | ||
| 2538 | U8 Flags; /* 0x17 */ | ||
| 2539 | U32 PhyInfo; /* 0x18 */ | ||
| 2540 | U8 NegotiatedLinkRate; /* 0x1C */ | ||
| 2541 | U8 Reserved3; /* 0x1D */ | ||
| 2542 | U16 Reserved4; /* 0x1E */ | ||
| 2543 | } MPI2_CONFIG_PAGE_SAS_PHY_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PHY_0, | ||
| 2544 | Mpi2SasPhyPage0_t, MPI2_POINTER pMpi2SasPhyPage0_t; | ||
| 2545 | |||
| 2546 | #define MPI2_SASPHY0_PAGEVERSION (0x03) | ||
| 2547 | |||
| 2548 | /* use MPI2_SAS_APHYINFO_ defines for AttachedPhyInfo field */ | ||
| 2549 | |||
| 2550 | /* use MPI2_SAS_PRATE_ defines for the ProgrammedLinkRate field */ | ||
| 2551 | |||
| 2552 | /* use MPI2_SAS_HWRATE_ defines for the HwLinkRate field */ | ||
| 2553 | |||
| 2554 | /* values for SAS PHY Page 0 Flags field */ | ||
| 2555 | #define MPI2_SAS_PHY0_FLAGS_SGPIO_DIRECT_ATTACH_ENC (0x01) | ||
| 2556 | |||
| 2557 | /* use MPI2_SAS_PHYINFO_ for the PhyInfo field */ | ||
| 2558 | |||
| 2559 | /* use MPI2_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */ | ||
| 2560 | |||
| 2561 | |||
| 2562 | /* SAS PHY Page 1 */ | ||
| 2563 | |||
| 2564 | typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_1 | ||
| 2565 | { | ||
| 2566 | MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ | ||
| 2567 | U32 Reserved1; /* 0x08 */ | ||
| 2568 | U32 InvalidDwordCount; /* 0x0C */ | ||
| 2569 | U32 RunningDisparityErrorCount; /* 0x10 */ | ||
| 2570 | U32 LossDwordSynchCount; /* 0x14 */ | ||
| 2571 | U32 PhyResetProblemCount; /* 0x18 */ | ||
| 2572 | } MPI2_CONFIG_PAGE_SAS_PHY_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PHY_1, | ||
| 2573 | Mpi2SasPhyPage1_t, MPI2_POINTER pMpi2SasPhyPage1_t; | ||
| 2574 | |||
| 2575 | #define MPI2_SASPHY1_PAGEVERSION (0x01) | ||
| 2576 | |||
| 2577 | |||
| 2578 | /* SAS PHY Page 2 */ | ||
| 2579 | |||
| 2580 | typedef struct _MPI2_SASPHY2_PHY_EVENT { | ||
| 2581 | U8 PhyEventCode; /* 0x00 */ | ||
| 2582 | U8 Reserved1; /* 0x01 */ | ||
| 2583 | U16 Reserved2; /* 0x02 */ | ||
| 2584 | U32 PhyEventInfo; /* 0x04 */ | ||
| 2585 | } MPI2_SASPHY2_PHY_EVENT, MPI2_POINTER PTR_MPI2_SASPHY2_PHY_EVENT, | ||
| 2586 | Mpi2SasPhy2PhyEvent_t, MPI2_POINTER pMpi2SasPhy2PhyEvent_t; | ||
| 2587 | |||
| 2588 | /* use MPI2_SASPHY3_EVENT_CODE_ for the PhyEventCode field */ | ||
| 2589 | |||
| 2590 | |||
| 2591 | /* | ||
| 2592 | * Host code (drivers, BIOS, utilities, etc.) should leave this define set to | ||
| 2593 | * one and check the value returned for NumPhyEvents at runtime. | ||
| 2594 | */ | ||
| 2595 | #ifndef MPI2_SASPHY2_PHY_EVENT_MAX | ||
| 2596 | #define MPI2_SASPHY2_PHY_EVENT_MAX (1) | ||
| 2597 | #endif | ||
| 2598 | |||
| 2599 | typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_2 { | ||
| 2600 | MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ | ||
| 2601 | U32 Reserved1; /* 0x08 */ | ||
| 2602 | U8 NumPhyEvents; /* 0x0C */ | ||
| 2603 | U8 Reserved2; /* 0x0D */ | ||
| 2604 | U16 Reserved3; /* 0x0E */ | ||
| 2605 | MPI2_SASPHY2_PHY_EVENT PhyEvent[MPI2_SASPHY2_PHY_EVENT_MAX]; | ||
| 2606 | /* 0x10 */ | ||
| 2607 | } MPI2_CONFIG_PAGE_SAS_PHY_2, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PHY_2, | ||
| 2608 | Mpi2SasPhyPage2_t, MPI2_POINTER pMpi2SasPhyPage2_t; | ||
| 2609 | |||
| 2610 | #define MPI2_SASPHY2_PAGEVERSION (0x00) | ||
| 2611 | |||
| 2612 | |||
| 2613 | /* SAS PHY Page 3 */ | ||
| 2614 | |||
| 2615 | typedef struct _MPI2_SASPHY3_PHY_EVENT_CONFIG { | ||
| 2616 | U8 PhyEventCode; /* 0x00 */ | ||
| 2617 | U8 Reserved1; /* 0x01 */ | ||
| 2618 | U16 Reserved2; /* 0x02 */ | ||
| 2619 | U8 CounterType; /* 0x04 */ | ||
| 2620 | U8 ThresholdWindow; /* 0x05 */ | ||
| 2621 | U8 TimeUnits; /* 0x06 */ | ||
| 2622 | U8 Reserved3; /* 0x07 */ | ||
| 2623 | U32 EventThreshold; /* 0x08 */ | ||
| 2624 | U16 ThresholdFlags; /* 0x0C */ | ||
| 2625 | U16 Reserved4; /* 0x0E */ | ||
| 2626 | } MPI2_SASPHY3_PHY_EVENT_CONFIG, MPI2_POINTER PTR_MPI2_SASPHY3_PHY_EVENT_CONFIG, | ||
| 2627 | Mpi2SasPhy3PhyEventConfig_t, MPI2_POINTER pMpi2SasPhy3PhyEventConfig_t; | ||
| 2628 | |||
| 2629 | /* values for PhyEventCode field */ | ||
| 2630 | #define MPI2_SASPHY3_EVENT_CODE_NO_EVENT (0x00) | ||
| 2631 | #define MPI2_SASPHY3_EVENT_CODE_INVALID_DWORD (0x01) | ||
| 2632 | #define MPI2_SASPHY3_EVENT_CODE_RUNNING_DISPARITY_ERROR (0x02) | ||
| 2633 | #define MPI2_SASPHY3_EVENT_CODE_LOSS_DWORD_SYNC (0x03) | ||
| 2634 | #define MPI2_SASPHY3_EVENT_CODE_PHY_RESET_PROBLEM (0x04) | ||
| 2635 | #define MPI2_SASPHY3_EVENT_CODE_ELASTICITY_BUF_OVERFLOW (0x05) | ||
| 2636 | #define MPI2_SASPHY3_EVENT_CODE_RX_ERROR (0x06) | ||
| 2637 | #define MPI2_SASPHY3_EVENT_CODE_RX_ADDR_FRAME_ERROR (0x20) | ||
| 2638 | #define MPI2_SASPHY3_EVENT_CODE_TX_AC_OPEN_REJECT (0x21) | ||
| 2639 | #define MPI2_SASPHY3_EVENT_CODE_RX_AC_OPEN_REJECT (0x22) | ||
| 2640 | #define MPI2_SASPHY3_EVENT_CODE_TX_RC_OPEN_REJECT (0x23) | ||
| 2641 | #define MPI2_SASPHY3_EVENT_CODE_RX_RC_OPEN_REJECT (0x24) | ||
| 2642 | #define MPI2_SASPHY3_EVENT_CODE_RX_AIP_PARTIAL_WAITING_ON (0x25) | ||
| 2643 | #define MPI2_SASPHY3_EVENT_CODE_RX_AIP_CONNECT_WAITING_ON (0x26) | ||
| 2644 | #define MPI2_SASPHY3_EVENT_CODE_TX_BREAK (0x27) | ||
| 2645 | #define MPI2_SASPHY3_EVENT_CODE_RX_BREAK (0x28) | ||
| 2646 | #define MPI2_SASPHY3_EVENT_CODE_BREAK_TIMEOUT (0x29) | ||
| 2647 | #define MPI2_SASPHY3_EVENT_CODE_CONNECTION (0x2A) | ||
| 2648 | #define MPI2_SASPHY3_EVENT_CODE_PEAKTX_PATHWAY_BLOCKED (0x2B) | ||
| 2649 | #define MPI2_SASPHY3_EVENT_CODE_PEAKTX_ARB_WAIT_TIME (0x2C) | ||
| 2650 | #define MPI2_SASPHY3_EVENT_CODE_PEAK_ARB_WAIT_TIME (0x2D) | ||
| 2651 | #define MPI2_SASPHY3_EVENT_CODE_PEAK_CONNECT_TIME (0x2E) | ||
| 2652 | #define MPI2_SASPHY3_EVENT_CODE_TX_SSP_FRAMES (0x40) | ||
| 2653 | #define MPI2_SASPHY3_EVENT_CODE_RX_SSP_FRAMES (0x41) | ||
| 2654 | #define MPI2_SASPHY3_EVENT_CODE_TX_SSP_ERROR_FRAMES (0x42) | ||
| 2655 | #define MPI2_SASPHY3_EVENT_CODE_RX_SSP_ERROR_FRAMES (0x43) | ||
| 2656 | #define MPI2_SASPHY3_EVENT_CODE_TX_CREDIT_BLOCKED (0x44) | ||
| 2657 | #define MPI2_SASPHY3_EVENT_CODE_RX_CREDIT_BLOCKED (0x45) | ||
| 2658 | #define MPI2_SASPHY3_EVENT_CODE_TX_SATA_FRAMES (0x50) | ||
| 2659 | #define MPI2_SASPHY3_EVENT_CODE_RX_SATA_FRAMES (0x51) | ||
| 2660 | #define MPI2_SASPHY3_EVENT_CODE_SATA_OVERFLOW (0x52) | ||
| 2661 | #define MPI2_SASPHY3_EVENT_CODE_TX_SMP_FRAMES (0x60) | ||
| 2662 | #define MPI2_SASPHY3_EVENT_CODE_RX_SMP_FRAMES (0x61) | ||
| 2663 | #define MPI2_SASPHY3_EVENT_CODE_RX_SMP_ERROR_FRAMES (0x63) | ||
| 2664 | #define MPI2_SASPHY3_EVENT_CODE_HOTPLUG_TIMEOUT (0xD0) | ||
| 2665 | #define MPI2_SASPHY3_EVENT_CODE_MISALIGNED_MUX_PRIMITIVE (0xD1) | ||
| 2666 | #define MPI2_SASPHY3_EVENT_CODE_RX_AIP (0xD2) | ||
| 2667 | |||
| 2668 | /* values for the CounterType field */ | ||
| 2669 | #define MPI2_SASPHY3_COUNTER_TYPE_WRAPPING (0x00) | ||
| 2670 | #define MPI2_SASPHY3_COUNTER_TYPE_SATURATING (0x01) | ||
| 2671 | #define MPI2_SASPHY3_COUNTER_TYPE_PEAK_VALUE (0x02) | ||
| 2672 | |||
| 2673 | /* values for the TimeUnits field */ | ||
| 2674 | #define MPI2_SASPHY3_TIME_UNITS_10_MICROSECONDS (0x00) | ||
| 2675 | #define MPI2_SASPHY3_TIME_UNITS_100_MICROSECONDS (0x01) | ||
| 2676 | #define MPI2_SASPHY3_TIME_UNITS_1_MILLISECOND (0x02) | ||
| 2677 | #define MPI2_SASPHY3_TIME_UNITS_10_MILLISECONDS (0x03) | ||
| 2678 | |||
| 2679 | /* values for the ThresholdFlags field */ | ||
| 2680 | #define MPI2_SASPHY3_TFLAGS_PHY_RESET (0x0002) | ||
| 2681 | #define MPI2_SASPHY3_TFLAGS_EVENT_NOTIFY (0x0001) | ||
| 2682 | |||
| 2683 | /* | ||
| 2684 | * Host code (drivers, BIOS, utilities, etc.) should leave this define set to | ||
| 2685 | * one and check the value returned for NumPhyEvents at runtime. | ||
| 2686 | */ | ||
| 2687 | #ifndef MPI2_SASPHY3_PHY_EVENT_MAX | ||
| 2688 | #define MPI2_SASPHY3_PHY_EVENT_MAX (1) | ||
| 2689 | #endif | ||
| 2690 | |||
| 2691 | typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_3 { | ||
| 2692 | MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ | ||
| 2693 | U32 Reserved1; /* 0x08 */ | ||
| 2694 | U8 NumPhyEvents; /* 0x0C */ | ||
| 2695 | U8 Reserved2; /* 0x0D */ | ||
| 2696 | U16 Reserved3; /* 0x0E */ | ||
| 2697 | MPI2_SASPHY3_PHY_EVENT_CONFIG PhyEventConfig | ||
| 2698 | [MPI2_SASPHY3_PHY_EVENT_MAX]; /* 0x10 */ | ||
| 2699 | } MPI2_CONFIG_PAGE_SAS_PHY_3, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PHY_3, | ||
| 2700 | Mpi2SasPhyPage3_t, MPI2_POINTER pMpi2SasPhyPage3_t; | ||
| 2701 | |||
| 2702 | #define MPI2_SASPHY3_PAGEVERSION (0x00) | ||
| 2703 | |||
| 2704 | |||
| 2705 | /* SAS PHY Page 4 */ | ||
| 2706 | |||
| 2707 | typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_4 { | ||
| 2708 | MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ | ||
| 2709 | U16 Reserved1; /* 0x08 */ | ||
| 2710 | U8 Reserved2; /* 0x0A */ | ||
| 2711 | U8 Flags; /* 0x0B */ | ||
| 2712 | U8 InitialFrame[28]; /* 0x0C */ | ||
| 2713 | } MPI2_CONFIG_PAGE_SAS_PHY_4, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PHY_4, | ||
| 2714 | Mpi2SasPhyPage4_t, MPI2_POINTER pMpi2SasPhyPage4_t; | ||
| 2715 | |||
| 2716 | #define MPI2_SASPHY4_PAGEVERSION (0x00) | ||
| 2717 | |||
| 2718 | /* values for the Flags field */ | ||
| 2719 | #define MPI2_SASPHY4_FLAGS_FRAME_VALID (0x02) | ||
| 2720 | #define MPI2_SASPHY4_FLAGS_SATA_FRAME (0x01) | ||
| 2721 | |||
| 2722 | |||
| 2723 | |||
| 2724 | |||
| 2725 | /**************************************************************************** | ||
| 2726 | * SAS Port Config Pages | ||
| 2727 | ****************************************************************************/ | ||
| 2728 | |||
| 2729 | /* SAS Port Page 0 */ | ||
| 2730 | |||
| 2731 | typedef struct _MPI2_CONFIG_PAGE_SAS_PORT_0 | ||
| 2732 | { | ||
| 2733 | MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ | ||
| 2734 | U8 PortNumber; /* 0x08 */ | ||
| 2735 | U8 PhysicalPort; /* 0x09 */ | ||
| 2736 | U8 PortWidth; /* 0x0A */ | ||
| 2737 | U8 PhysicalPortWidth; /* 0x0B */ | ||
| 2738 | U8 ZoneGroup; /* 0x0C */ | ||
| 2739 | U8 Reserved1; /* 0x0D */ | ||
| 2740 | U16 Reserved2; /* 0x0E */ | ||
| 2741 | U64 SASAddress; /* 0x10 */ | ||
| 2742 | U32 DeviceInfo; /* 0x18 */ | ||
| 2743 | U32 Reserved3; /* 0x1C */ | ||
| 2744 | U32 Reserved4; /* 0x20 */ | ||
| 2745 | } MPI2_CONFIG_PAGE_SAS_PORT_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PORT_0, | ||
| 2746 | Mpi2SasPortPage0_t, MPI2_POINTER pMpi2SasPortPage0_t; | ||
| 2747 | |||
| 2748 | #define MPI2_SASPORT0_PAGEVERSION (0x00) | ||
| 2749 | |||
| 2750 | /* see mpi2_sas.h for values for SAS Port Page 0 DeviceInfo values */ | ||
| 2751 | |||
| 2752 | |||
| 2753 | /**************************************************************************** | ||
| 2754 | * SAS Enclosure Config Pages | ||
| 2755 | ****************************************************************************/ | ||
| 2756 | |||
| 2757 | /* SAS Enclosure Page 0 */ | ||
| 2758 | |||
| 2759 | typedef struct _MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0 | ||
| 2760 | { | ||
| 2761 | MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ | ||
| 2762 | U32 Reserved1; /* 0x08 */ | ||
| 2763 | U64 EnclosureLogicalID; /* 0x0C */ | ||
| 2764 | U16 Flags; /* 0x14 */ | ||
| 2765 | U16 EnclosureHandle; /* 0x16 */ | ||
| 2766 | U16 NumSlots; /* 0x18 */ | ||
| 2767 | U16 StartSlot; /* 0x1A */ | ||
| 2768 | U8 Reserved2; /* 0x1C */ | ||
| 2769 | U8 EnclosureLevel; /* 0x1D */ | ||
| 2770 | U16 SEPDevHandle; /* 0x1E */ | ||
| 2771 | U32 Reserved3; /* 0x20 */ | ||
| 2772 | U32 Reserved4; /* 0x24 */ | ||
| 2773 | } MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0, | ||
| 2774 | MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0, | ||
| 2775 | Mpi2SasEnclosurePage0_t, MPI2_POINTER pMpi2SasEnclosurePage0_t; | ||
| 2776 | |||
| 2777 | #define MPI2_SASENCLOSURE0_PAGEVERSION (0x04) | ||
| 2778 | |||
| 2779 | /* values for SAS Enclosure Page 0 Flags field */ | ||
| 2780 | #define MPI2_SAS_ENCLS0_FLAGS_ENCL_LEVEL_VALID (0x0010) | ||
| 2781 | #define MPI2_SAS_ENCLS0_FLAGS_MNG_MASK (0x000F) | ||
| 2782 | #define MPI2_SAS_ENCLS0_FLAGS_MNG_UNKNOWN (0x0000) | ||
| 2783 | #define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_SES (0x0001) | ||
| 2784 | #define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_SGPIO (0x0002) | ||
| 2785 | #define MPI2_SAS_ENCLS0_FLAGS_MNG_EXP_SGPIO (0x0003) | ||
| 2786 | #define MPI2_SAS_ENCLS0_FLAGS_MNG_SES_ENCLOSURE (0x0004) | ||
| 2787 | #define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_GPIO (0x0005) | ||
| 2788 | |||
| 2789 | |||
| 2790 | /**************************************************************************** | ||
| 2791 | * Log Config Page | ||
| 2792 | ****************************************************************************/ | ||
| 2793 | |||
| 2794 | /* Log Page 0 */ | ||
| 2795 | |||
| 2796 | /* | ||
| 2797 | * Host code (drivers, BIOS, utilities, etc.) should leave this define set to | ||
| 2798 | * one and check the value returned for NumLogEntries at runtime. | ||
| 2799 | */ | ||
| 2800 | #ifndef MPI2_LOG_0_NUM_LOG_ENTRIES | ||
| 2801 | #define MPI2_LOG_0_NUM_LOG_ENTRIES (1) | ||
| 2802 | #endif | ||
| 2803 | |||
| 2804 | #define MPI2_LOG_0_LOG_DATA_LENGTH (0x1C) | ||
| 2805 | |||
| 2806 | typedef struct _MPI2_LOG_0_ENTRY | ||
| 2807 | { | ||
| 2808 | U64 TimeStamp; /* 0x00 */ | ||
| 2809 | U32 Reserved1; /* 0x08 */ | ||
| 2810 | U16 LogSequence; /* 0x0C */ | ||
| 2811 | U16 LogEntryQualifier; /* 0x0E */ | ||
| 2812 | U8 VP_ID; /* 0x10 */ | ||
| 2813 | U8 VF_ID; /* 0x11 */ | ||
| 2814 | U16 Reserved2; /* 0x12 */ | ||
| 2815 | U8 LogData[MPI2_LOG_0_LOG_DATA_LENGTH];/* 0x14 */ | ||
| 2816 | } MPI2_LOG_0_ENTRY, MPI2_POINTER PTR_MPI2_LOG_0_ENTRY, | ||
| 2817 | Mpi2Log0Entry_t, MPI2_POINTER pMpi2Log0Entry_t; | ||
| 2818 | |||
| 2819 | /* values for Log Page 0 LogEntry LogEntryQualifier field */ | ||
| 2820 | #define MPI2_LOG_0_ENTRY_QUAL_ENTRY_UNUSED (0x0000) | ||
| 2821 | #define MPI2_LOG_0_ENTRY_QUAL_POWER_ON_RESET (0x0001) | ||
| 2822 | #define MPI2_LOG_0_ENTRY_QUAL_TIMESTAMP_UPDATE (0x0002) | ||
| 2823 | #define MPI2_LOG_0_ENTRY_QUAL_MIN_IMPLEMENT_SPEC (0x8000) | ||
| 2824 | #define MPI2_LOG_0_ENTRY_QUAL_MAX_IMPLEMENT_SPEC (0xFFFF) | ||
| 2825 | |||
| 2826 | typedef struct _MPI2_CONFIG_PAGE_LOG_0 | ||
| 2827 | { | ||
| 2828 | MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ | ||
| 2829 | U32 Reserved1; /* 0x08 */ | ||
| 2830 | U32 Reserved2; /* 0x0C */ | ||
| 2831 | U16 NumLogEntries; /* 0x10 */ | ||
| 2832 | U16 Reserved3; /* 0x12 */ | ||
| 2833 | MPI2_LOG_0_ENTRY LogEntry[MPI2_LOG_0_NUM_LOG_ENTRIES]; /* 0x14 */ | ||
| 2834 | } MPI2_CONFIG_PAGE_LOG_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_LOG_0, | ||
| 2835 | Mpi2LogPage0_t, MPI2_POINTER pMpi2LogPage0_t; | ||
| 2836 | |||
| 2837 | #define MPI2_LOG_0_PAGEVERSION (0x02) | ||
| 2838 | |||
| 2839 | |||
| 2840 | /**************************************************************************** | ||
| 2841 | * RAID Config Page | ||
| 2842 | ****************************************************************************/ | ||
| 2843 | |||
| 2844 | /* RAID Page 0 */ | ||
| 2845 | |||
| 2846 | /* | ||
| 2847 | * Host code (drivers, BIOS, utilities, etc.) should leave this define set to | ||
| 2848 | * one and check the value returned for NumElements at runtime. | ||
| 2849 | */ | ||
| 2850 | #ifndef MPI2_RAIDCONFIG0_MAX_ELEMENTS | ||
| 2851 | #define MPI2_RAIDCONFIG0_MAX_ELEMENTS (1) | ||
| 2852 | #endif | ||
| 2853 | |||
| 2854 | typedef struct _MPI2_RAIDCONFIG0_CONFIG_ELEMENT | ||
| 2855 | { | ||
| 2856 | U16 ElementFlags; /* 0x00 */ | ||
| 2857 | U16 VolDevHandle; /* 0x02 */ | ||
| 2858 | U8 HotSparePool; /* 0x04 */ | ||
| 2859 | U8 PhysDiskNum; /* 0x05 */ | ||
| 2860 | U16 PhysDiskDevHandle; /* 0x06 */ | ||
| 2861 | } MPI2_RAIDCONFIG0_CONFIG_ELEMENT, | ||
| 2862 | MPI2_POINTER PTR_MPI2_RAIDCONFIG0_CONFIG_ELEMENT, | ||
| 2863 | Mpi2RaidConfig0ConfigElement_t, MPI2_POINTER pMpi2RaidConfig0ConfigElement_t; | ||
| 2864 | |||
| 2865 | /* values for the ElementFlags field */ | ||
| 2866 | #define MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE (0x000F) | ||
| 2867 | #define MPI2_RAIDCONFIG0_EFLAGS_VOLUME_ELEMENT (0x0000) | ||
| 2868 | #define MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT (0x0001) | ||
| 2869 | #define MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT (0x0002) | ||
| 2870 | #define MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT (0x0003) | ||
| 2871 | |||
| 2872 | |||
| 2873 | typedef struct _MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0 | ||
| 2874 | { | ||
| 2875 | MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ | ||
| 2876 | U8 NumHotSpares; /* 0x08 */ | ||
| 2877 | U8 NumPhysDisks; /* 0x09 */ | ||
| 2878 | U8 NumVolumes; /* 0x0A */ | ||
| 2879 | U8 ConfigNum; /* 0x0B */ | ||
| 2880 | U32 Flags; /* 0x0C */ | ||
| 2881 | U8 ConfigGUID[24]; /* 0x10 */ | ||
| 2882 | U32 Reserved1; /* 0x28 */ | ||
| 2883 | U8 NumElements; /* 0x2C */ | ||
| 2884 | U8 Reserved2; /* 0x2D */ | ||
| 2885 | U16 Reserved3; /* 0x2E */ | ||
| 2886 | MPI2_RAIDCONFIG0_CONFIG_ELEMENT ConfigElement[MPI2_RAIDCONFIG0_MAX_ELEMENTS]; /* 0x30 */ | ||
| 2887 | } MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0, | ||
| 2888 | MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0, | ||
| 2889 | Mpi2RaidConfigurationPage0_t, MPI2_POINTER pMpi2RaidConfigurationPage0_t; | ||
| 2890 | |||
| 2891 | #define MPI2_RAIDCONFIG0_PAGEVERSION (0x00) | ||
| 2892 | |||
| 2893 | /* values for RAID Configuration Page 0 Flags field */ | ||
| 2894 | #define MPI2_RAIDCONFIG0_FLAG_FOREIGN_CONFIG (0x00000001) | ||
| 2895 | |||
| 2896 | |||
| 2897 | /**************************************************************************** | ||
| 2898 | * Driver Persistent Mapping Config Pages | ||
| 2899 | ****************************************************************************/ | ||
| 2900 | |||
| 2901 | /* Driver Persistent Mapping Page 0 */ | ||
| 2902 | |||
| 2903 | typedef struct _MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY | ||
| 2904 | { | ||
| 2905 | U64 PhysicalIdentifier; /* 0x00 */ | ||
| 2906 | U16 MappingInformation; /* 0x08 */ | ||
| 2907 | U16 DeviceIndex; /* 0x0A */ | ||
| 2908 | U32 PhysicalBitsMapping; /* 0x0C */ | ||
| 2909 | U32 Reserved1; /* 0x10 */ | ||
| 2910 | } MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY, | ||
| 2911 | MPI2_POINTER PTR_MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY, | ||
| 2912 | Mpi2DriverMap0Entry_t, MPI2_POINTER pMpi2DriverMap0Entry_t; | ||
| 2913 | |||
| 2914 | typedef struct _MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 | ||
| 2915 | { | ||
| 2916 | MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ | ||
| 2917 | MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY Entry; /* 0x08 */ | ||
| 2918 | } MPI2_CONFIG_PAGE_DRIVER_MAPPING_0, | ||
| 2919 | MPI2_POINTER PTR_MPI2_CONFIG_PAGE_DRIVER_MAPPING_0, | ||
| 2920 | Mpi2DriverMappingPage0_t, MPI2_POINTER pMpi2DriverMappingPage0_t; | ||
| 2921 | |||
| 2922 | #define MPI2_DRIVERMAPPING0_PAGEVERSION (0x00) | ||
| 2923 | |||
| 2924 | /* values for Driver Persistent Mapping Page 0 MappingInformation field */ | ||
| 2925 | #define MPI2_DRVMAP0_MAPINFO_SLOT_MASK (0x07F0) | ||
| 2926 | #define MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT (4) | ||
| 2927 | #define MPI2_DRVMAP0_MAPINFO_MISSING_MASK (0x000F) | ||
| 2928 | |||
| 2929 | |||
| 2930 | /**************************************************************************** | ||
| 2931 | * Ethernet Config Pages | ||
| 2932 | ****************************************************************************/ | ||
| 2933 | |||
| 2934 | /* Ethernet Page 0 */ | ||
| 2935 | |||
| 2936 | /* IP address (union of IPv4 and IPv6) */ | ||
| 2937 | typedef union _MPI2_ETHERNET_IP_ADDR { | ||
| 2938 | U32 IPv4Addr; | ||
| 2939 | U32 IPv6Addr[4]; | ||
| 2940 | } MPI2_ETHERNET_IP_ADDR, MPI2_POINTER PTR_MPI2_ETHERNET_IP_ADDR, | ||
| 2941 | Mpi2EthernetIpAddr_t, MPI2_POINTER pMpi2EthernetIpAddr_t; | ||
| 2942 | |||
| 2943 | #define MPI2_ETHERNET_HOST_NAME_LENGTH (32) | ||
| 2944 | |||
| 2945 | typedef struct _MPI2_CONFIG_PAGE_ETHERNET_0 { | ||
| 2946 | MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ | ||
| 2947 | U8 NumInterfaces; /* 0x08 */ | ||
| 2948 | U8 Reserved0; /* 0x09 */ | ||
| 2949 | U16 Reserved1; /* 0x0A */ | ||
| 2950 | U32 Status; /* 0x0C */ | ||
| 2951 | U8 MediaState; /* 0x10 */ | ||
| 2952 | U8 Reserved2; /* 0x11 */ | ||
| 2953 | U16 Reserved3; /* 0x12 */ | ||
| 2954 | U8 MacAddress[6]; /* 0x14 */ | ||
| 2955 | U8 Reserved4; /* 0x1A */ | ||
| 2956 | U8 Reserved5; /* 0x1B */ | ||
| 2957 | MPI2_ETHERNET_IP_ADDR IpAddress; /* 0x1C */ | ||
| 2958 | MPI2_ETHERNET_IP_ADDR SubnetMask; /* 0x2C */ | ||
| 2959 | MPI2_ETHERNET_IP_ADDR GatewayIpAddress; /* 0x3C */ | ||
| 2960 | MPI2_ETHERNET_IP_ADDR DNS1IpAddress; /* 0x4C */ | ||
| 2961 | MPI2_ETHERNET_IP_ADDR DNS2IpAddress; /* 0x5C */ | ||
| 2962 | MPI2_ETHERNET_IP_ADDR DhcpIpAddress; /* 0x6C */ | ||
| 2963 | U8 HostName | ||
| 2964 | [MPI2_ETHERNET_HOST_NAME_LENGTH];/* 0x7C */ | ||
| 2965 | } MPI2_CONFIG_PAGE_ETHERNET_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_ETHERNET_0, | ||
| 2966 | Mpi2EthernetPage0_t, MPI2_POINTER pMpi2EthernetPage0_t; | ||
| 2967 | |||
| 2968 | #define MPI2_ETHERNETPAGE0_PAGEVERSION (0x00) | ||
| 2969 | |||
| 2970 | /* values for Ethernet Page 0 Status field */ | ||
| 2971 | #define MPI2_ETHPG0_STATUS_IPV6_CAPABLE (0x80000000) | ||
| 2972 | #define MPI2_ETHPG0_STATUS_IPV4_CAPABLE (0x40000000) | ||
| 2973 | #define MPI2_ETHPG0_STATUS_CONSOLE_CONNECTED (0x20000000) | ||
| 2974 | #define MPI2_ETHPG0_STATUS_DEFAULT_IF (0x00000100) | ||
| 2975 | #define MPI2_ETHPG0_STATUS_FW_DWNLD_ENABLED (0x00000080) | ||
| 2976 | #define MPI2_ETHPG0_STATUS_TELNET_ENABLED (0x00000040) | ||
| 2977 | #define MPI2_ETHPG0_STATUS_SSH2_ENABLED (0x00000020) | ||
| 2978 | #define MPI2_ETHPG0_STATUS_DHCP_CLIENT_ENABLED (0x00000010) | ||
| 2979 | #define MPI2_ETHPG0_STATUS_IPV6_ENABLED (0x00000008) | ||
| 2980 | #define MPI2_ETHPG0_STATUS_IPV4_ENABLED (0x00000004) | ||
| 2981 | #define MPI2_ETHPG0_STATUS_IPV6_ADDRESSES (0x00000002) | ||
| 2982 | #define MPI2_ETHPG0_STATUS_ETH_IF_ENABLED (0x00000001) | ||
| 2983 | |||
| 2984 | /* values for Ethernet Page 0 MediaState field */ | ||
| 2985 | #define MPI2_ETHPG0_MS_DUPLEX_MASK (0x80) | ||
| 2986 | #define MPI2_ETHPG0_MS_HALF_DUPLEX (0x00) | ||
| 2987 | #define MPI2_ETHPG0_MS_FULL_DUPLEX (0x80) | ||
| 2988 | |||
| 2989 | #define MPI2_ETHPG0_MS_CONNECT_SPEED_MASK (0x07) | ||
| 2990 | #define MPI2_ETHPG0_MS_NOT_CONNECTED (0x00) | ||
| 2991 | #define MPI2_ETHPG0_MS_10MBIT (0x01) | ||
| 2992 | #define MPI2_ETHPG0_MS_100MBIT (0x02) | ||
| 2993 | #define MPI2_ETHPG0_MS_1GBIT (0x03) | ||
| 2994 | |||
| 2995 | |||
| 2996 | /* Ethernet Page 1 */ | ||
| 2997 | |||
| 2998 | typedef struct _MPI2_CONFIG_PAGE_ETHERNET_1 { | ||
| 2999 | MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ | ||
| 3000 | U32 Reserved0; /* 0x08 */ | ||
| 3001 | U32 Flags; /* 0x0C */ | ||
| 3002 | U8 MediaState; /* 0x10 */ | ||
| 3003 | U8 Reserved1; /* 0x11 */ | ||
| 3004 | U16 Reserved2; /* 0x12 */ | ||
| 3005 | U8 MacAddress[6]; /* 0x14 */ | ||
| 3006 | U8 Reserved3; /* 0x1A */ | ||
| 3007 | U8 Reserved4; /* 0x1B */ | ||
| 3008 | MPI2_ETHERNET_IP_ADDR StaticIpAddress; /* 0x1C */ | ||
| 3009 | MPI2_ETHERNET_IP_ADDR StaticSubnetMask; /* 0x2C */ | ||
| 3010 | MPI2_ETHERNET_IP_ADDR StaticGatewayIpAddress; /* 0x3C */ | ||
| 3011 | MPI2_ETHERNET_IP_ADDR StaticDNS1IpAddress; /* 0x4C */ | ||
| 3012 | MPI2_ETHERNET_IP_ADDR StaticDNS2IpAddress; /* 0x5C */ | ||
| 3013 | U32 Reserved5; /* 0x6C */ | ||
| 3014 | U32 Reserved6; /* 0x70 */ | ||
| 3015 | U32 Reserved7; /* 0x74 */ | ||
| 3016 | U32 Reserved8; /* 0x78 */ | ||
| 3017 | U8 HostName | ||
| 3018 | [MPI2_ETHERNET_HOST_NAME_LENGTH];/* 0x7C */ | ||
| 3019 | } MPI2_CONFIG_PAGE_ETHERNET_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_ETHERNET_1, | ||
| 3020 | Mpi2EthernetPage1_t, MPI2_POINTER pMpi2EthernetPage1_t; | ||
| 3021 | |||
| 3022 | #define MPI2_ETHERNETPAGE1_PAGEVERSION (0x00) | ||
| 3023 | |||
| 3024 | /* values for Ethernet Page 1 Flags field */ | ||
| 3025 | #define MPI2_ETHPG1_FLAG_SET_DEFAULT_IF (0x00000100) | ||
| 3026 | #define MPI2_ETHPG1_FLAG_ENABLE_FW_DOWNLOAD (0x00000080) | ||
| 3027 | #define MPI2_ETHPG1_FLAG_ENABLE_TELNET (0x00000040) | ||
| 3028 | #define MPI2_ETHPG1_FLAG_ENABLE_SSH2 (0x00000020) | ||
| 3029 | #define MPI2_ETHPG1_FLAG_ENABLE_DHCP_CLIENT (0x00000010) | ||
| 3030 | #define MPI2_ETHPG1_FLAG_ENABLE_IPV6 (0x00000008) | ||
| 3031 | #define MPI2_ETHPG1_FLAG_ENABLE_IPV4 (0x00000004) | ||
| 3032 | #define MPI2_ETHPG1_FLAG_USE_IPV6_ADDRESSES (0x00000002) | ||
| 3033 | #define MPI2_ETHPG1_FLAG_ENABLE_ETH_IF (0x00000001) | ||
| 3034 | |||
| 3035 | /* values for Ethernet Page 1 MediaState field */ | ||
| 3036 | #define MPI2_ETHPG1_MS_DUPLEX_MASK (0x80) | ||
| 3037 | #define MPI2_ETHPG1_MS_HALF_DUPLEX (0x00) | ||
| 3038 | #define MPI2_ETHPG1_MS_FULL_DUPLEX (0x80) | ||
| 3039 | |||
| 3040 | #define MPI2_ETHPG1_MS_DATA_RATE_MASK (0x07) | ||
| 3041 | #define MPI2_ETHPG1_MS_DATA_RATE_AUTO (0x00) | ||
| 3042 | #define MPI2_ETHPG1_MS_DATA_RATE_10MBIT (0x01) | ||
| 3043 | #define MPI2_ETHPG1_MS_DATA_RATE_100MBIT (0x02) | ||
| 3044 | #define MPI2_ETHPG1_MS_DATA_RATE_1GBIT (0x03) | ||
| 3045 | |||
| 3046 | |||
| 3047 | /**************************************************************************** | ||
| 3048 | * Extended Manufacturing Config Pages | ||
| 3049 | ****************************************************************************/ | ||
| 3050 | |||
| 3051 | /* | ||
| 3052 | * Generic structure to use for product-specific extended manufacturing pages | ||
| 3053 | * (currently Extended Manufacturing Page 40 through Extended Manufacturing | ||
| 3054 | * Page 60). | ||
| 3055 | */ | ||
| 3056 | |||
| 3057 | typedef struct _MPI2_CONFIG_PAGE_EXT_MAN_PS { | ||
| 3058 | MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ | ||
| 3059 | U32 ProductSpecificInfo; /* 0x08 */ | ||
| 3060 | } MPI2_CONFIG_PAGE_EXT_MAN_PS, | ||
| 3061 | MPI2_POINTER PTR_MPI2_CONFIG_PAGE_EXT_MAN_PS, | ||
| 3062 | Mpi2ExtManufacturingPagePS_t, | ||
| 3063 | MPI2_POINTER pMpi2ExtManufacturingPagePS_t; | ||
| 3064 | |||
| 3065 | /* PageVersion should be provided by product-specific code */ | ||
| 3066 | |||
| 3067 | #endif | ||
| 3068 | |||
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_init.h b/drivers/scsi/mpt2sas/mpi/mpi2_init.h deleted file mode 100644 index eea1a16b13ec..000000000000 --- a/drivers/scsi/mpt2sas/mpi/mpi2_init.h +++ /dev/null | |||
| @@ -1,461 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2000-2014 LSI Corporation. | ||
| 3 | * | ||
| 4 | * | ||
| 5 | * Name: mpi2_init.h | ||
| 6 | * Title: MPI SCSI initiator mode messages and structures | ||
| 7 | * Creation Date: June 23, 2006 | ||
| 8 | * | ||
| 9 | * mpi2_init.h Version: 02.00.15 | ||
| 10 | * | ||
| 11 | * Version History | ||
| 12 | * --------------- | ||
| 13 | * | ||
| 14 | * Date Version Description | ||
| 15 | * -------- -------- ------------------------------------------------------ | ||
| 16 | * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. | ||
| 17 | * 10-31-07 02.00.01 Fixed name for pMpi2SCSITaskManagementRequest_t. | ||
| 18 | * 12-18-07 02.00.02 Modified Task Management Target Reset Method defines. | ||
| 19 | * 02-29-08 02.00.03 Added Query Task Set and Query Unit Attention. | ||
| 20 | * 03-03-08 02.00.04 Fixed name of struct _MPI2_SCSI_TASK_MANAGE_REPLY. | ||
| 21 | * 05-21-08 02.00.05 Fixed typo in name of Mpi2SepRequest_t. | ||
| 22 | * 10-02-08 02.00.06 Removed Untagged and No Disconnect values from SCSI IO | ||
| 23 | * Control field Task Attribute flags. | ||
| 24 | * Moved LUN field defines to mpi2.h because they are | ||
| 25 | * common to many structures. | ||
| 26 | * 05-06-09 02.00.07 Changed task management type of Query Unit Attention to | ||
| 27 | * Query Asynchronous Event. | ||
| 28 | * Defined two new bits in the SlotStatus field of the SCSI | ||
| 29 | * Enclosure Processor Request and Reply. | ||
| 30 | * 10-28-09 02.00.08 Added defines for decoding the ResponseInfo bytes for | ||
| 31 | * both SCSI IO Error Reply and SCSI Task Management Reply. | ||
| 32 | * Added ResponseInfo field to MPI2_SCSI_TASK_MANAGE_REPLY. | ||
| 33 | * Added MPI2_SCSITASKMGMT_RSP_TM_OVERLAPPED_TAG define. | ||
| 34 | * 02-10-10 02.00.09 Removed unused structure that had "#if 0" around it. | ||
| 35 | * 05-12-10 02.00.10 Added optional vendor-unique region to SCSI IO Request. | ||
| 36 | * 11-10-10 02.00.11 Added MPI2_SCSIIO_NUM_SGLOFFSETS define. | ||
| 37 | * 02-06-12 02.00.13 Added alternate defines for Task Priority / Command | ||
| 38 | * Priority to match SAM-4. | ||
| 39 | * 07-10-12 02.00.14 Added MPI2_SCSIIO_CONTROL_SHIFT_DATADIRECTION. | ||
| 40 | * 04-09-13 02.00.15 Added SCSIStatusQualifier field to MPI2_SCSI_IO_REPLY, | ||
| 41 | * replacing the Reserved4 field. | ||
| 42 | * -------------------------------------------------------------------------- | ||
| 43 | */ | ||
| 44 | |||
| 45 | #ifndef MPI2_INIT_H | ||
| 46 | #define MPI2_INIT_H | ||
| 47 | |||
| 48 | /***************************************************************************** | ||
| 49 | * | ||
| 50 | * SCSI Initiator Messages | ||
| 51 | * | ||
| 52 | *****************************************************************************/ | ||
| 53 | |||
| 54 | /**************************************************************************** | ||
| 55 | * SCSI IO messages and associated structures | ||
| 56 | ****************************************************************************/ | ||
| 57 | |||
| 58 | typedef struct | ||
| 59 | { | ||
| 60 | U8 CDB[20]; /* 0x00 */ | ||
| 61 | U32 PrimaryReferenceTag; /* 0x14 */ | ||
| 62 | U16 PrimaryApplicationTag; /* 0x18 */ | ||
| 63 | U16 PrimaryApplicationTagMask; /* 0x1A */ | ||
| 64 | U32 TransferLength; /* 0x1C */ | ||
| 65 | } MPI2_SCSI_IO_CDB_EEDP32, MPI2_POINTER PTR_MPI2_SCSI_IO_CDB_EEDP32, | ||
| 66 | Mpi2ScsiIoCdbEedp32_t, MPI2_POINTER pMpi2ScsiIoCdbEedp32_t; | ||
| 67 | |||
| 68 | typedef union | ||
| 69 | { | ||
| 70 | U8 CDB32[32]; | ||
| 71 | MPI2_SCSI_IO_CDB_EEDP32 EEDP32; | ||
| 72 | MPI2_SGE_SIMPLE_UNION SGE; | ||
| 73 | } MPI2_SCSI_IO_CDB_UNION, MPI2_POINTER PTR_MPI2_SCSI_IO_CDB_UNION, | ||
| 74 | Mpi2ScsiIoCdb_t, MPI2_POINTER pMpi2ScsiIoCdb_t; | ||
| 75 | |||
| 76 | /* SCSI IO Request Message */ | ||
| 77 | typedef struct _MPI2_SCSI_IO_REQUEST | ||
| 78 | { | ||
| 79 | U16 DevHandle; /* 0x00 */ | ||
| 80 | U8 ChainOffset; /* 0x02 */ | ||
| 81 | U8 Function; /* 0x03 */ | ||
| 82 | U16 Reserved1; /* 0x04 */ | ||
| 83 | U8 Reserved2; /* 0x06 */ | ||
| 84 | U8 MsgFlags; /* 0x07 */ | ||
| 85 | U8 VP_ID; /* 0x08 */ | ||
| 86 | U8 VF_ID; /* 0x09 */ | ||
| 87 | U16 Reserved3; /* 0x0A */ | ||
| 88 | U32 SenseBufferLowAddress; /* 0x0C */ | ||
| 89 | U16 SGLFlags; /* 0x10 */ | ||
| 90 | U8 SenseBufferLength; /* 0x12 */ | ||
| 91 | U8 Reserved4; /* 0x13 */ | ||
| 92 | U8 SGLOffset0; /* 0x14 */ | ||
| 93 | U8 SGLOffset1; /* 0x15 */ | ||
| 94 | U8 SGLOffset2; /* 0x16 */ | ||
| 95 | U8 SGLOffset3; /* 0x17 */ | ||
| 96 | U32 SkipCount; /* 0x18 */ | ||
| 97 | U32 DataLength; /* 0x1C */ | ||
| 98 | U32 BidirectionalDataLength; /* 0x20 */ | ||
| 99 | U16 IoFlags; /* 0x24 */ | ||
| 100 | U16 EEDPFlags; /* 0x26 */ | ||
| 101 | U32 EEDPBlockSize; /* 0x28 */ | ||
| 102 | U32 SecondaryReferenceTag; /* 0x2C */ | ||
| 103 | U16 SecondaryApplicationTag; /* 0x30 */ | ||
| 104 | U16 ApplicationTagTranslationMask; /* 0x32 */ | ||
| 105 | U8 LUN[8]; /* 0x34 */ | ||
| 106 | U32 Control; /* 0x3C */ | ||
| 107 | MPI2_SCSI_IO_CDB_UNION CDB; /* 0x40 */ | ||
| 108 | |||
| 109 | #ifdef MPI2_SCSI_IO_VENDOR_UNIQUE_REGION /* typically this is left undefined */ | ||
| 110 | MPI2_SCSI_IO_VENDOR_UNIQUE VendorRegion; | ||
| 111 | #endif | ||
| 112 | |||
| 113 | MPI2_SGE_IO_UNION SGL; /* 0x60 */ | ||
| 114 | |||
| 115 | } MPI2_SCSI_IO_REQUEST, MPI2_POINTER PTR_MPI2_SCSI_IO_REQUEST, | ||
| 116 | Mpi2SCSIIORequest_t, MPI2_POINTER pMpi2SCSIIORequest_t; | ||
| 117 | |||
| 118 | /* SCSI IO MsgFlags bits */ | ||
| 119 | |||
| 120 | /* MsgFlags for SenseBufferAddressSpace */ | ||
| 121 | #define MPI2_SCSIIO_MSGFLAGS_MASK_SENSE_ADDR (0x0C) | ||
| 122 | #define MPI2_SCSIIO_MSGFLAGS_SYSTEM_SENSE_ADDR (0x00) | ||
| 123 | #define MPI2_SCSIIO_MSGFLAGS_IOCDDR_SENSE_ADDR (0x04) | ||
| 124 | #define MPI2_SCSIIO_MSGFLAGS_IOCPLB_SENSE_ADDR (0x08) | ||
| 125 | #define MPI2_SCSIIO_MSGFLAGS_IOCPLBNTA_SENSE_ADDR (0x0C) | ||
| 126 | |||
| 127 | /* SCSI IO SGLFlags bits */ | ||
| 128 | |||
| 129 | /* base values for Data Location Address Space */ | ||
| 130 | #define MPI2_SCSIIO_SGLFLAGS_ADDR_MASK (0x0C) | ||
| 131 | #define MPI2_SCSIIO_SGLFLAGS_SYSTEM_ADDR (0x00) | ||
| 132 | #define MPI2_SCSIIO_SGLFLAGS_IOCDDR_ADDR (0x04) | ||
| 133 | #define MPI2_SCSIIO_SGLFLAGS_IOCPLB_ADDR (0x08) | ||
| 134 | #define MPI2_SCSIIO_SGLFLAGS_IOCPLBNTA_ADDR (0x0C) | ||
| 135 | |||
| 136 | /* base values for Type */ | ||
| 137 | #define MPI2_SCSIIO_SGLFLAGS_TYPE_MASK (0x03) | ||
| 138 | #define MPI2_SCSIIO_SGLFLAGS_TYPE_MPI (0x00) | ||
| 139 | #define MPI2_SCSIIO_SGLFLAGS_TYPE_IEEE32 (0x01) | ||
| 140 | #define MPI2_SCSIIO_SGLFLAGS_TYPE_IEEE64 (0x02) | ||
| 141 | |||
| 142 | /* shift values for each sub-field */ | ||
| 143 | #define MPI2_SCSIIO_SGLFLAGS_SGL3_SHIFT (12) | ||
| 144 | #define MPI2_SCSIIO_SGLFLAGS_SGL2_SHIFT (8) | ||
| 145 | #define MPI2_SCSIIO_SGLFLAGS_SGL1_SHIFT (4) | ||
| 146 | #define MPI2_SCSIIO_SGLFLAGS_SGL0_SHIFT (0) | ||
| 147 | |||
| 148 | /* number of SGLOffset fields */ | ||
| 149 | #define MPI2_SCSIIO_NUM_SGLOFFSETS (4) | ||
| 150 | |||
| 151 | /* SCSI IO IoFlags bits */ | ||
| 152 | |||
| 153 | /* Large CDB Address Space */ | ||
| 154 | #define MPI2_SCSIIO_CDB_ADDR_MASK (0x6000) | ||
| 155 | #define MPI2_SCSIIO_CDB_ADDR_SYSTEM (0x0000) | ||
| 156 | #define MPI2_SCSIIO_CDB_ADDR_IOCDDR (0x2000) | ||
| 157 | #define MPI2_SCSIIO_CDB_ADDR_IOCPLB (0x4000) | ||
| 158 | #define MPI2_SCSIIO_CDB_ADDR_IOCPLBNTA (0x6000) | ||
| 159 | |||
| 160 | #define MPI2_SCSIIO_IOFLAGS_LARGE_CDB (0x1000) | ||
| 161 | #define MPI2_SCSIIO_IOFLAGS_BIDIRECTIONAL (0x0800) | ||
| 162 | #define MPI2_SCSIIO_IOFLAGS_MULTICAST (0x0400) | ||
| 163 | #define MPI2_SCSIIO_IOFLAGS_CMD_DETERMINES_DATA_DIR (0x0200) | ||
| 164 | #define MPI2_SCSIIO_IOFLAGS_CDBLENGTH_MASK (0x01FF) | ||
| 165 | |||
| 166 | /* SCSI IO EEDPFlags bits */ | ||
| 167 | |||
| 168 | #define MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG (0x8000) | ||
| 169 | #define MPI2_SCSIIO_EEDPFLAGS_INC_SEC_REFTAG (0x4000) | ||
| 170 | #define MPI2_SCSIIO_EEDPFLAGS_INC_PRI_APPTAG (0x2000) | ||
| 171 | #define MPI2_SCSIIO_EEDPFLAGS_INC_SEC_APPTAG (0x1000) | ||
| 172 | |||
| 173 | #define MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG (0x0400) | ||
| 174 | #define MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG (0x0200) | ||
| 175 | #define MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD (0x0100) | ||
| 176 | |||
| 177 | #define MPI2_SCSIIO_EEDPFLAGS_PASSTHRU_REFTAG (0x0008) | ||
| 178 | |||
| 179 | #define MPI2_SCSIIO_EEDPFLAGS_MASK_OP (0x0007) | ||
| 180 | #define MPI2_SCSIIO_EEDPFLAGS_NOOP_OP (0x0000) | ||
| 181 | #define MPI2_SCSIIO_EEDPFLAGS_CHECK_OP (0x0001) | ||
| 182 | #define MPI2_SCSIIO_EEDPFLAGS_STRIP_OP (0x0002) | ||
| 183 | #define MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP (0x0003) | ||
| 184 | #define MPI2_SCSIIO_EEDPFLAGS_INSERT_OP (0x0004) | ||
| 185 | #define MPI2_SCSIIO_EEDPFLAGS_REPLACE_OP (0x0006) | ||
| 186 | #define MPI2_SCSIIO_EEDPFLAGS_CHECK_REGEN_OP (0x0007) | ||
| 187 | |||
| 188 | /* SCSI IO LUN fields: use MPI2_LUN_ from mpi2.h */ | ||
| 189 | |||
| 190 | /* SCSI IO Control bits */ | ||
| 191 | #define MPI2_SCSIIO_CONTROL_ADDCDBLEN_MASK (0xFC000000) | ||
| 192 | #define MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT (26) | ||
| 193 | |||
| 194 | #define MPI2_SCSIIO_CONTROL_DATADIRECTION_MASK (0x03000000) | ||
| 195 | #define MPI2_SCSIIO_CONTROL_SHIFT_DATADIRECTION (24) | ||
| 196 | #define MPI2_SCSIIO_CONTROL_NODATATRANSFER (0x00000000) | ||
| 197 | #define MPI2_SCSIIO_CONTROL_WRITE (0x01000000) | ||
| 198 | #define MPI2_SCSIIO_CONTROL_READ (0x02000000) | ||
| 199 | #define MPI2_SCSIIO_CONTROL_BIDIRECTIONAL (0x03000000) | ||
| 200 | |||
| 201 | #define MPI2_SCSIIO_CONTROL_TASKPRI_MASK (0x00007800) | ||
| 202 | #define MPI2_SCSIIO_CONTROL_TASKPRI_SHIFT (11) | ||
| 203 | /* alternate name for the previous field; called Command Priority in SAM-4 */ | ||
| 204 | #define MPI2_SCSIIO_CONTROL_CMDPRI_MASK (0x00007800) | ||
| 205 | #define MPI2_SCSIIO_CONTROL_CMDPRI_SHIFT (11) | ||
| 206 | |||
| 207 | #define MPI2_SCSIIO_CONTROL_TASKATTRIBUTE_MASK (0x00000700) | ||
| 208 | #define MPI2_SCSIIO_CONTROL_SIMPLEQ (0x00000000) | ||
| 209 | #define MPI2_SCSIIO_CONTROL_HEADOFQ (0x00000100) | ||
| 210 | #define MPI2_SCSIIO_CONTROL_ORDEREDQ (0x00000200) | ||
| 211 | #define MPI2_SCSIIO_CONTROL_ACAQ (0x00000400) | ||
| 212 | |||
| 213 | #define MPI2_SCSIIO_CONTROL_TLR_MASK (0x000000C0) | ||
| 214 | #define MPI2_SCSIIO_CONTROL_NO_TLR (0x00000000) | ||
| 215 | #define MPI2_SCSIIO_CONTROL_TLR_ON (0x00000040) | ||
| 216 | #define MPI2_SCSIIO_CONTROL_TLR_OFF (0x00000080) | ||
| 217 | |||
| 218 | |||
| 219 | /* SCSI IO Error Reply Message */ | ||
| 220 | typedef struct _MPI2_SCSI_IO_REPLY | ||
| 221 | { | ||
| 222 | U16 DevHandle; /* 0x00 */ | ||
| 223 | U8 MsgLength; /* 0x02 */ | ||
| 224 | U8 Function; /* 0x03 */ | ||
| 225 | U16 Reserved1; /* 0x04 */ | ||
| 226 | U8 Reserved2; /* 0x06 */ | ||
| 227 | U8 MsgFlags; /* 0x07 */ | ||
| 228 | U8 VP_ID; /* 0x08 */ | ||
| 229 | U8 VF_ID; /* 0x09 */ | ||
| 230 | U16 Reserved3; /* 0x0A */ | ||
| 231 | U8 SCSIStatus; /* 0x0C */ | ||
| 232 | U8 SCSIState; /* 0x0D */ | ||
| 233 | U16 IOCStatus; /* 0x0E */ | ||
| 234 | U32 IOCLogInfo; /* 0x10 */ | ||
| 235 | U32 TransferCount; /* 0x14 */ | ||
| 236 | U32 SenseCount; /* 0x18 */ | ||
| 237 | U32 ResponseInfo; /* 0x1C */ | ||
| 238 | U16 TaskTag; /* 0x20 */ | ||
| 239 | U16 SCSIStatusQualifier; /* 0x22 */ | ||
| 240 | U32 BidirectionalTransferCount; /* 0x24 */ | ||
| 241 | U32 Reserved5; /* 0x28 */ | ||
| 242 | U32 Reserved6; /* 0x2C */ | ||
| 243 | } MPI2_SCSI_IO_REPLY, MPI2_POINTER PTR_MPI2_SCSI_IO_REPLY, | ||
| 244 | Mpi2SCSIIOReply_t, MPI2_POINTER pMpi2SCSIIOReply_t; | ||
| 245 | |||
| 246 | /* SCSI IO Reply SCSIStatus values (SAM-4 status codes) */ | ||
| 247 | |||
| 248 | #define MPI2_SCSI_STATUS_GOOD (0x00) | ||
| 249 | #define MPI2_SCSI_STATUS_CHECK_CONDITION (0x02) | ||
| 250 | #define MPI2_SCSI_STATUS_CONDITION_MET (0x04) | ||
| 251 | #define MPI2_SCSI_STATUS_BUSY (0x08) | ||
| 252 | #define MPI2_SCSI_STATUS_INTERMEDIATE (0x10) | ||
| 253 | #define MPI2_SCSI_STATUS_INTERMEDIATE_CONDMET (0x14) | ||
| 254 | #define MPI2_SCSI_STATUS_RESERVATION_CONFLICT (0x18) | ||
| 255 | #define MPI2_SCSI_STATUS_COMMAND_TERMINATED (0x22) /* obsolete */ | ||
| 256 | #define MPI2_SCSI_STATUS_TASK_SET_FULL (0x28) | ||
| 257 | #define MPI2_SCSI_STATUS_ACA_ACTIVE (0x30) | ||
| 258 | #define MPI2_SCSI_STATUS_TASK_ABORTED (0x40) | ||
| 259 | |||
| 260 | /* SCSI IO Reply SCSIState flags */ | ||
| 261 | |||
| 262 | #define MPI2_SCSI_STATE_RESPONSE_INFO_VALID (0x10) | ||
| 263 | #define MPI2_SCSI_STATE_TERMINATED (0x08) | ||
| 264 | #define MPI2_SCSI_STATE_NO_SCSI_STATUS (0x04) | ||
| 265 | #define MPI2_SCSI_STATE_AUTOSENSE_FAILED (0x02) | ||
| 266 | #define MPI2_SCSI_STATE_AUTOSENSE_VALID (0x01) | ||
| 267 | |||
| 268 | /* masks and shifts for the ResponseInfo field */ | ||
| 269 | |||
| 270 | #define MPI2_SCSI_RI_MASK_REASONCODE (0x000000FF) | ||
| 271 | #define MPI2_SCSI_RI_SHIFT_REASONCODE (0) | ||
| 272 | |||
| 273 | #define MPI2_SCSI_TASKTAG_UNKNOWN (0xFFFF) | ||
| 274 | |||
| 275 | |||
| 276 | /**************************************************************************** | ||
| 277 | * SCSI Task Management messages | ||
| 278 | ****************************************************************************/ | ||
| 279 | |||
| 280 | /* SCSI Task Management Request Message */ | ||
| 281 | typedef struct _MPI2_SCSI_TASK_MANAGE_REQUEST | ||
| 282 | { | ||
| 283 | U16 DevHandle; /* 0x00 */ | ||
| 284 | U8 ChainOffset; /* 0x02 */ | ||
| 285 | U8 Function; /* 0x03 */ | ||
| 286 | U8 Reserved1; /* 0x04 */ | ||
| 287 | U8 TaskType; /* 0x05 */ | ||
| 288 | U8 Reserved2; /* 0x06 */ | ||
| 289 | U8 MsgFlags; /* 0x07 */ | ||
| 290 | U8 VP_ID; /* 0x08 */ | ||
| 291 | U8 VF_ID; /* 0x09 */ | ||
| 292 | U16 Reserved3; /* 0x0A */ | ||
| 293 | U8 LUN[8]; /* 0x0C */ | ||
| 294 | U32 Reserved4[7]; /* 0x14 */ | ||
| 295 | U16 TaskMID; /* 0x30 */ | ||
| 296 | U16 Reserved5; /* 0x32 */ | ||
| 297 | } MPI2_SCSI_TASK_MANAGE_REQUEST, | ||
| 298 | MPI2_POINTER PTR_MPI2_SCSI_TASK_MANAGE_REQUEST, | ||
| 299 | Mpi2SCSITaskManagementRequest_t, | ||
| 300 | MPI2_POINTER pMpi2SCSITaskManagementRequest_t; | ||
| 301 | |||
| 302 | /* TaskType values */ | ||
| 303 | |||
| 304 | #define MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK (0x01) | ||
| 305 | #define MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET (0x02) | ||
| 306 | #define MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET (0x03) | ||
| 307 | #define MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET (0x05) | ||
| 308 | #define MPI2_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET (0x06) | ||
| 309 | #define MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK (0x07) | ||
| 310 | #define MPI2_SCSITASKMGMT_TASKTYPE_CLR_ACA (0x08) | ||
| 311 | #define MPI2_SCSITASKMGMT_TASKTYPE_QRY_TASK_SET (0x09) | ||
| 312 | #define MPI2_SCSITASKMGMT_TASKTYPE_QRY_ASYNC_EVENT (0x0A) | ||
| 313 | |||
| 314 | /* obsolete TaskType name */ | ||
| 315 | #define MPI2_SCSITASKMGMT_TASKTYPE_QRY_UNIT_ATTENTION \ | ||
| 316 | (MPI2_SCSITASKMGMT_TASKTYPE_QRY_ASYNC_EVENT) | ||
| 317 | |||
| 318 | /* MsgFlags bits */ | ||
| 319 | |||
| 320 | #define MPI2_SCSITASKMGMT_MSGFLAGS_MASK_TARGET_RESET (0x18) | ||
| 321 | #define MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET (0x00) | ||
| 322 | #define MPI2_SCSITASKMGMT_MSGFLAGS_NEXUS_RESET_SRST (0x08) | ||
| 323 | #define MPI2_SCSITASKMGMT_MSGFLAGS_SAS_HARD_LINK_RESET (0x10) | ||
| 324 | |||
| 325 | #define MPI2_SCSITASKMGMT_MSGFLAGS_DO_NOT_SEND_TASK_IU (0x01) | ||
| 326 | |||
| 327 | |||
| 328 | |||
| 329 | /* SCSI Task Management Reply Message */ | ||
| 330 | typedef struct _MPI2_SCSI_TASK_MANAGE_REPLY | ||
| 331 | { | ||
| 332 | U16 DevHandle; /* 0x00 */ | ||
| 333 | U8 MsgLength; /* 0x02 */ | ||
| 334 | U8 Function; /* 0x03 */ | ||
| 335 | U8 ResponseCode; /* 0x04 */ | ||
| 336 | U8 TaskType; /* 0x05 */ | ||
| 337 | U8 Reserved1; /* 0x06 */ | ||
| 338 | U8 MsgFlags; /* 0x07 */ | ||
| 339 | U8 VP_ID; /* 0x08 */ | ||
| 340 | U8 VF_ID; /* 0x09 */ | ||
| 341 | U16 Reserved2; /* 0x0A */ | ||
| 342 | U16 Reserved3; /* 0x0C */ | ||
| 343 | U16 IOCStatus; /* 0x0E */ | ||
| 344 | U32 IOCLogInfo; /* 0x10 */ | ||
| 345 | U32 TerminationCount; /* 0x14 */ | ||
| 346 | U32 ResponseInfo; /* 0x18 */ | ||
| 347 | } MPI2_SCSI_TASK_MANAGE_REPLY, | ||
| 348 | MPI2_POINTER PTR_MPI2_SCSI_TASK_MANAGE_REPLY, | ||
| 349 | Mpi2SCSITaskManagementReply_t, MPI2_POINTER pMpi2SCSIManagementReply_t; | ||
| 350 | |||
| 351 | /* ResponseCode values */ | ||
| 352 | |||
| 353 | #define MPI2_SCSITASKMGMT_RSP_TM_COMPLETE (0x00) | ||
| 354 | #define MPI2_SCSITASKMGMT_RSP_INVALID_FRAME (0x02) | ||
| 355 | #define MPI2_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED (0x04) | ||
| 356 | #define MPI2_SCSITASKMGMT_RSP_TM_FAILED (0x05) | ||
| 357 | #define MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED (0x08) | ||
| 358 | #define MPI2_SCSITASKMGMT_RSP_TM_INVALID_LUN (0x09) | ||
| 359 | #define MPI2_SCSITASKMGMT_RSP_TM_OVERLAPPED_TAG (0x0A) | ||
| 360 | #define MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC (0x80) | ||
| 361 | |||
| 362 | /* masks and shifts for the ResponseInfo field */ | ||
| 363 | |||
| 364 | #define MPI2_SCSITASKMGMT_RI_MASK_REASONCODE (0x000000FF) | ||
| 365 | #define MPI2_SCSITASKMGMT_RI_SHIFT_REASONCODE (0) | ||
| 366 | #define MPI2_SCSITASKMGMT_RI_MASK_ARI2 (0x0000FF00) | ||
| 367 | #define MPI2_SCSITASKMGMT_RI_SHIFT_ARI2 (8) | ||
| 368 | #define MPI2_SCSITASKMGMT_RI_MASK_ARI1 (0x00FF0000) | ||
| 369 | #define MPI2_SCSITASKMGMT_RI_SHIFT_ARI1 (16) | ||
| 370 | #define MPI2_SCSITASKMGMT_RI_MASK_ARI0 (0xFF000000) | ||
| 371 | #define MPI2_SCSITASKMGMT_RI_SHIFT_ARI0 (24) | ||
| 372 | |||
| 373 | |||
| 374 | /**************************************************************************** | ||
| 375 | * SCSI Enclosure Processor messages | ||
| 376 | ****************************************************************************/ | ||
| 377 | |||
| 378 | /* SCSI Enclosure Processor Request Message */ | ||
| 379 | typedef struct _MPI2_SEP_REQUEST | ||
| 380 | { | ||
| 381 | U16 DevHandle; /* 0x00 */ | ||
| 382 | U8 ChainOffset; /* 0x02 */ | ||
| 383 | U8 Function; /* 0x03 */ | ||
| 384 | U8 Action; /* 0x04 */ | ||
| 385 | U8 Flags; /* 0x05 */ | ||
| 386 | U8 Reserved1; /* 0x06 */ | ||
| 387 | U8 MsgFlags; /* 0x07 */ | ||
| 388 | U8 VP_ID; /* 0x08 */ | ||
| 389 | U8 VF_ID; /* 0x09 */ | ||
| 390 | U16 Reserved2; /* 0x0A */ | ||
| 391 | U32 SlotStatus; /* 0x0C */ | ||
| 392 | U32 Reserved3; /* 0x10 */ | ||
| 393 | U32 Reserved4; /* 0x14 */ | ||
| 394 | U32 Reserved5; /* 0x18 */ | ||
| 395 | U16 Slot; /* 0x1C */ | ||
| 396 | U16 EnclosureHandle; /* 0x1E */ | ||
| 397 | } MPI2_SEP_REQUEST, MPI2_POINTER PTR_MPI2_SEP_REQUEST, | ||
| 398 | Mpi2SepRequest_t, MPI2_POINTER pMpi2SepRequest_t; | ||
| 399 | |||
| 400 | /* Action defines */ | ||
| 401 | #define MPI2_SEP_REQ_ACTION_WRITE_STATUS (0x00) | ||
| 402 | #define MPI2_SEP_REQ_ACTION_READ_STATUS (0x01) | ||
| 403 | |||
| 404 | /* Flags defines */ | ||
| 405 | #define MPI2_SEP_REQ_FLAGS_DEVHANDLE_ADDRESS (0x00) | ||
| 406 | #define MPI2_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS (0x01) | ||
| 407 | |||
| 408 | /* SlotStatus defines */ | ||
| 409 | #define MPI2_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE (0x00040000) | ||
| 410 | #define MPI2_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST (0x00020000) | ||
| 411 | #define MPI2_SEP_REQ_SLOTSTATUS_REBUILD_STOPPED (0x00000200) | ||
| 412 | #define MPI2_SEP_REQ_SLOTSTATUS_HOT_SPARE (0x00000100) | ||
| 413 | #define MPI2_SEP_REQ_SLOTSTATUS_UNCONFIGURED (0x00000080) | ||
| 414 | #define MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT (0x00000040) | ||
| 415 | #define MPI2_SEP_REQ_SLOTSTATUS_IN_CRITICAL_ARRAY (0x00000010) | ||
| 416 | #define MPI2_SEP_REQ_SLOTSTATUS_IN_FAILED_ARRAY (0x00000008) | ||
| 417 | #define MPI2_SEP_REQ_SLOTSTATUS_DEV_REBUILDING (0x00000004) | ||
| 418 | #define MPI2_SEP_REQ_SLOTSTATUS_DEV_FAULTY (0x00000002) | ||
| 419 | #define MPI2_SEP_REQ_SLOTSTATUS_NO_ERROR (0x00000001) | ||
| 420 | |||
| 421 | |||
| 422 | /* SCSI Enclosure Processor Reply Message */ | ||
| 423 | typedef struct _MPI2_SEP_REPLY | ||
| 424 | { | ||
| 425 | U16 DevHandle; /* 0x00 */ | ||
| 426 | U8 MsgLength; /* 0x02 */ | ||
| 427 | U8 Function; /* 0x03 */ | ||
| 428 | U8 Action; /* 0x04 */ | ||
| 429 | U8 Flags; /* 0x05 */ | ||
| 430 | U8 Reserved1; /* 0x06 */ | ||
| 431 | U8 MsgFlags; /* 0x07 */ | ||
| 432 | U8 VP_ID; /* 0x08 */ | ||
| 433 | U8 VF_ID; /* 0x09 */ | ||
| 434 | U16 Reserved2; /* 0x0A */ | ||
| 435 | U16 Reserved3; /* 0x0C */ | ||
| 436 | U16 IOCStatus; /* 0x0E */ | ||
| 437 | U32 IOCLogInfo; /* 0x10 */ | ||
| 438 | U32 SlotStatus; /* 0x14 */ | ||
| 439 | U32 Reserved4; /* 0x18 */ | ||
| 440 | U16 Slot; /* 0x1C */ | ||
| 441 | U16 EnclosureHandle; /* 0x1E */ | ||
| 442 | } MPI2_SEP_REPLY, MPI2_POINTER PTR_MPI2_SEP_REPLY, | ||
| 443 | Mpi2SepReply_t, MPI2_POINTER pMpi2SepReply_t; | ||
| 444 | |||
| 445 | /* SlotStatus defines */ | ||
| 446 | #define MPI2_SEP_REPLY_SLOTSTATUS_REMOVE_READY (0x00040000) | ||
| 447 | #define MPI2_SEP_REPLY_SLOTSTATUS_IDENTIFY_REQUEST (0x00020000) | ||
| 448 | #define MPI2_SEP_REPLY_SLOTSTATUS_REBUILD_STOPPED (0x00000200) | ||
| 449 | #define MPI2_SEP_REPLY_SLOTSTATUS_HOT_SPARE (0x00000100) | ||
| 450 | #define MPI2_SEP_REPLY_SLOTSTATUS_UNCONFIGURED (0x00000080) | ||
| 451 | #define MPI2_SEP_REPLY_SLOTSTATUS_PREDICTED_FAULT (0x00000040) | ||
| 452 | #define MPI2_SEP_REPLY_SLOTSTATUS_IN_CRITICAL_ARRAY (0x00000010) | ||
| 453 | #define MPI2_SEP_REPLY_SLOTSTATUS_IN_FAILED_ARRAY (0x00000008) | ||
| 454 | #define MPI2_SEP_REPLY_SLOTSTATUS_DEV_REBUILDING (0x00000004) | ||
| 455 | #define MPI2_SEP_REPLY_SLOTSTATUS_DEV_FAULTY (0x00000002) | ||
| 456 | #define MPI2_SEP_REPLY_SLOTSTATUS_NO_ERROR (0x00000001) | ||
| 457 | |||
| 458 | |||
| 459 | #endif | ||
| 460 | |||
| 461 | |||
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h b/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h deleted file mode 100644 index b02de48be204..000000000000 --- a/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h +++ /dev/null | |||
| @@ -1,1708 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2000-2014 LSI Corporation. | ||
| 3 | * | ||
| 4 | * | ||
| 5 | * Name: mpi2_ioc.h | ||
| 6 | * Title: MPI IOC, Port, Event, FW Download, and FW Upload messages | ||
| 7 | * Creation Date: October 11, 2006 | ||
| 8 | * | ||
| 9 | * mpi2_ioc.h Version: 02.00.24 | ||
| 10 | * | ||
| 11 | * Version History | ||
| 12 | * --------------- | ||
| 13 | * | ||
| 14 | * Date Version Description | ||
| 15 | * -------- -------- ------------------------------------------------------ | ||
| 16 | * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. | ||
| 17 | * 06-04-07 02.00.01 In IOCFacts Reply structure, renamed MaxDevices to | ||
| 18 | * MaxTargets. | ||
| 19 | * Added TotalImageSize field to FWDownload Request. | ||
| 20 | * Added reserved words to FWUpload Request. | ||
| 21 | * 06-26-07 02.00.02 Added IR Configuration Change List Event. | ||
| 22 | * 08-31-07 02.00.03 Removed SystemReplyQueueDepth field from the IOCInit | ||
| 23 | * request and replaced it with | ||
| 24 | * ReplyDescriptorPostQueueDepth and ReplyFreeQueueDepth. | ||
| 25 | * Replaced the MinReplyQueueDepth field of the IOCFacts | ||
| 26 | * reply with MaxReplyDescriptorPostQueueDepth. | ||
| 27 | * Added MPI2_RDPQ_DEPTH_MIN define to specify the minimum | ||
| 28 | * depth for the Reply Descriptor Post Queue. | ||
| 29 | * Added SASAddress field to Initiator Device Table | ||
| 30 | * Overflow Event data. | ||
| 31 | * 10-31-07 02.00.04 Added ReasonCode MPI2_EVENT_SAS_INIT_RC_NOT_RESPONDING | ||
| 32 | * for SAS Initiator Device Status Change Event data. | ||
| 33 | * Modified Reason Code defines for SAS Topology Change | ||
| 34 | * List Event data, including adding a bit for PHY Vacant | ||
| 35 | * status, and adding a mask for the Reason Code. | ||
| 36 | * Added define for | ||
| 37 | * MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING. | ||
| 38 | * Added define for MPI2_EXT_IMAGE_TYPE_MEGARAID. | ||
| 39 | * 12-18-07 02.00.05 Added Boot Status defines for the IOCExceptions field of | ||
| 40 | * the IOCFacts Reply. | ||
| 41 | * Removed MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER define. | ||
| 42 | * Moved MPI2_VERSION_UNION to mpi2.h. | ||
| 43 | * Changed MPI2_EVENT_NOTIFICATION_REQUEST to use masks | ||
| 44 | * instead of enables, and added SASBroadcastPrimitiveMasks | ||
| 45 | * field. | ||
| 46 | * Added Log Entry Added Event and related structure. | ||
| 47 | * 02-29-08 02.00.06 Added define MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID. | ||
| 48 | * Removed define MPI2_IOCFACTS_PROTOCOL_SMP_TARGET. | ||
| 49 | * Added MaxVolumes and MaxPersistentEntries fields to | ||
| 50 | * IOCFacts reply. | ||
| 51 | * Added ProtocalFlags and IOCCapabilities fields to | ||
| 52 | * MPI2_FW_IMAGE_HEADER. | ||
| 53 | * Removed MPI2_PORTENABLE_FLAGS_ENABLE_SINGLE_PORT. | ||
| 54 | * 03-03-08 02.00.07 Fixed MPI2_FW_IMAGE_HEADER by changing Reserved26 to | ||
| 55 | * a U16 (from a U32). | ||
| 56 | * Removed extra 's' from EventMasks name. | ||
| 57 | * 06-27-08 02.00.08 Fixed an offset in a comment. | ||
| 58 | * 10-02-08 02.00.09 Removed SystemReplyFrameSize from MPI2_IOC_INIT_REQUEST. | ||
| 59 | * Removed CurReplyFrameSize from MPI2_IOC_FACTS_REPLY and | ||
| 60 | * renamed MinReplyFrameSize to ReplyFrameSize. | ||
| 61 | * Added MPI2_IOCFACTS_EXCEPT_IR_FOREIGN_CONFIG_MAX. | ||
| 62 | * Added two new RAIDOperation values for Integrated RAID | ||
| 63 | * Operations Status Event data. | ||
| 64 | * Added four new IR Configuration Change List Event data | ||
| 65 | * ReasonCode values. | ||
| 66 | * Added two new ReasonCode defines for SAS Device Status | ||
| 67 | * Change Event data. | ||
| 68 | * Added three new DiscoveryStatus bits for the SAS | ||
| 69 | * Discovery event data. | ||
| 70 | * Added Multiplexing Status Change bit to the PhyStatus | ||
| 71 | * field of the SAS Topology Change List event data. | ||
| 72 | * Removed define for MPI2_INIT_IMAGE_BOOTFLAGS_XMEMCOPY. | ||
| 73 | * BootFlags are now product-specific. | ||
| 74 | * Added defines for the indivdual signature bytes | ||
| 75 | * for MPI2_INIT_IMAGE_FOOTER. | ||
| 76 | * 01-19-09 02.00.10 Added MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY define. | ||
| 77 | * Added MPI2_EVENT_SAS_DISC_DS_DOWNSTREAM_INITIATOR | ||
| 78 | * define. | ||
| 79 | * Added MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE | ||
| 80 | * define. | ||
| 81 | * Removed MPI2_EVENT_SAS_DISC_DS_SATA_INIT_FAILURE define. | ||
| 82 | * 05-06-09 02.00.11 Added MPI2_IOCFACTS_CAPABILITY_RAID_ACCELERATOR define. | ||
| 83 | * Added MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX define. | ||
| 84 | * Added two new reason codes for SAS Device Status Change | ||
| 85 | * Event. | ||
| 86 | * Added new event: SAS PHY Counter. | ||
| 87 | * 07-30-09 02.00.12 Added GPIO Interrupt event define and structure. | ||
| 88 | * Added MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER define. | ||
| 89 | * Added new product id family for 2208. | ||
| 90 | * 10-28-09 02.00.13 Added HostMSIxVectors field to MPI2_IOC_INIT_REQUEST. | ||
| 91 | * Added MaxMSIxVectors field to MPI2_IOC_FACTS_REPLY. | ||
| 92 | * Added MinDevHandle field to MPI2_IOC_FACTS_REPLY. | ||
| 93 | * Added MPI2_IOCFACTS_CAPABILITY_HOST_BASED_DISCOVERY. | ||
| 94 | * Added MPI2_EVENT_HOST_BASED_DISCOVERY_PHY define. | ||
| 95 | * Added MPI2_EVENT_SAS_TOPO_ES_NO_EXPANDER define. | ||
| 96 | * Added Host Based Discovery Phy Event data. | ||
| 97 | * Added defines for ProductID Product field | ||
| 98 | * (MPI2_FW_HEADER_PID_). | ||
| 99 | * Modified values for SAS ProductID Family | ||
| 100 | * (MPI2_FW_HEADER_PID_FAMILY_). | ||
| 101 | * 02-10-10 02.00.14 Added SAS Quiesce Event structure and defines. | ||
| 102 | * Added PowerManagementControl Request structures and | ||
| 103 | * defines. | ||
| 104 | * 05-12-10 02.00.15 Marked Task Set Full Event as obsolete. | ||
| 105 | * Added MPI2_EVENT_SAS_TOPO_LR_UNSUPPORTED_PHY define. | ||
| 106 | * 11-10-10 02.00.16 Added MPI2_FW_DOWNLOAD_ITYPE_MIN_PRODUCT_SPECIFIC. | ||
| 107 | * 02-23-11 02.00.17 Added SAS NOTIFY Primitive event, and added | ||
| 108 | * SASNotifyPrimitiveMasks field to | ||
| 109 | * MPI2_EVENT_NOTIFICATION_REQUEST. | ||
| 110 | * Added Temperature Threshold Event. | ||
| 111 | * Added Host Message Event. | ||
| 112 | * Added Send Host Message request and reply. | ||
| 113 | * 05-25-11 02.00.18 For Extended Image Header, added | ||
| 114 | * MPI2_EXT_IMAGE_TYPE_MIN_PRODUCT_SPECIFIC and | ||
| 115 | * MPI2_EXT_IMAGE_TYPE_MAX_PRODUCT_SPECIFIC defines. | ||
| 116 | * Deprecated MPI2_EXT_IMAGE_TYPE_MAX define. | ||
| 117 | * 08-24-11 02.00.19 Added PhysicalPort field to | ||
| 118 | * MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE structure. | ||
| 119 | * Marked MPI2_PM_CONTROL_FEATURE_PCIE_LINK as obsolete. | ||
| 120 | * 03-29-12 02.00.21 Added a product specific range to event values. | ||
| 121 | * 07-26-12 02.00.22 Added MPI2_IOCFACTS_EXCEPT_PARTIAL_MEMORY_FAILURE. | ||
| 122 | * Added ElapsedSeconds field to | ||
| 123 | * MPI2_EVENT_DATA_IR_OPERATION_STATUS. | ||
| 124 | * 08-19-13 02.00.23 For IOCInit, added MPI2_IOCINIT_MSGFLAG_RDPQ_ARRAY_MODE | ||
| 125 | * and MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY. | ||
| 126 | * Added MPI2_IOCFACTS_CAPABILITY_RDPQ_ARRAY_CAPABLE. | ||
| 127 | * Added MPI2_FW_DOWNLOAD_ITYPE_PUBLIC_KEY. | ||
| 128 | * Added Encrypted Hash Extended Image. | ||
| 129 | * 12-05-13 02.00.24 Added MPI25_HASH_IMAGE_TYPE_BIOS. | ||
| 130 | * -------------------------------------------------------------------------- | ||
| 131 | */ | ||
| 132 | |||
| 133 | #ifndef MPI2_IOC_H | ||
| 134 | #define MPI2_IOC_H | ||
| 135 | |||
| 136 | /***************************************************************************** | ||
| 137 | * | ||
| 138 | * IOC Messages | ||
| 139 | * | ||
| 140 | *****************************************************************************/ | ||
| 141 | |||
| 142 | /**************************************************************************** | ||
| 143 | * IOCInit message | ||
| 144 | ****************************************************************************/ | ||
| 145 | |||
| 146 | /* IOCInit Request message */ | ||
| 147 | typedef struct _MPI2_IOC_INIT_REQUEST | ||
| 148 | { | ||
| 149 | U8 WhoInit; /* 0x00 */ | ||
| 150 | U8 Reserved1; /* 0x01 */ | ||
| 151 | U8 ChainOffset; /* 0x02 */ | ||
| 152 | U8 Function; /* 0x03 */ | ||
| 153 | U16 Reserved2; /* 0x04 */ | ||
| 154 | U8 Reserved3; /* 0x06 */ | ||
| 155 | U8 MsgFlags; /* 0x07 */ | ||
| 156 | U8 VP_ID; /* 0x08 */ | ||
| 157 | U8 VF_ID; /* 0x09 */ | ||
| 158 | U16 Reserved4; /* 0x0A */ | ||
| 159 | U16 MsgVersion; /* 0x0C */ | ||
| 160 | U16 HeaderVersion; /* 0x0E */ | ||
| 161 | U32 Reserved5; /* 0x10 */ | ||
| 162 | U16 Reserved6; /* 0x14 */ | ||
| 163 | U8 Reserved7; /* 0x16 */ | ||
| 164 | U8 HostMSIxVectors; /* 0x17 */ | ||
| 165 | U16 Reserved8; /* 0x18 */ | ||
| 166 | U16 SystemRequestFrameSize; /* 0x1A */ | ||
| 167 | U16 ReplyDescriptorPostQueueDepth; /* 0x1C */ | ||
| 168 | U16 ReplyFreeQueueDepth; /* 0x1E */ | ||
| 169 | U32 SenseBufferAddressHigh; /* 0x20 */ | ||
| 170 | U32 SystemReplyAddressHigh; /* 0x24 */ | ||
| 171 | U64 SystemRequestFrameBaseAddress; /* 0x28 */ | ||
| 172 | U64 ReplyDescriptorPostQueueAddress;/* 0x30 */ | ||
| 173 | U64 ReplyFreeQueueAddress; /* 0x38 */ | ||
| 174 | U64 TimeStamp; /* 0x40 */ | ||
| 175 | } MPI2_IOC_INIT_REQUEST, MPI2_POINTER PTR_MPI2_IOC_INIT_REQUEST, | ||
| 176 | Mpi2IOCInitRequest_t, MPI2_POINTER pMpi2IOCInitRequest_t; | ||
| 177 | |||
| 178 | /* WhoInit values */ | ||
| 179 | #define MPI2_WHOINIT_NOT_INITIALIZED (0x00) | ||
| 180 | #define MPI2_WHOINIT_SYSTEM_BIOS (0x01) | ||
| 181 | #define MPI2_WHOINIT_ROM_BIOS (0x02) | ||
| 182 | #define MPI2_WHOINIT_PCI_PEER (0x03) | ||
| 183 | #define MPI2_WHOINIT_HOST_DRIVER (0x04) | ||
| 184 | #define MPI2_WHOINIT_MANUFACTURER (0x05) | ||
| 185 | |||
| 186 | /* MsgFlags */ | ||
| 187 | #define MPI2_IOCINIT_MSGFLAG_RDPQ_ARRAY_MODE (0x01) | ||
| 188 | |||
| 189 | /* MsgVersion */ | ||
| 190 | #define MPI2_IOCINIT_MSGVERSION_MAJOR_MASK (0xFF00) | ||
| 191 | #define MPI2_IOCINIT_MSGVERSION_MAJOR_SHIFT (8) | ||
| 192 | #define MPI2_IOCINIT_MSGVERSION_MINOR_MASK (0x00FF) | ||
| 193 | #define MPI2_IOCINIT_MSGVERSION_MINOR_SHIFT (0) | ||
| 194 | |||
| 195 | /* HeaderVersion */ | ||
| 196 | #define MPI2_IOCINIT_HDRVERSION_UNIT_MASK (0xFF00) | ||
| 197 | #define MPI2_IOCINIT_HDRVERSION_UNIT_SHIFT (8) | ||
| 198 | #define MPI2_IOCINIT_HDRVERSION_DEV_MASK (0x00FF) | ||
| 199 | #define MPI2_IOCINIT_HDRVERSION_DEV_SHIFT (0) | ||
| 200 | |||
| 201 | /* minimum depth for a Reply Descriptor Post Queue */ | ||
| 202 | #define MPI2_RDPQ_DEPTH_MIN (16) | ||
| 203 | |||
| 204 | /* Reply Descriptor Post Queue Array Entry */ | ||
| 205 | typedef struct _MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY { | ||
| 206 | U64 RDPQBaseAddress; /* 0x00 */ | ||
| 207 | U32 Reserved1; /* 0x08 */ | ||
| 208 | U32 Reserved2; /* 0x0C */ | ||
| 209 | } MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY, | ||
| 210 | MPI2_POINTER PTR_MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY, | ||
| 211 | Mpi2IOCInitRDPQArrayEntry, MPI2_POINTER pMpi2IOCInitRDPQArrayEntry; | ||
| 212 | |||
| 213 | /* IOCInit Reply message */ | ||
| 214 | typedef struct _MPI2_IOC_INIT_REPLY | ||
| 215 | { | ||
| 216 | U8 WhoInit; /* 0x00 */ | ||
| 217 | U8 Reserved1; /* 0x01 */ | ||
| 218 | U8 MsgLength; /* 0x02 */ | ||
| 219 | U8 Function; /* 0x03 */ | ||
| 220 | U16 Reserved2; /* 0x04 */ | ||
| 221 | U8 Reserved3; /* 0x06 */ | ||
| 222 | U8 MsgFlags; /* 0x07 */ | ||
| 223 | U8 VP_ID; /* 0x08 */ | ||
| 224 | U8 VF_ID; /* 0x09 */ | ||
| 225 | U16 Reserved4; /* 0x0A */ | ||
| 226 | U16 Reserved5; /* 0x0C */ | ||
| 227 | U16 IOCStatus; /* 0x0E */ | ||
| 228 | U32 IOCLogInfo; /* 0x10 */ | ||
| 229 | } MPI2_IOC_INIT_REPLY, MPI2_POINTER PTR_MPI2_IOC_INIT_REPLY, | ||
| 230 | Mpi2IOCInitReply_t, MPI2_POINTER pMpi2IOCInitReply_t; | ||
| 231 | |||
| 232 | |||
| 233 | /**************************************************************************** | ||
| 234 | * IOCFacts message | ||
| 235 | ****************************************************************************/ | ||
| 236 | |||
| 237 | /* IOCFacts Request message */ | ||
| 238 | typedef struct _MPI2_IOC_FACTS_REQUEST | ||
| 239 | { | ||
| 240 | U16 Reserved1; /* 0x00 */ | ||
| 241 | U8 ChainOffset; /* 0x02 */ | ||
| 242 | U8 Function; /* 0x03 */ | ||
| 243 | U16 Reserved2; /* 0x04 */ | ||
| 244 | U8 Reserved3; /* 0x06 */ | ||
| 245 | U8 MsgFlags; /* 0x07 */ | ||
| 246 | U8 VP_ID; /* 0x08 */ | ||
| 247 | U8 VF_ID; /* 0x09 */ | ||
| 248 | U16 Reserved4; /* 0x0A */ | ||
| 249 | } MPI2_IOC_FACTS_REQUEST, MPI2_POINTER PTR_MPI2_IOC_FACTS_REQUEST, | ||
| 250 | Mpi2IOCFactsRequest_t, MPI2_POINTER pMpi2IOCFactsRequest_t; | ||
| 251 | |||
| 252 | |||
| 253 | /* IOCFacts Reply message */ | ||
| 254 | typedef struct _MPI2_IOC_FACTS_REPLY | ||
| 255 | { | ||
| 256 | U16 MsgVersion; /* 0x00 */ | ||
| 257 | U8 MsgLength; /* 0x02 */ | ||
| 258 | U8 Function; /* 0x03 */ | ||
| 259 | U16 HeaderVersion; /* 0x04 */ | ||
| 260 | U8 IOCNumber; /* 0x06 */ | ||
| 261 | U8 MsgFlags; /* 0x07 */ | ||
| 262 | U8 VP_ID; /* 0x08 */ | ||
| 263 | U8 VF_ID; /* 0x09 */ | ||
| 264 | U16 Reserved1; /* 0x0A */ | ||
| 265 | U16 IOCExceptions; /* 0x0C */ | ||
| 266 | U16 IOCStatus; /* 0x0E */ | ||
| 267 | U32 IOCLogInfo; /* 0x10 */ | ||
| 268 | U8 MaxChainDepth; /* 0x14 */ | ||
| 269 | U8 WhoInit; /* 0x15 */ | ||
| 270 | U8 NumberOfPorts; /* 0x16 */ | ||
| 271 | U8 MaxMSIxVectors; /* 0x17 */ | ||
| 272 | U16 RequestCredit; /* 0x18 */ | ||
| 273 | U16 ProductID; /* 0x1A */ | ||
| 274 | U32 IOCCapabilities; /* 0x1C */ | ||
| 275 | MPI2_VERSION_UNION FWVersion; /* 0x20 */ | ||
| 276 | U16 IOCRequestFrameSize; /* 0x24 */ | ||
| 277 | U16 Reserved3; /* 0x26 */ | ||
| 278 | U16 MaxInitiators; /* 0x28 */ | ||
| 279 | U16 MaxTargets; /* 0x2A */ | ||
| 280 | U16 MaxSasExpanders; /* 0x2C */ | ||
| 281 | U16 MaxEnclosures; /* 0x2E */ | ||
| 282 | U16 ProtocolFlags; /* 0x30 */ | ||
| 283 | U16 HighPriorityCredit; /* 0x32 */ | ||
| 284 | U16 MaxReplyDescriptorPostQueueDepth; /* 0x34 */ | ||
| 285 | U8 ReplyFrameSize; /* 0x36 */ | ||
| 286 | U8 MaxVolumes; /* 0x37 */ | ||
| 287 | U16 MaxDevHandle; /* 0x38 */ | ||
| 288 | U16 MaxPersistentEntries; /* 0x3A */ | ||
| 289 | U16 MinDevHandle; /* 0x3C */ | ||
| 290 | U16 Reserved4; /* 0x3E */ | ||
| 291 | } MPI2_IOC_FACTS_REPLY, MPI2_POINTER PTR_MPI2_IOC_FACTS_REPLY, | ||
| 292 | Mpi2IOCFactsReply_t, MPI2_POINTER pMpi2IOCFactsReply_t; | ||
| 293 | |||
| 294 | /* MsgVersion */ | ||
| 295 | #define MPI2_IOCFACTS_MSGVERSION_MAJOR_MASK (0xFF00) | ||
| 296 | #define MPI2_IOCFACTS_MSGVERSION_MAJOR_SHIFT (8) | ||
| 297 | #define MPI2_IOCFACTS_MSGVERSION_MINOR_MASK (0x00FF) | ||
| 298 | #define MPI2_IOCFACTS_MSGVERSION_MINOR_SHIFT (0) | ||
| 299 | |||
| 300 | /* HeaderVersion */ | ||
| 301 | #define MPI2_IOCFACTS_HDRVERSION_UNIT_MASK (0xFF00) | ||
| 302 | #define MPI2_IOCFACTS_HDRVERSION_UNIT_SHIFT (8) | ||
| 303 | #define MPI2_IOCFACTS_HDRVERSION_DEV_MASK (0x00FF) | ||
| 304 | #define MPI2_IOCFACTS_HDRVERSION_DEV_SHIFT (0) | ||
| 305 | |||
| 306 | /* IOCExceptions */ | ||
| 307 | #define MPI2_IOCFACTS_EXCEPT_PARTIAL_MEMORY_FAILURE (0x0200) | ||
| 308 | #define MPI2_IOCFACTS_EXCEPT_IR_FOREIGN_CONFIG_MAX (0x0100) | ||
| 309 | |||
| 310 | #define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_MASK (0x00E0) | ||
| 311 | #define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_GOOD (0x0000) | ||
| 312 | #define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_BACKUP (0x0020) | ||
| 313 | #define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_RESTORED (0x0040) | ||
| 314 | #define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_CORRUPT_BACKUP (0x0060) | ||
| 315 | |||
| 316 | #define MPI2_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED (0x0010) | ||
| 317 | #define MPI2_IOCFACTS_EXCEPT_MANUFACT_CHECKSUM_FAIL (0x0008) | ||
| 318 | #define MPI2_IOCFACTS_EXCEPT_FW_CHECKSUM_FAIL (0x0004) | ||
| 319 | #define MPI2_IOCFACTS_EXCEPT_RAID_CONFIG_INVALID (0x0002) | ||
| 320 | #define MPI2_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL (0x0001) | ||
| 321 | |||
| 322 | /* defines for WhoInit field are after the IOCInit Request */ | ||
| 323 | |||
| 324 | /* ProductID field uses MPI2_FW_HEADER_PID_ */ | ||
| 325 | |||
| 326 | /* IOCCapabilities */ | ||
| 327 | #define MPI2_IOCFACTS_CAPABILITY_RDPQ_ARRAY_CAPABLE (0x00040000) | ||
| 328 | #define MPI2_IOCFACTS_CAPABILITY_HOST_BASED_DISCOVERY (0x00010000) | ||
| 329 | #define MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX (0x00008000) | ||
| 330 | #define MPI2_IOCFACTS_CAPABILITY_RAID_ACCELERATOR (0x00004000) | ||
| 331 | #define MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY (0x00002000) | ||
| 332 | #define MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID (0x00001000) | ||
| 333 | #define MPI2_IOCFACTS_CAPABILITY_TLR (0x00000800) | ||
| 334 | #define MPI2_IOCFACTS_CAPABILITY_MULTICAST (0x00000100) | ||
| 335 | #define MPI2_IOCFACTS_CAPABILITY_BIDIRECTIONAL_TARGET (0x00000080) | ||
| 336 | #define MPI2_IOCFACTS_CAPABILITY_EEDP (0x00000040) | ||
| 337 | #define MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER (0x00000020) | ||
| 338 | #define MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER (0x00000010) | ||
| 339 | #define MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER (0x00000008) | ||
| 340 | #define MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING (0x00000004) | ||
| 341 | |||
| 342 | /* ProtocolFlags */ | ||
| 343 | #define MPI2_IOCFACTS_PROTOCOL_SCSI_TARGET (0x0001) | ||
| 344 | #define MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR (0x0002) | ||
| 345 | |||
| 346 | |||
| 347 | /**************************************************************************** | ||
| 348 | * PortFacts message | ||
| 349 | ****************************************************************************/ | ||
| 350 | |||
| 351 | /* PortFacts Request message */ | ||
| 352 | typedef struct _MPI2_PORT_FACTS_REQUEST | ||
| 353 | { | ||
| 354 | U16 Reserved1; /* 0x00 */ | ||
| 355 | U8 ChainOffset; /* 0x02 */ | ||
| 356 | U8 Function; /* 0x03 */ | ||
| 357 | U16 Reserved2; /* 0x04 */ | ||
| 358 | U8 PortNumber; /* 0x06 */ | ||
| 359 | U8 MsgFlags; /* 0x07 */ | ||
| 360 | U8 VP_ID; /* 0x08 */ | ||
| 361 | U8 VF_ID; /* 0x09 */ | ||
| 362 | U16 Reserved3; /* 0x0A */ | ||
| 363 | } MPI2_PORT_FACTS_REQUEST, MPI2_POINTER PTR_MPI2_PORT_FACTS_REQUEST, | ||
| 364 | Mpi2PortFactsRequest_t, MPI2_POINTER pMpi2PortFactsRequest_t; | ||
| 365 | |||
| 366 | /* PortFacts Reply message */ | ||
| 367 | typedef struct _MPI2_PORT_FACTS_REPLY | ||
| 368 | { | ||
| 369 | U16 Reserved1; /* 0x00 */ | ||
| 370 | U8 MsgLength; /* 0x02 */ | ||
| 371 | U8 Function; /* 0x03 */ | ||
| 372 | U16 Reserved2; /* 0x04 */ | ||
| 373 | U8 PortNumber; /* 0x06 */ | ||
| 374 | U8 MsgFlags; /* 0x07 */ | ||
| 375 | U8 VP_ID; /* 0x08 */ | ||
| 376 | U8 VF_ID; /* 0x09 */ | ||
| 377 | U16 Reserved3; /* 0x0A */ | ||
| 378 | U16 Reserved4; /* 0x0C */ | ||
| 379 | U16 IOCStatus; /* 0x0E */ | ||
| 380 | U32 IOCLogInfo; /* 0x10 */ | ||
| 381 | U8 Reserved5; /* 0x14 */ | ||
| 382 | U8 PortType; /* 0x15 */ | ||
| 383 | U16 Reserved6; /* 0x16 */ | ||
| 384 | U16 MaxPostedCmdBuffers; /* 0x18 */ | ||
| 385 | U16 Reserved7; /* 0x1A */ | ||
| 386 | } MPI2_PORT_FACTS_REPLY, MPI2_POINTER PTR_MPI2_PORT_FACTS_REPLY, | ||
| 387 | Mpi2PortFactsReply_t, MPI2_POINTER pMpi2PortFactsReply_t; | ||
| 388 | |||
| 389 | /* PortType values */ | ||
| 390 | #define MPI2_PORTFACTS_PORTTYPE_INACTIVE (0x00) | ||
| 391 | #define MPI2_PORTFACTS_PORTTYPE_FC (0x10) | ||
| 392 | #define MPI2_PORTFACTS_PORTTYPE_ISCSI (0x20) | ||
| 393 | #define MPI2_PORTFACTS_PORTTYPE_SAS_PHYSICAL (0x30) | ||
| 394 | #define MPI2_PORTFACTS_PORTTYPE_SAS_VIRTUAL (0x31) | ||
| 395 | |||
| 396 | |||
| 397 | /**************************************************************************** | ||
| 398 | * PortEnable message | ||
| 399 | ****************************************************************************/ | ||
| 400 | |||
| 401 | /* PortEnable Request message */ | ||
| 402 | typedef struct _MPI2_PORT_ENABLE_REQUEST | ||
| 403 | { | ||
| 404 | U16 Reserved1; /* 0x00 */ | ||
| 405 | U8 ChainOffset; /* 0x02 */ | ||
| 406 | U8 Function; /* 0x03 */ | ||
| 407 | U8 Reserved2; /* 0x04 */ | ||
| 408 | U8 PortFlags; /* 0x05 */ | ||
| 409 | U8 Reserved3; /* 0x06 */ | ||
| 410 | U8 MsgFlags; /* 0x07 */ | ||
| 411 | U8 VP_ID; /* 0x08 */ | ||
| 412 | U8 VF_ID; /* 0x09 */ | ||
| 413 | U16 Reserved4; /* 0x0A */ | ||
| 414 | } MPI2_PORT_ENABLE_REQUEST, MPI2_POINTER PTR_MPI2_PORT_ENABLE_REQUEST, | ||
| 415 | Mpi2PortEnableRequest_t, MPI2_POINTER pMpi2PortEnableRequest_t; | ||
| 416 | |||
| 417 | |||
| 418 | /* PortEnable Reply message */ | ||
| 419 | typedef struct _MPI2_PORT_ENABLE_REPLY | ||
| 420 | { | ||
| 421 | U16 Reserved1; /* 0x00 */ | ||
| 422 | U8 MsgLength; /* 0x02 */ | ||
| 423 | U8 Function; /* 0x03 */ | ||
| 424 | U8 Reserved2; /* 0x04 */ | ||
| 425 | U8 PortFlags; /* 0x05 */ | ||
| 426 | U8 Reserved3; /* 0x06 */ | ||
| 427 | U8 MsgFlags; /* 0x07 */ | ||
| 428 | U8 VP_ID; /* 0x08 */ | ||
| 429 | U8 VF_ID; /* 0x09 */ | ||
| 430 | U16 Reserved4; /* 0x0A */ | ||
| 431 | U16 Reserved5; /* 0x0C */ | ||
| 432 | U16 IOCStatus; /* 0x0E */ | ||
| 433 | U32 IOCLogInfo; /* 0x10 */ | ||
| 434 | } MPI2_PORT_ENABLE_REPLY, MPI2_POINTER PTR_MPI2_PORT_ENABLE_REPLY, | ||
| 435 | Mpi2PortEnableReply_t, MPI2_POINTER pMpi2PortEnableReply_t; | ||
| 436 | |||
| 437 | |||
| 438 | /**************************************************************************** | ||
| 439 | * EventNotification message | ||
| 440 | ****************************************************************************/ | ||
| 441 | |||
| 442 | /* EventNotification Request message */ | ||
| 443 | #define MPI2_EVENT_NOTIFY_EVENTMASK_WORDS (4) | ||
| 444 | |||
| 445 | typedef struct _MPI2_EVENT_NOTIFICATION_REQUEST | ||
| 446 | { | ||
| 447 | U16 Reserved1; /* 0x00 */ | ||
| 448 | U8 ChainOffset; /* 0x02 */ | ||
| 449 | U8 Function; /* 0x03 */ | ||
| 450 | U16 Reserved2; /* 0x04 */ | ||
| 451 | U8 Reserved3; /* 0x06 */ | ||
| 452 | U8 MsgFlags; /* 0x07 */ | ||
| 453 | U8 VP_ID; /* 0x08 */ | ||
| 454 | U8 VF_ID; /* 0x09 */ | ||
| 455 | U16 Reserved4; /* 0x0A */ | ||
| 456 | U32 Reserved5; /* 0x0C */ | ||
| 457 | U32 Reserved6; /* 0x10 */ | ||
| 458 | U32 EventMasks[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];/* 0x14 */ | ||
| 459 | U16 SASBroadcastPrimitiveMasks; /* 0x24 */ | ||
| 460 | U16 SASNotifyPrimitiveMasks; /* 0x26 */ | ||
| 461 | U32 Reserved8; /* 0x28 */ | ||
| 462 | } MPI2_EVENT_NOTIFICATION_REQUEST, | ||
| 463 | MPI2_POINTER PTR_MPI2_EVENT_NOTIFICATION_REQUEST, | ||
| 464 | Mpi2EventNotificationRequest_t, MPI2_POINTER pMpi2EventNotificationRequest_t; | ||
| 465 | |||
| 466 | |||
| 467 | /* EventNotification Reply message */ | ||
| 468 | typedef struct _MPI2_EVENT_NOTIFICATION_REPLY | ||
| 469 | { | ||
| 470 | U16 EventDataLength; /* 0x00 */ | ||
| 471 | U8 MsgLength; /* 0x02 */ | ||
| 472 | U8 Function; /* 0x03 */ | ||
| 473 | U16 Reserved1; /* 0x04 */ | ||
| 474 | U8 AckRequired; /* 0x06 */ | ||
| 475 | U8 MsgFlags; /* 0x07 */ | ||
| 476 | U8 VP_ID; /* 0x08 */ | ||
| 477 | U8 VF_ID; /* 0x09 */ | ||
| 478 | U16 Reserved2; /* 0x0A */ | ||
| 479 | U16 Reserved3; /* 0x0C */ | ||
| 480 | U16 IOCStatus; /* 0x0E */ | ||
| 481 | U32 IOCLogInfo; /* 0x10 */ | ||
| 482 | U16 Event; /* 0x14 */ | ||
| 483 | U16 Reserved4; /* 0x16 */ | ||
| 484 | U32 EventContext; /* 0x18 */ | ||
| 485 | U32 EventData[1]; /* 0x1C */ | ||
| 486 | } MPI2_EVENT_NOTIFICATION_REPLY, MPI2_POINTER PTR_MPI2_EVENT_NOTIFICATION_REPLY, | ||
| 487 | Mpi2EventNotificationReply_t, MPI2_POINTER pMpi2EventNotificationReply_t; | ||
| 488 | |||
| 489 | /* AckRequired */ | ||
| 490 | #define MPI2_EVENT_NOTIFICATION_ACK_NOT_REQUIRED (0x00) | ||
| 491 | #define MPI2_EVENT_NOTIFICATION_ACK_REQUIRED (0x01) | ||
| 492 | |||
| 493 | /* Event */ | ||
| 494 | #define MPI2_EVENT_LOG_DATA (0x0001) | ||
| 495 | #define MPI2_EVENT_STATE_CHANGE (0x0002) | ||
| 496 | #define MPI2_EVENT_HARD_RESET_RECEIVED (0x0005) | ||
| 497 | #define MPI2_EVENT_EVENT_CHANGE (0x000A) | ||
| 498 | #define MPI2_EVENT_TASK_SET_FULL (0x000E) /* obsolete */ | ||
| 499 | #define MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE (0x000F) | ||
| 500 | #define MPI2_EVENT_IR_OPERATION_STATUS (0x0014) | ||
| 501 | #define MPI2_EVENT_SAS_DISCOVERY (0x0016) | ||
| 502 | #define MPI2_EVENT_SAS_BROADCAST_PRIMITIVE (0x0017) | ||
| 503 | #define MPI2_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE (0x0018) | ||
| 504 | #define MPI2_EVENT_SAS_INIT_TABLE_OVERFLOW (0x0019) | ||
| 505 | #define MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST (0x001C) | ||
| 506 | #define MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE (0x001D) | ||
| 507 | #define MPI2_EVENT_IR_VOLUME (0x001E) | ||
| 508 | #define MPI2_EVENT_IR_PHYSICAL_DISK (0x001F) | ||
| 509 | #define MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST (0x0020) | ||
| 510 | #define MPI2_EVENT_LOG_ENTRY_ADDED (0x0021) | ||
| 511 | #define MPI2_EVENT_SAS_PHY_COUNTER (0x0022) | ||
| 512 | #define MPI2_EVENT_GPIO_INTERRUPT (0x0023) | ||
| 513 | #define MPI2_EVENT_HOST_BASED_DISCOVERY_PHY (0x0024) | ||
| 514 | #define MPI2_EVENT_SAS_QUIESCE (0x0025) | ||
| 515 | #define MPI2_EVENT_SAS_NOTIFY_PRIMITIVE (0x0026) | ||
| 516 | #define MPI2_EVENT_TEMP_THRESHOLD (0x0027) | ||
| 517 | #define MPI2_EVENT_HOST_MESSAGE (0x0028) | ||
| 518 | #define MPI2_EVENT_MIN_PRODUCT_SPECIFIC (0x006E) | ||
| 519 | #define MPI2_EVENT_MAX_PRODUCT_SPECIFIC (0x007F) | ||
| 520 | |||
| 521 | /* Log Entry Added Event data */ | ||
| 522 | |||
| 523 | /* the following structure matches MPI2_LOG_0_ENTRY in mpi2_cnfg.h */ | ||
| 524 | #define MPI2_EVENT_DATA_LOG_DATA_LENGTH (0x1C) | ||
| 525 | |||
| 526 | typedef struct _MPI2_EVENT_DATA_LOG_ENTRY_ADDED | ||
| 527 | { | ||
| 528 | U64 TimeStamp; /* 0x00 */ | ||
| 529 | U32 Reserved1; /* 0x08 */ | ||
| 530 | U16 LogSequence; /* 0x0C */ | ||
| 531 | U16 LogEntryQualifier; /* 0x0E */ | ||
| 532 | U8 VP_ID; /* 0x10 */ | ||
| 533 | U8 VF_ID; /* 0x11 */ | ||
| 534 | U16 Reserved2; /* 0x12 */ | ||
| 535 | U8 LogData[MPI2_EVENT_DATA_LOG_DATA_LENGTH];/* 0x14 */ | ||
| 536 | } MPI2_EVENT_DATA_LOG_ENTRY_ADDED, | ||
| 537 | MPI2_POINTER PTR_MPI2_EVENT_DATA_LOG_ENTRY_ADDED, | ||
| 538 | Mpi2EventDataLogEntryAdded_t, MPI2_POINTER pMpi2EventDataLogEntryAdded_t; | ||
| 539 | |||
| 540 | /* GPIO Interrupt Event data */ | ||
| 541 | |||
| 542 | typedef struct _MPI2_EVENT_DATA_GPIO_INTERRUPT { | ||
| 543 | U8 GPIONum; /* 0x00 */ | ||
| 544 | U8 Reserved1; /* 0x01 */ | ||
| 545 | U16 Reserved2; /* 0x02 */ | ||
| 546 | } MPI2_EVENT_DATA_GPIO_INTERRUPT, | ||
| 547 | MPI2_POINTER PTR_MPI2_EVENT_DATA_GPIO_INTERRUPT, | ||
| 548 | Mpi2EventDataGpioInterrupt_t, MPI2_POINTER pMpi2EventDataGpioInterrupt_t; | ||
| 549 | |||
| 550 | /* Temperature Threshold Event data */ | ||
| 551 | |||
| 552 | typedef struct _MPI2_EVENT_DATA_TEMPERATURE { | ||
| 553 | U16 Status; /* 0x00 */ | ||
| 554 | U8 SensorNum; /* 0x02 */ | ||
| 555 | U8 Reserved1; /* 0x03 */ | ||
| 556 | U16 CurrentTemperature; /* 0x04 */ | ||
| 557 | U16 Reserved2; /* 0x06 */ | ||
| 558 | U32 Reserved3; /* 0x08 */ | ||
| 559 | U32 Reserved4; /* 0x0C */ | ||
| 560 | } MPI2_EVENT_DATA_TEMPERATURE, | ||
| 561 | MPI2_POINTER PTR_MPI2_EVENT_DATA_TEMPERATURE, | ||
| 562 | Mpi2EventDataTemperature_t, MPI2_POINTER pMpi2EventDataTemperature_t; | ||
| 563 | |||
| 564 | /* Temperature Threshold Event data Status bits */ | ||
| 565 | #define MPI2_EVENT_TEMPERATURE3_EXCEEDED (0x0008) | ||
| 566 | #define MPI2_EVENT_TEMPERATURE2_EXCEEDED (0x0004) | ||
| 567 | #define MPI2_EVENT_TEMPERATURE1_EXCEEDED (0x0002) | ||
| 568 | #define MPI2_EVENT_TEMPERATURE0_EXCEEDED (0x0001) | ||
| 569 | |||
| 570 | |||
| 571 | /* Host Message Event data */ | ||
| 572 | |||
| 573 | typedef struct _MPI2_EVENT_DATA_HOST_MESSAGE { | ||
| 574 | U8 SourceVF_ID; /* 0x00 */ | ||
| 575 | U8 Reserved1; /* 0x01 */ | ||
| 576 | U16 Reserved2; /* 0x02 */ | ||
| 577 | U32 Reserved3; /* 0x04 */ | ||
| 578 | U32 HostData[1]; /* 0x08 */ | ||
| 579 | } MPI2_EVENT_DATA_HOST_MESSAGE, MPI2_POINTER PTR_MPI2_EVENT_DATA_HOST_MESSAGE, | ||
| 580 | Mpi2EventDataHostMessage_t, MPI2_POINTER pMpi2EventDataHostMessage_t; | ||
| 581 | |||
| 582 | |||
| 583 | /* Hard Reset Received Event data */ | ||
| 584 | |||
| 585 | typedef struct _MPI2_EVENT_DATA_HARD_RESET_RECEIVED | ||
| 586 | { | ||
| 587 | U8 Reserved1; /* 0x00 */ | ||
| 588 | U8 Port; /* 0x01 */ | ||
| 589 | U16 Reserved2; /* 0x02 */ | ||
| 590 | } MPI2_EVENT_DATA_HARD_RESET_RECEIVED, | ||
| 591 | MPI2_POINTER PTR_MPI2_EVENT_DATA_HARD_RESET_RECEIVED, | ||
| 592 | Mpi2EventDataHardResetReceived_t, | ||
| 593 | MPI2_POINTER pMpi2EventDataHardResetReceived_t; | ||
| 594 | |||
| 595 | /* Task Set Full Event data */ | ||
| 596 | /* this event is obsolete */ | ||
| 597 | |||
| 598 | typedef struct _MPI2_EVENT_DATA_TASK_SET_FULL | ||
| 599 | { | ||
| 600 | U16 DevHandle; /* 0x00 */ | ||
| 601 | U16 CurrentDepth; /* 0x02 */ | ||
| 602 | } MPI2_EVENT_DATA_TASK_SET_FULL, MPI2_POINTER PTR_MPI2_EVENT_DATA_TASK_SET_FULL, | ||
| 603 | Mpi2EventDataTaskSetFull_t, MPI2_POINTER pMpi2EventDataTaskSetFull_t; | ||
| 604 | |||
| 605 | |||
| 606 | /* SAS Device Status Change Event data */ | ||
| 607 | |||
| 608 | typedef struct _MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE | ||
| 609 | { | ||
| 610 | U16 TaskTag; /* 0x00 */ | ||
| 611 | U8 ReasonCode; /* 0x02 */ | ||
| 612 | U8 PhysicalPort; /* 0x03 */ | ||
| 613 | U8 ASC; /* 0x04 */ | ||
| 614 | U8 ASCQ; /* 0x05 */ | ||
| 615 | U16 DevHandle; /* 0x06 */ | ||
| 616 | U32 Reserved2; /* 0x08 */ | ||
| 617 | U64 SASAddress; /* 0x0C */ | ||
| 618 | U8 LUN[8]; /* 0x14 */ | ||
| 619 | } MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE, | ||
| 620 | MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE, | ||
| 621 | Mpi2EventDataSasDeviceStatusChange_t, | ||
| 622 | MPI2_POINTER pMpi2EventDataSasDeviceStatusChange_t; | ||
| 623 | |||
| 624 | /* SAS Device Status Change Event data ReasonCode values */ | ||
| 625 | #define MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA (0x05) | ||
| 626 | #define MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED (0x07) | ||
| 627 | #define MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET (0x08) | ||
| 628 | #define MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL (0x09) | ||
| 629 | #define MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL (0x0A) | ||
| 630 | #define MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL (0x0B) | ||
| 631 | #define MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL (0x0C) | ||
| 632 | #define MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION (0x0D) | ||
| 633 | #define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET (0x0E) | ||
| 634 | #define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL (0x0F) | ||
| 635 | #define MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE (0x10) | ||
| 636 | #define MPI2_EVENT_SAS_DEV_STAT_RC_EXPANDER_REDUCED_FUNCTIONALITY (0x11) | ||
| 637 | #define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_EXPANDER_REDUCED_FUNCTIONALITY (0x12) | ||
| 638 | |||
| 639 | |||
| 640 | /* Integrated RAID Operation Status Event data */ | ||
| 641 | |||
| 642 | typedef struct _MPI2_EVENT_DATA_IR_OPERATION_STATUS | ||
| 643 | { | ||
| 644 | U16 VolDevHandle; /* 0x00 */ | ||
| 645 | U16 Reserved1; /* 0x02 */ | ||
| 646 | U8 RAIDOperation; /* 0x04 */ | ||
| 647 | U8 PercentComplete; /* 0x05 */ | ||
| 648 | U16 Reserved2; /* 0x06 */ | ||
| 649 | U32 ElapsedSeconds; /* 0x08 */ | ||
| 650 | } MPI2_EVENT_DATA_IR_OPERATION_STATUS, | ||
| 651 | MPI2_POINTER PTR_MPI2_EVENT_DATA_IR_OPERATION_STATUS, | ||
| 652 | Mpi2EventDataIrOperationStatus_t, | ||
| 653 | MPI2_POINTER pMpi2EventDataIrOperationStatus_t; | ||
| 654 | |||
| 655 | /* Integrated RAID Operation Status Event data RAIDOperation values */ | ||
| 656 | #define MPI2_EVENT_IR_RAIDOP_RESYNC (0x00) | ||
| 657 | #define MPI2_EVENT_IR_RAIDOP_ONLINE_CAP_EXPANSION (0x01) | ||
| 658 | #define MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK (0x02) | ||
| 659 | #define MPI2_EVENT_IR_RAIDOP_BACKGROUND_INIT (0x03) | ||
| 660 | #define MPI2_EVENT_IR_RAIDOP_MAKE_DATA_CONSISTENT (0x04) | ||
| 661 | |||
| 662 | |||
| 663 | /* Integrated RAID Volume Event data */ | ||
| 664 | |||
| 665 | typedef struct _MPI2_EVENT_DATA_IR_VOLUME | ||
| 666 | { | ||
| 667 | U16 VolDevHandle; /* 0x00 */ | ||
| 668 | U8 ReasonCode; /* 0x02 */ | ||
| 669 | U8 Reserved1; /* 0x03 */ | ||
| 670 | U32 NewValue; /* 0x04 */ | ||
| 671 | U32 PreviousValue; /* 0x08 */ | ||
| 672 | } MPI2_EVENT_DATA_IR_VOLUME, MPI2_POINTER PTR_MPI2_EVENT_DATA_IR_VOLUME, | ||
| 673 | Mpi2EventDataIrVolume_t, MPI2_POINTER pMpi2EventDataIrVolume_t; | ||
| 674 | |||
| 675 | /* Integrated RAID Volume Event data ReasonCode values */ | ||
| 676 | #define MPI2_EVENT_IR_VOLUME_RC_SETTINGS_CHANGED (0x01) | ||
| 677 | #define MPI2_EVENT_IR_VOLUME_RC_STATUS_FLAGS_CHANGED (0x02) | ||
| 678 | #define MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED (0x03) | ||
| 679 | |||
| 680 | |||
| 681 | /* Integrated RAID Physical Disk Event data */ | ||
| 682 | |||
| 683 | typedef struct _MPI2_EVENT_DATA_IR_PHYSICAL_DISK | ||
| 684 | { | ||
| 685 | U16 Reserved1; /* 0x00 */ | ||
| 686 | U8 ReasonCode; /* 0x02 */ | ||
| 687 | U8 PhysDiskNum; /* 0x03 */ | ||
| 688 | U16 PhysDiskDevHandle; /* 0x04 */ | ||
| 689 | U16 Reserved2; /* 0x06 */ | ||
| 690 | U16 Slot; /* 0x08 */ | ||
| 691 | U16 EnclosureHandle; /* 0x0A */ | ||
| 692 | U32 NewValue; /* 0x0C */ | ||
| 693 | U32 PreviousValue; /* 0x10 */ | ||
| 694 | } MPI2_EVENT_DATA_IR_PHYSICAL_DISK, | ||
| 695 | MPI2_POINTER PTR_MPI2_EVENT_DATA_IR_PHYSICAL_DISK, | ||
| 696 | Mpi2EventDataIrPhysicalDisk_t, MPI2_POINTER pMpi2EventDataIrPhysicalDisk_t; | ||
| 697 | |||
| 698 | /* Integrated RAID Physical Disk Event data ReasonCode values */ | ||
| 699 | #define MPI2_EVENT_IR_PHYSDISK_RC_SETTINGS_CHANGED (0x01) | ||
| 700 | #define MPI2_EVENT_IR_PHYSDISK_RC_STATUS_FLAGS_CHANGED (0x02) | ||
| 701 | #define MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED (0x03) | ||
| 702 | |||
| 703 | |||
| 704 | /* Integrated RAID Configuration Change List Event data */ | ||
| 705 | |||
| 706 | /* | ||
| 707 | * Host code (drivers, BIOS, utilities, etc.) should leave this define set to | ||
| 708 | * one and check NumElements at runtime. | ||
| 709 | */ | ||
| 710 | #ifndef MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT | ||
| 711 | #define MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT (1) | ||
| 712 | #endif | ||
| 713 | |||
| 714 | typedef struct _MPI2_EVENT_IR_CONFIG_ELEMENT | ||
| 715 | { | ||
| 716 | U16 ElementFlags; /* 0x00 */ | ||
| 717 | U16 VolDevHandle; /* 0x02 */ | ||
| 718 | U8 ReasonCode; /* 0x04 */ | ||
| 719 | U8 PhysDiskNum; /* 0x05 */ | ||
| 720 | U16 PhysDiskDevHandle; /* 0x06 */ | ||
| 721 | } MPI2_EVENT_IR_CONFIG_ELEMENT, MPI2_POINTER PTR_MPI2_EVENT_IR_CONFIG_ELEMENT, | ||
| 722 | Mpi2EventIrConfigElement_t, MPI2_POINTER pMpi2EventIrConfigElement_t; | ||
| 723 | |||
| 724 | /* IR Configuration Change List Event data ElementFlags values */ | ||
| 725 | #define MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK (0x000F) | ||
| 726 | #define MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT (0x0000) | ||
| 727 | #define MPI2_EVENT_IR_CHANGE_EFLAGS_VOLPHYSDISK_ELEMENT (0x0001) | ||
| 728 | #define MPI2_EVENT_IR_CHANGE_EFLAGS_HOTSPARE_ELEMENT (0x0002) | ||
| 729 | |||
| 730 | /* IR Configuration Change List Event data ReasonCode values */ | ||
| 731 | #define MPI2_EVENT_IR_CHANGE_RC_ADDED (0x01) | ||
| 732 | #define MPI2_EVENT_IR_CHANGE_RC_REMOVED (0x02) | ||
| 733 | #define MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE (0x03) | ||
| 734 | #define MPI2_EVENT_IR_CHANGE_RC_HIDE (0x04) | ||
| 735 | #define MPI2_EVENT_IR_CHANGE_RC_UNHIDE (0x05) | ||
| 736 | #define MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED (0x06) | ||
| 737 | #define MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED (0x07) | ||
| 738 | #define MPI2_EVENT_IR_CHANGE_RC_PD_CREATED (0x08) | ||
| 739 | #define MPI2_EVENT_IR_CHANGE_RC_PD_DELETED (0x09) | ||
| 740 | |||
| 741 | typedef struct _MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST | ||
| 742 | { | ||
| 743 | U8 NumElements; /* 0x00 */ | ||
| 744 | U8 Reserved1; /* 0x01 */ | ||
| 745 | U8 Reserved2; /* 0x02 */ | ||
| 746 | U8 ConfigNum; /* 0x03 */ | ||
| 747 | U32 Flags; /* 0x04 */ | ||
| 748 | MPI2_EVENT_IR_CONFIG_ELEMENT ConfigElement[MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT]; /* 0x08 */ | ||
| 749 | } MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST, | ||
| 750 | MPI2_POINTER PTR_MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST, | ||
| 751 | Mpi2EventDataIrConfigChangeList_t, | ||
| 752 | MPI2_POINTER pMpi2EventDataIrConfigChangeList_t; | ||
| 753 | |||
| 754 | /* IR Configuration Change List Event data Flags values */ | ||
| 755 | #define MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG (0x00000001) | ||
| 756 | |||
| 757 | |||
| 758 | /* SAS Discovery Event data */ | ||
| 759 | |||
| 760 | typedef struct _MPI2_EVENT_DATA_SAS_DISCOVERY | ||
| 761 | { | ||
| 762 | U8 Flags; /* 0x00 */ | ||
| 763 | U8 ReasonCode; /* 0x01 */ | ||
| 764 | U8 PhysicalPort; /* 0x02 */ | ||
| 765 | U8 Reserved1; /* 0x03 */ | ||
| 766 | U32 DiscoveryStatus; /* 0x04 */ | ||
| 767 | } MPI2_EVENT_DATA_SAS_DISCOVERY, | ||
| 768 | MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_DISCOVERY, | ||
| 769 | Mpi2EventDataSasDiscovery_t, MPI2_POINTER pMpi2EventDataSasDiscovery_t; | ||
| 770 | |||
| 771 | /* SAS Discovery Event data Flags values */ | ||
| 772 | #define MPI2_EVENT_SAS_DISC_DEVICE_CHANGE (0x02) | ||
| 773 | #define MPI2_EVENT_SAS_DISC_IN_PROGRESS (0x01) | ||
| 774 | |||
| 775 | /* SAS Discovery Event data ReasonCode values */ | ||
| 776 | #define MPI2_EVENT_SAS_DISC_RC_STARTED (0x01) | ||
| 777 | #define MPI2_EVENT_SAS_DISC_RC_COMPLETED (0x02) | ||
| 778 | |||
| 779 | /* SAS Discovery Event data DiscoveryStatus values */ | ||
| 780 | #define MPI2_EVENT_SAS_DISC_DS_MAX_ENCLOSURES_EXCEED (0x80000000) | ||
| 781 | #define MPI2_EVENT_SAS_DISC_DS_MAX_EXPANDERS_EXCEED (0x40000000) | ||
| 782 | #define MPI2_EVENT_SAS_DISC_DS_MAX_DEVICES_EXCEED (0x20000000) | ||
| 783 | #define MPI2_EVENT_SAS_DISC_DS_MAX_TOPO_PHYS_EXCEED (0x10000000) | ||
| 784 | #define MPI2_EVENT_SAS_DISC_DS_DOWNSTREAM_INITIATOR (0x08000000) | ||
| 785 | #define MPI2_EVENT_SAS_DISC_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE (0x00008000) | ||
| 786 | #define MPI2_EVENT_SAS_DISC_DS_EXP_MULTI_SUBTRACTIVE (0x00004000) | ||
| 787 | #define MPI2_EVENT_SAS_DISC_DS_MULTI_PORT_DOMAIN (0x00002000) | ||
| 788 | #define MPI2_EVENT_SAS_DISC_DS_TABLE_TO_SUBTRACTIVE_LINK (0x00001000) | ||
| 789 | #define MPI2_EVENT_SAS_DISC_DS_UNSUPPORTED_DEVICE (0x00000800) | ||
| 790 | #define MPI2_EVENT_SAS_DISC_DS_TABLE_LINK (0x00000400) | ||
| 791 | #define MPI2_EVENT_SAS_DISC_DS_SUBTRACTIVE_LINK (0x00000200) | ||
| 792 | #define MPI2_EVENT_SAS_DISC_DS_SMP_CRC_ERROR (0x00000100) | ||
| 793 | #define MPI2_EVENT_SAS_DISC_DS_SMP_FUNCTION_FAILED (0x00000080) | ||
| 794 | #define MPI2_EVENT_SAS_DISC_DS_INDEX_NOT_EXIST (0x00000040) | ||
| 795 | #define MPI2_EVENT_SAS_DISC_DS_OUT_ROUTE_ENTRIES (0x00000020) | ||
| 796 | #define MPI2_EVENT_SAS_DISC_DS_SMP_TIMEOUT (0x00000010) | ||
| 797 | #define MPI2_EVENT_SAS_DISC_DS_MULTIPLE_PORTS (0x00000004) | ||
| 798 | #define MPI2_EVENT_SAS_DISC_DS_UNADDRESSABLE_DEVICE (0x00000002) | ||
| 799 | #define MPI2_EVENT_SAS_DISC_DS_LOOP_DETECTED (0x00000001) | ||
| 800 | |||
| 801 | |||
| 802 | /* SAS Broadcast Primitive Event data */ | ||
| 803 | |||
| 804 | typedef struct _MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE | ||
| 805 | { | ||
| 806 | U8 PhyNum; /* 0x00 */ | ||
| 807 | U8 Port; /* 0x01 */ | ||
| 808 | U8 PortWidth; /* 0x02 */ | ||
| 809 | U8 Primitive; /* 0x03 */ | ||
| 810 | } MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE, | ||
| 811 | MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE, | ||
| 812 | Mpi2EventDataSasBroadcastPrimitive_t, | ||
| 813 | MPI2_POINTER pMpi2EventDataSasBroadcastPrimitive_t; | ||
| 814 | |||
| 815 | /* defines for the Primitive field */ | ||
| 816 | #define MPI2_EVENT_PRIMITIVE_CHANGE (0x01) | ||
| 817 | #define MPI2_EVENT_PRIMITIVE_SES (0x02) | ||
| 818 | #define MPI2_EVENT_PRIMITIVE_EXPANDER (0x03) | ||
| 819 | #define MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT (0x04) | ||
| 820 | #define MPI2_EVENT_PRIMITIVE_RESERVED3 (0x05) | ||
| 821 | #define MPI2_EVENT_PRIMITIVE_RESERVED4 (0x06) | ||
| 822 | #define MPI2_EVENT_PRIMITIVE_CHANGE0_RESERVED (0x07) | ||
| 823 | #define MPI2_EVENT_PRIMITIVE_CHANGE1_RESERVED (0x08) | ||
| 824 | |||
| 825 | /* SAS Notify Primitive Event data */ | ||
| 826 | |||
| 827 | typedef struct _MPI2_EVENT_DATA_SAS_NOTIFY_PRIMITIVE { | ||
| 828 | U8 PhyNum; /* 0x00 */ | ||
| 829 | U8 Port; /* 0x01 */ | ||
| 830 | U8 Reserved1; /* 0x02 */ | ||
| 831 | U8 Primitive; /* 0x03 */ | ||
| 832 | } MPI2_EVENT_DATA_SAS_NOTIFY_PRIMITIVE, | ||
| 833 | MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_NOTIFY_PRIMITIVE, | ||
| 834 | Mpi2EventDataSasNotifyPrimitive_t, | ||
| 835 | MPI2_POINTER pMpi2EventDataSasNotifyPrimitive_t; | ||
| 836 | |||
| 837 | /* defines for the Primitive field */ | ||
| 838 | #define MPI2_EVENT_NOTIFY_ENABLE_SPINUP (0x01) | ||
| 839 | #define MPI2_EVENT_NOTIFY_POWER_LOSS_EXPECTED (0x02) | ||
| 840 | #define MPI2_EVENT_NOTIFY_RESERVED1 (0x03) | ||
| 841 | #define MPI2_EVENT_NOTIFY_RESERVED2 (0x04) | ||
| 842 | |||
| 843 | |||
| 844 | /* SAS Initiator Device Status Change Event data */ | ||
| 845 | |||
| 846 | typedef struct _MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE | ||
| 847 | { | ||
| 848 | U8 ReasonCode; /* 0x00 */ | ||
| 849 | U8 PhysicalPort; /* 0x01 */ | ||
| 850 | U16 DevHandle; /* 0x02 */ | ||
| 851 | U64 SASAddress; /* 0x04 */ | ||
| 852 | } MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE, | ||
| 853 | MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE, | ||
| 854 | Mpi2EventDataSasInitDevStatusChange_t, | ||
| 855 | MPI2_POINTER pMpi2EventDataSasInitDevStatusChange_t; | ||
| 856 | |||
| 857 | /* SAS Initiator Device Status Change event ReasonCode values */ | ||
| 858 | #define MPI2_EVENT_SAS_INIT_RC_ADDED (0x01) | ||
| 859 | #define MPI2_EVENT_SAS_INIT_RC_NOT_RESPONDING (0x02) | ||
| 860 | |||
| 861 | |||
| 862 | /* SAS Initiator Device Table Overflow Event data */ | ||
| 863 | |||
| 864 | typedef struct _MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW | ||
| 865 | { | ||
| 866 | U16 MaxInit; /* 0x00 */ | ||
| 867 | U16 CurrentInit; /* 0x02 */ | ||
| 868 | U64 SASAddress; /* 0x04 */ | ||
| 869 | } MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW, | ||
| 870 | MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW, | ||
| 871 | Mpi2EventDataSasInitTableOverflow_t, | ||
| 872 | MPI2_POINTER pMpi2EventDataSasInitTableOverflow_t; | ||
| 873 | |||
| 874 | |||
| 875 | /* SAS Topology Change List Event data */ | ||
| 876 | |||
| 877 | /* | ||
| 878 | * Host code (drivers, BIOS, utilities, etc.) should leave this define set to | ||
| 879 | * one and check NumEntries at runtime. | ||
| 880 | */ | ||
| 881 | #ifndef MPI2_EVENT_SAS_TOPO_PHY_COUNT | ||
| 882 | #define MPI2_EVENT_SAS_TOPO_PHY_COUNT (1) | ||
| 883 | #endif | ||
| 884 | |||
| 885 | typedef struct _MPI2_EVENT_SAS_TOPO_PHY_ENTRY | ||
| 886 | { | ||
| 887 | U16 AttachedDevHandle; /* 0x00 */ | ||
| 888 | U8 LinkRate; /* 0x02 */ | ||
| 889 | U8 PhyStatus; /* 0x03 */ | ||
| 890 | } MPI2_EVENT_SAS_TOPO_PHY_ENTRY, MPI2_POINTER PTR_MPI2_EVENT_SAS_TOPO_PHY_ENTRY, | ||
| 891 | Mpi2EventSasTopoPhyEntry_t, MPI2_POINTER pMpi2EventSasTopoPhyEntry_t; | ||
| 892 | |||
| 893 | typedef struct _MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST | ||
| 894 | { | ||
| 895 | U16 EnclosureHandle; /* 0x00 */ | ||
| 896 | U16 ExpanderDevHandle; /* 0x02 */ | ||
| 897 | U8 NumPhys; /* 0x04 */ | ||
| 898 | U8 Reserved1; /* 0x05 */ | ||
| 899 | U16 Reserved2; /* 0x06 */ | ||
| 900 | U8 NumEntries; /* 0x08 */ | ||
| 901 | U8 StartPhyNum; /* 0x09 */ | ||
| 902 | U8 ExpStatus; /* 0x0A */ | ||
| 903 | U8 PhysicalPort; /* 0x0B */ | ||
| 904 | MPI2_EVENT_SAS_TOPO_PHY_ENTRY PHY[MPI2_EVENT_SAS_TOPO_PHY_COUNT]; /* 0x0C*/ | ||
| 905 | } MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST, | ||
| 906 | MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST, | ||
| 907 | Mpi2EventDataSasTopologyChangeList_t, | ||
| 908 | MPI2_POINTER pMpi2EventDataSasTopologyChangeList_t; | ||
| 909 | |||
| 910 | /* values for the ExpStatus field */ | ||
| 911 | #define MPI2_EVENT_SAS_TOPO_ES_NO_EXPANDER (0x00) | ||
| 912 | #define MPI2_EVENT_SAS_TOPO_ES_ADDED (0x01) | ||
| 913 | #define MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING (0x02) | ||
| 914 | #define MPI2_EVENT_SAS_TOPO_ES_RESPONDING (0x03) | ||
| 915 | #define MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING (0x04) | ||
| 916 | |||
| 917 | /* defines for the LinkRate field */ | ||
| 918 | #define MPI2_EVENT_SAS_TOPO_LR_CURRENT_MASK (0xF0) | ||
| 919 | #define MPI2_EVENT_SAS_TOPO_LR_CURRENT_SHIFT (4) | ||
| 920 | #define MPI2_EVENT_SAS_TOPO_LR_PREV_MASK (0x0F) | ||
| 921 | #define MPI2_EVENT_SAS_TOPO_LR_PREV_SHIFT (0) | ||
| 922 | |||
| 923 | #define MPI2_EVENT_SAS_TOPO_LR_UNKNOWN_LINK_RATE (0x00) | ||
| 924 | #define MPI2_EVENT_SAS_TOPO_LR_PHY_DISABLED (0x01) | ||
| 925 | #define MPI2_EVENT_SAS_TOPO_LR_NEGOTIATION_FAILED (0x02) | ||
| 926 | #define MPI2_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE (0x03) | ||
| 927 | #define MPI2_EVENT_SAS_TOPO_LR_PORT_SELECTOR (0x04) | ||
| 928 | #define MPI2_EVENT_SAS_TOPO_LR_SMP_RESET_IN_PROGRESS (0x05) | ||
| 929 | #define MPI2_EVENT_SAS_TOPO_LR_UNSUPPORTED_PHY (0x06) | ||
| 930 | #define MPI2_EVENT_SAS_TOPO_LR_RATE_1_5 (0x08) | ||
| 931 | #define MPI2_EVENT_SAS_TOPO_LR_RATE_3_0 (0x09) | ||
| 932 | #define MPI2_EVENT_SAS_TOPO_LR_RATE_6_0 (0x0A) | ||
| 933 | |||
| 934 | /* values for the PhyStatus field */ | ||
| 935 | #define MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT (0x80) | ||
| 936 | #define MPI2_EVENT_SAS_TOPO_PS_MULTIPLEX_CHANGE (0x10) | ||
| 937 | /* values for the PhyStatus ReasonCode sub-field */ | ||
| 938 | #define MPI2_EVENT_SAS_TOPO_RC_MASK (0x0F) | ||
| 939 | #define MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED (0x01) | ||
| 940 | #define MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING (0x02) | ||
| 941 | #define MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED (0x03) | ||
| 942 | #define MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE (0x04) | ||
| 943 | #define MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING (0x05) | ||
| 944 | |||
| 945 | |||
| 946 | /* SAS Enclosure Device Status Change Event data */ | ||
| 947 | |||
| 948 | typedef struct _MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE | ||
| 949 | { | ||
| 950 | U16 EnclosureHandle; /* 0x00 */ | ||
| 951 | U8 ReasonCode; /* 0x02 */ | ||
| 952 | U8 PhysicalPort; /* 0x03 */ | ||
| 953 | U64 EnclosureLogicalID; /* 0x04 */ | ||
| 954 | U16 NumSlots; /* 0x0C */ | ||
| 955 | U16 StartSlot; /* 0x0E */ | ||
| 956 | U32 PhyBits; /* 0x10 */ | ||
| 957 | } MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE, | ||
| 958 | MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE, | ||
| 959 | Mpi2EventDataSasEnclDevStatusChange_t, | ||
| 960 | MPI2_POINTER pMpi2EventDataSasEnclDevStatusChange_t; | ||
| 961 | |||
| 962 | /* SAS Enclosure Device Status Change event ReasonCode values */ | ||
| 963 | #define MPI2_EVENT_SAS_ENCL_RC_ADDED (0x01) | ||
| 964 | #define MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING (0x02) | ||
| 965 | |||
| 966 | |||
| 967 | /* SAS PHY Counter Event data */ | ||
| 968 | |||
| 969 | typedef struct _MPI2_EVENT_DATA_SAS_PHY_COUNTER { | ||
| 970 | U64 TimeStamp; /* 0x00 */ | ||
| 971 | U32 Reserved1; /* 0x08 */ | ||
| 972 | U8 PhyEventCode; /* 0x0C */ | ||
| 973 | U8 PhyNum; /* 0x0D */ | ||
| 974 | U16 Reserved2; /* 0x0E */ | ||
| 975 | U32 PhyEventInfo; /* 0x10 */ | ||
| 976 | U8 CounterType; /* 0x14 */ | ||
| 977 | U8 ThresholdWindow; /* 0x15 */ | ||
| 978 | U8 TimeUnits; /* 0x16 */ | ||
| 979 | U8 Reserved3; /* 0x17 */ | ||
| 980 | U32 EventThreshold; /* 0x18 */ | ||
| 981 | U16 ThresholdFlags; /* 0x1C */ | ||
| 982 | U16 Reserved4; /* 0x1E */ | ||
| 983 | } MPI2_EVENT_DATA_SAS_PHY_COUNTER, | ||
| 984 | MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_PHY_COUNTER, | ||
| 985 | Mpi2EventDataSasPhyCounter_t, MPI2_POINTER pMpi2EventDataSasPhyCounter_t; | ||
| 986 | |||
| 987 | /* use MPI2_SASPHY3_EVENT_CODE_ values from mpi2_cnfg.h for the | ||
| 988 | * PhyEventCode field | ||
| 989 | * use MPI2_SASPHY3_COUNTER_TYPE_ values from mpi2_cnfg.h for the | ||
| 990 | * CounterType field | ||
| 991 | * use MPI2_SASPHY3_TIME_UNITS_ values from mpi2_cnfg.h for the | ||
| 992 | * TimeUnits field | ||
| 993 | * use MPI2_SASPHY3_TFLAGS_ values from mpi2_cnfg.h for the | ||
| 994 | * ThresholdFlags field | ||
| 995 | * */ | ||
| 996 | |||
| 997 | |||
| 998 | /* SAS Quiesce Event data */ | ||
| 999 | |||
| 1000 | typedef struct _MPI2_EVENT_DATA_SAS_QUIESCE { | ||
| 1001 | U8 ReasonCode; /* 0x00 */ | ||
| 1002 | U8 Reserved1; /* 0x01 */ | ||
| 1003 | U16 Reserved2; /* 0x02 */ | ||
| 1004 | U32 Reserved3; /* 0x04 */ | ||
| 1005 | } MPI2_EVENT_DATA_SAS_QUIESCE, | ||
| 1006 | MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_QUIESCE, | ||
| 1007 | Mpi2EventDataSasQuiesce_t, MPI2_POINTER pMpi2EventDataSasQuiesce_t; | ||
| 1008 | |||
| 1009 | /* SAS Quiesce Event data ReasonCode values */ | ||
| 1010 | #define MPI2_EVENT_SAS_QUIESCE_RC_STARTED (0x01) | ||
| 1011 | #define MPI2_EVENT_SAS_QUIESCE_RC_COMPLETED (0x02) | ||
| 1012 | |||
| 1013 | |||
| 1014 | /* Host Based Discovery Phy Event data */ | ||
| 1015 | |||
| 1016 | typedef struct _MPI2_EVENT_HBD_PHY_SAS { | ||
| 1017 | U8 Flags; /* 0x00 */ | ||
| 1018 | U8 NegotiatedLinkRate; /* 0x01 */ | ||
| 1019 | U8 PhyNum; /* 0x02 */ | ||
| 1020 | U8 PhysicalPort; /* 0x03 */ | ||
| 1021 | U32 Reserved1; /* 0x04 */ | ||
| 1022 | U8 InitialFrame[28]; /* 0x08 */ | ||
| 1023 | } MPI2_EVENT_HBD_PHY_SAS, MPI2_POINTER PTR_MPI2_EVENT_HBD_PHY_SAS, | ||
| 1024 | Mpi2EventHbdPhySas_t, MPI2_POINTER pMpi2EventHbdPhySas_t; | ||
| 1025 | |||
| 1026 | /* values for the Flags field */ | ||
| 1027 | #define MPI2_EVENT_HBD_SAS_FLAGS_FRAME_VALID (0x02) | ||
| 1028 | #define MPI2_EVENT_HBD_SAS_FLAGS_SATA_FRAME (0x01) | ||
| 1029 | |||
| 1030 | /* use MPI2_SAS_NEG_LINK_RATE_ defines from mpi2_cnfg.h for | ||
| 1031 | * the NegotiatedLinkRate field */ | ||
| 1032 | |||
| 1033 | typedef union _MPI2_EVENT_HBD_DESCRIPTOR { | ||
| 1034 | MPI2_EVENT_HBD_PHY_SAS Sas; | ||
| 1035 | } MPI2_EVENT_HBD_DESCRIPTOR, MPI2_POINTER PTR_MPI2_EVENT_HBD_DESCRIPTOR, | ||
| 1036 | Mpi2EventHbdDescriptor_t, MPI2_POINTER pMpi2EventHbdDescriptor_t; | ||
| 1037 | |||
| 1038 | typedef struct _MPI2_EVENT_DATA_HBD_PHY { | ||
| 1039 | U8 DescriptorType; /* 0x00 */ | ||
| 1040 | U8 Reserved1; /* 0x01 */ | ||
| 1041 | U16 Reserved2; /* 0x02 */ | ||
| 1042 | U32 Reserved3; /* 0x04 */ | ||
| 1043 | MPI2_EVENT_HBD_DESCRIPTOR Descriptor; /* 0x08 */ | ||
| 1044 | } MPI2_EVENT_DATA_HBD_PHY, MPI2_POINTER PTR_MPI2_EVENT_DATA_HBD_PHY, | ||
| 1045 | Mpi2EventDataHbdPhy_t, MPI2_POINTER pMpi2EventDataMpi2EventDataHbdPhy_t; | ||
| 1046 | |||
| 1047 | /* values for the DescriptorType field */ | ||
| 1048 | #define MPI2_EVENT_HBD_DT_SAS (0x01) | ||
| 1049 | |||
| 1050 | |||
| 1051 | |||
| 1052 | /**************************************************************************** | ||
| 1053 | * EventAck message | ||
| 1054 | ****************************************************************************/ | ||
| 1055 | |||
| 1056 | /* EventAck Request message */ | ||
| 1057 | typedef struct _MPI2_EVENT_ACK_REQUEST | ||
| 1058 | { | ||
| 1059 | U16 Reserved1; /* 0x00 */ | ||
| 1060 | U8 ChainOffset; /* 0x02 */ | ||
| 1061 | U8 Function; /* 0x03 */ | ||
| 1062 | U16 Reserved2; /* 0x04 */ | ||
| 1063 | U8 Reserved3; /* 0x06 */ | ||
| 1064 | U8 MsgFlags; /* 0x07 */ | ||
| 1065 | U8 VP_ID; /* 0x08 */ | ||
| 1066 | U8 VF_ID; /* 0x09 */ | ||
| 1067 | U16 Reserved4; /* 0x0A */ | ||
| 1068 | U16 Event; /* 0x0C */ | ||
| 1069 | U16 Reserved5; /* 0x0E */ | ||
| 1070 | U32 EventContext; /* 0x10 */ | ||
| 1071 | } MPI2_EVENT_ACK_REQUEST, MPI2_POINTER PTR_MPI2_EVENT_ACK_REQUEST, | ||
| 1072 | Mpi2EventAckRequest_t, MPI2_POINTER pMpi2EventAckRequest_t; | ||
| 1073 | |||
| 1074 | |||
| 1075 | /* EventAck Reply message */ | ||
| 1076 | typedef struct _MPI2_EVENT_ACK_REPLY | ||
| 1077 | { | ||
| 1078 | U16 Reserved1; /* 0x00 */ | ||
| 1079 | U8 MsgLength; /* 0x02 */ | ||
| 1080 | U8 Function; /* 0x03 */ | ||
| 1081 | U16 Reserved2; /* 0x04 */ | ||
| 1082 | U8 Reserved3; /* 0x06 */ | ||
| 1083 | U8 MsgFlags; /* 0x07 */ | ||
| 1084 | U8 VP_ID; /* 0x08 */ | ||
| 1085 | U8 VF_ID; /* 0x09 */ | ||
| 1086 | U16 Reserved4; /* 0x0A */ | ||
| 1087 | U16 Reserved5; /* 0x0C */ | ||
| 1088 | U16 IOCStatus; /* 0x0E */ | ||
| 1089 | U32 IOCLogInfo; /* 0x10 */ | ||
| 1090 | } MPI2_EVENT_ACK_REPLY, MPI2_POINTER PTR_MPI2_EVENT_ACK_REPLY, | ||
| 1091 | Mpi2EventAckReply_t, MPI2_POINTER pMpi2EventAckReply_t; | ||
| 1092 | |||
| 1093 | |||
| 1094 | /**************************************************************************** | ||
| 1095 | * SendHostMessage message | ||
| 1096 | ****************************************************************************/ | ||
| 1097 | |||
| 1098 | /* SendHostMessage Request message */ | ||
| 1099 | typedef struct _MPI2_SEND_HOST_MESSAGE_REQUEST { | ||
| 1100 | U16 HostDataLength; /* 0x00 */ | ||
| 1101 | U8 ChainOffset; /* 0x02 */ | ||
| 1102 | U8 Function; /* 0x03 */ | ||
| 1103 | U16 Reserved1; /* 0x04 */ | ||
| 1104 | U8 Reserved2; /* 0x06 */ | ||
| 1105 | U8 MsgFlags; /* 0x07 */ | ||
| 1106 | U8 VP_ID; /* 0x08 */ | ||
| 1107 | U8 VF_ID; /* 0x09 */ | ||
| 1108 | U16 Reserved3; /* 0x0A */ | ||
| 1109 | U8 Reserved4; /* 0x0C */ | ||
| 1110 | U8 DestVF_ID; /* 0x0D */ | ||
| 1111 | U16 Reserved5; /* 0x0E */ | ||
| 1112 | U32 Reserved6; /* 0x10 */ | ||
| 1113 | U32 Reserved7; /* 0x14 */ | ||
| 1114 | U32 Reserved8; /* 0x18 */ | ||
| 1115 | U32 Reserved9; /* 0x1C */ | ||
| 1116 | U32 Reserved10; /* 0x20 */ | ||
| 1117 | U32 HostData[1]; /* 0x24 */ | ||
| 1118 | } MPI2_SEND_HOST_MESSAGE_REQUEST, | ||
| 1119 | MPI2_POINTER PTR_MPI2_SEND_HOST_MESSAGE_REQUEST, | ||
| 1120 | Mpi2SendHostMessageRequest_t, MPI2_POINTER pMpi2SendHostMessageRequest_t; | ||
| 1121 | |||
| 1122 | |||
| 1123 | /* SendHostMessage Reply message */ | ||
| 1124 | typedef struct _MPI2_SEND_HOST_MESSAGE_REPLY { | ||
| 1125 | U16 HostDataLength; /* 0x00 */ | ||
| 1126 | U8 MsgLength; /* 0x02 */ | ||
| 1127 | U8 Function; /* 0x03 */ | ||
| 1128 | U16 Reserved1; /* 0x04 */ | ||
| 1129 | U8 Reserved2; /* 0x06 */ | ||
| 1130 | U8 MsgFlags; /* 0x07 */ | ||
| 1131 | U8 VP_ID; /* 0x08 */ | ||
| 1132 | U8 VF_ID; /* 0x09 */ | ||
| 1133 | U16 Reserved3; /* 0x0A */ | ||
| 1134 | U16 Reserved4; /* 0x0C */ | ||
| 1135 | U16 IOCStatus; /* 0x0E */ | ||
| 1136 | U32 IOCLogInfo; /* 0x10 */ | ||
| 1137 | } MPI2_SEND_HOST_MESSAGE_REPLY, MPI2_POINTER PTR_MPI2_SEND_HOST_MESSAGE_REPLY, | ||
| 1138 | Mpi2SendHostMessageReply_t, MPI2_POINTER pMpi2SendHostMessageReply_t; | ||
| 1139 | |||
| 1140 | |||
| 1141 | /**************************************************************************** | ||
| 1142 | * FWDownload message | ||
| 1143 | ****************************************************************************/ | ||
| 1144 | |||
| 1145 | /* FWDownload Request message */ | ||
| 1146 | typedef struct _MPI2_FW_DOWNLOAD_REQUEST | ||
| 1147 | { | ||
| 1148 | U8 ImageType; /* 0x00 */ | ||
| 1149 | U8 Reserved1; /* 0x01 */ | ||
| 1150 | U8 ChainOffset; /* 0x02 */ | ||
| 1151 | U8 Function; /* 0x03 */ | ||
| 1152 | U16 Reserved2; /* 0x04 */ | ||
| 1153 | U8 Reserved3; /* 0x06 */ | ||
| 1154 | U8 MsgFlags; /* 0x07 */ | ||
| 1155 | U8 VP_ID; /* 0x08 */ | ||
| 1156 | U8 VF_ID; /* 0x09 */ | ||
| 1157 | U16 Reserved4; /* 0x0A */ | ||
| 1158 | U32 TotalImageSize; /* 0x0C */ | ||
| 1159 | U32 Reserved5; /* 0x10 */ | ||
| 1160 | MPI2_MPI_SGE_UNION SGL; /* 0x14 */ | ||
| 1161 | } MPI2_FW_DOWNLOAD_REQUEST, MPI2_POINTER PTR_MPI2_FW_DOWNLOAD_REQUEST, | ||
| 1162 | Mpi2FWDownloadRequest, MPI2_POINTER pMpi2FWDownloadRequest; | ||
| 1163 | |||
| 1164 | #define MPI2_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT (0x01) | ||
| 1165 | |||
| 1166 | #define MPI2_FW_DOWNLOAD_ITYPE_FW (0x01) | ||
| 1167 | #define MPI2_FW_DOWNLOAD_ITYPE_BIOS (0x02) | ||
| 1168 | #define MPI2_FW_DOWNLOAD_ITYPE_MANUFACTURING (0x06) | ||
| 1169 | #define MPI2_FW_DOWNLOAD_ITYPE_CONFIG_1 (0x07) | ||
| 1170 | #define MPI2_FW_DOWNLOAD_ITYPE_CONFIG_2 (0x08) | ||
| 1171 | #define MPI2_FW_DOWNLOAD_ITYPE_MEGARAID (0x09) | ||
| 1172 | #define MPI2_FW_DOWNLOAD_ITYPE_COMPLETE (0x0A) | ||
| 1173 | #define MPI2_FW_DOWNLOAD_ITYPE_COMMON_BOOT_BLOCK (0x0B) | ||
| 1174 | #define MPI2_FW_DOWNLOAD_ITYPE_PUBLIC_KEY (0x0C) | ||
| 1175 | #define MPI2_FW_DOWNLOAD_ITYPE_MIN_PRODUCT_SPECIFIC (0xF0) | ||
| 1176 | |||
| 1177 | /* FWDownload TransactionContext Element */ | ||
| 1178 | typedef struct _MPI2_FW_DOWNLOAD_TCSGE | ||
| 1179 | { | ||
| 1180 | U8 Reserved1; /* 0x00 */ | ||
| 1181 | U8 ContextSize; /* 0x01 */ | ||
| 1182 | U8 DetailsLength; /* 0x02 */ | ||
| 1183 | U8 Flags; /* 0x03 */ | ||
| 1184 | U32 Reserved2; /* 0x04 */ | ||
| 1185 | U32 ImageOffset; /* 0x08 */ | ||
| 1186 | U32 ImageSize; /* 0x0C */ | ||
| 1187 | } MPI2_FW_DOWNLOAD_TCSGE, MPI2_POINTER PTR_MPI2_FW_DOWNLOAD_TCSGE, | ||
| 1188 | Mpi2FWDownloadTCSGE_t, MPI2_POINTER pMpi2FWDownloadTCSGE_t; | ||
| 1189 | |||
| 1190 | /* FWDownload Reply message */ | ||
| 1191 | typedef struct _MPI2_FW_DOWNLOAD_REPLY | ||
| 1192 | { | ||
| 1193 | U8 ImageType; /* 0x00 */ | ||
| 1194 | U8 Reserved1; /* 0x01 */ | ||
| 1195 | U8 MsgLength; /* 0x02 */ | ||
| 1196 | U8 Function; /* 0x03 */ | ||
| 1197 | U16 Reserved2; /* 0x04 */ | ||
| 1198 | U8 Reserved3; /* 0x06 */ | ||
| 1199 | U8 MsgFlags; /* 0x07 */ | ||
| 1200 | U8 VP_ID; /* 0x08 */ | ||
| 1201 | U8 VF_ID; /* 0x09 */ | ||
| 1202 | U16 Reserved4; /* 0x0A */ | ||
| 1203 | U16 Reserved5; /* 0x0C */ | ||
| 1204 | U16 IOCStatus; /* 0x0E */ | ||
| 1205 | U32 IOCLogInfo; /* 0x10 */ | ||
| 1206 | } MPI2_FW_DOWNLOAD_REPLY, MPI2_POINTER PTR_MPI2_FW_DOWNLOAD_REPLY, | ||
| 1207 | Mpi2FWDownloadReply_t, MPI2_POINTER pMpi2FWDownloadReply_t; | ||
| 1208 | |||
| 1209 | |||
| 1210 | /**************************************************************************** | ||
| 1211 | * FWUpload message | ||
| 1212 | ****************************************************************************/ | ||
| 1213 | |||
| 1214 | /* FWUpload Request message */ | ||
| 1215 | typedef struct _MPI2_FW_UPLOAD_REQUEST | ||
| 1216 | { | ||
| 1217 | U8 ImageType; /* 0x00 */ | ||
| 1218 | U8 Reserved1; /* 0x01 */ | ||
| 1219 | U8 ChainOffset; /* 0x02 */ | ||
| 1220 | U8 Function; /* 0x03 */ | ||
| 1221 | U16 Reserved2; /* 0x04 */ | ||
| 1222 | U8 Reserved3; /* 0x06 */ | ||
| 1223 | U8 MsgFlags; /* 0x07 */ | ||
| 1224 | U8 VP_ID; /* 0x08 */ | ||
| 1225 | U8 VF_ID; /* 0x09 */ | ||
| 1226 | U16 Reserved4; /* 0x0A */ | ||
| 1227 | U32 Reserved5; /* 0x0C */ | ||
| 1228 | U32 Reserved6; /* 0x10 */ | ||
| 1229 | MPI2_MPI_SGE_UNION SGL; /* 0x14 */ | ||
| 1230 | } MPI2_FW_UPLOAD_REQUEST, MPI2_POINTER PTR_MPI2_FW_UPLOAD_REQUEST, | ||
| 1231 | Mpi2FWUploadRequest_t, MPI2_POINTER pMpi2FWUploadRequest_t; | ||
| 1232 | |||
| 1233 | #define MPI2_FW_UPLOAD_ITYPE_FW_CURRENT (0x00) | ||
| 1234 | #define MPI2_FW_UPLOAD_ITYPE_FW_FLASH (0x01) | ||
| 1235 | #define MPI2_FW_UPLOAD_ITYPE_BIOS_FLASH (0x02) | ||
| 1236 | #define MPI2_FW_UPLOAD_ITYPE_FW_BACKUP (0x05) | ||
| 1237 | #define MPI2_FW_UPLOAD_ITYPE_MANUFACTURING (0x06) | ||
| 1238 | #define MPI2_FW_UPLOAD_ITYPE_CONFIG_1 (0x07) | ||
| 1239 | #define MPI2_FW_UPLOAD_ITYPE_CONFIG_2 (0x08) | ||
| 1240 | #define MPI2_FW_UPLOAD_ITYPE_MEGARAID (0x09) | ||
| 1241 | #define MPI2_FW_UPLOAD_ITYPE_COMPLETE (0x0A) | ||
| 1242 | #define MPI2_FW_UPLOAD_ITYPE_COMMON_BOOT_BLOCK (0x0B) | ||
| 1243 | |||
| 1244 | typedef struct _MPI2_FW_UPLOAD_TCSGE | ||
| 1245 | { | ||
| 1246 | U8 Reserved1; /* 0x00 */ | ||
| 1247 | U8 ContextSize; /* 0x01 */ | ||
| 1248 | U8 DetailsLength; /* 0x02 */ | ||
| 1249 | U8 Flags; /* 0x03 */ | ||
| 1250 | U32 Reserved2; /* 0x04 */ | ||
| 1251 | U32 ImageOffset; /* 0x08 */ | ||
| 1252 | U32 ImageSize; /* 0x0C */ | ||
| 1253 | } MPI2_FW_UPLOAD_TCSGE, MPI2_POINTER PTR_MPI2_FW_UPLOAD_TCSGE, | ||
| 1254 | Mpi2FWUploadTCSGE_t, MPI2_POINTER pMpi2FWUploadTCSGE_t; | ||
| 1255 | |||
| 1256 | /* FWUpload Reply message */ | ||
| 1257 | typedef struct _MPI2_FW_UPLOAD_REPLY | ||
| 1258 | { | ||
| 1259 | U8 ImageType; /* 0x00 */ | ||
| 1260 | U8 Reserved1; /* 0x01 */ | ||
| 1261 | U8 MsgLength; /* 0x02 */ | ||
| 1262 | U8 Function; /* 0x03 */ | ||
| 1263 | U16 Reserved2; /* 0x04 */ | ||
| 1264 | U8 Reserved3; /* 0x06 */ | ||
| 1265 | U8 MsgFlags; /* 0x07 */ | ||
| 1266 | U8 VP_ID; /* 0x08 */ | ||
| 1267 | U8 VF_ID; /* 0x09 */ | ||
| 1268 | U16 Reserved4; /* 0x0A */ | ||
| 1269 | U16 Reserved5; /* 0x0C */ | ||
| 1270 | U16 IOCStatus; /* 0x0E */ | ||
| 1271 | U32 IOCLogInfo; /* 0x10 */ | ||
| 1272 | U32 ActualImageSize; /* 0x14 */ | ||
| 1273 | } MPI2_FW_UPLOAD_REPLY, MPI2_POINTER PTR_MPI2_FW_UPLOAD_REPLY, | ||
| 1274 | Mpi2FWUploadReply_t, MPI2_POINTER pMPi2FWUploadReply_t; | ||
| 1275 | |||
| 1276 | |||
| 1277 | /* FW Image Header */ | ||
| 1278 | typedef struct _MPI2_FW_IMAGE_HEADER | ||
| 1279 | { | ||
| 1280 | U32 Signature; /* 0x00 */ | ||
| 1281 | U32 Signature0; /* 0x04 */ | ||
| 1282 | U32 Signature1; /* 0x08 */ | ||
| 1283 | U32 Signature2; /* 0x0C */ | ||
| 1284 | MPI2_VERSION_UNION MPIVersion; /* 0x10 */ | ||
| 1285 | MPI2_VERSION_UNION FWVersion; /* 0x14 */ | ||
| 1286 | MPI2_VERSION_UNION NVDATAVersion; /* 0x18 */ | ||
| 1287 | MPI2_VERSION_UNION PackageVersion; /* 0x1C */ | ||
| 1288 | U16 VendorID; /* 0x20 */ | ||
| 1289 | U16 ProductID; /* 0x22 */ | ||
| 1290 | U16 ProtocolFlags; /* 0x24 */ | ||
| 1291 | U16 Reserved26; /* 0x26 */ | ||
| 1292 | U32 IOCCapabilities; /* 0x28 */ | ||
| 1293 | U32 ImageSize; /* 0x2C */ | ||
| 1294 | U32 NextImageHeaderOffset; /* 0x30 */ | ||
| 1295 | U32 Checksum; /* 0x34 */ | ||
| 1296 | U32 Reserved38; /* 0x38 */ | ||
| 1297 | U32 Reserved3C; /* 0x3C */ | ||
| 1298 | U32 Reserved40; /* 0x40 */ | ||
| 1299 | U32 Reserved44; /* 0x44 */ | ||
| 1300 | U32 Reserved48; /* 0x48 */ | ||
| 1301 | U32 Reserved4C; /* 0x4C */ | ||
| 1302 | U32 Reserved50; /* 0x50 */ | ||
| 1303 | U32 Reserved54; /* 0x54 */ | ||
| 1304 | U32 Reserved58; /* 0x58 */ | ||
| 1305 | U32 Reserved5C; /* 0x5C */ | ||
| 1306 | U32 Reserved60; /* 0x60 */ | ||
| 1307 | U32 FirmwareVersionNameWhat; /* 0x64 */ | ||
| 1308 | U8 FirmwareVersionName[32]; /* 0x68 */ | ||
| 1309 | U32 VendorNameWhat; /* 0x88 */ | ||
| 1310 | U8 VendorName[32]; /* 0x8C */ | ||
| 1311 | U32 PackageNameWhat; /* 0x88 */ | ||
| 1312 | U8 PackageName[32]; /* 0x8C */ | ||
| 1313 | U32 ReservedD0; /* 0xD0 */ | ||
| 1314 | U32 ReservedD4; /* 0xD4 */ | ||
| 1315 | U32 ReservedD8; /* 0xD8 */ | ||
| 1316 | U32 ReservedDC; /* 0xDC */ | ||
| 1317 | U32 ReservedE0; /* 0xE0 */ | ||
| 1318 | U32 ReservedE4; /* 0xE4 */ | ||
| 1319 | U32 ReservedE8; /* 0xE8 */ | ||
| 1320 | U32 ReservedEC; /* 0xEC */ | ||
| 1321 | U32 ReservedF0; /* 0xF0 */ | ||
| 1322 | U32 ReservedF4; /* 0xF4 */ | ||
| 1323 | U32 ReservedF8; /* 0xF8 */ | ||
| 1324 | U32 ReservedFC; /* 0xFC */ | ||
| 1325 | } MPI2_FW_IMAGE_HEADER, MPI2_POINTER PTR_MPI2_FW_IMAGE_HEADER, | ||
| 1326 | Mpi2FWImageHeader_t, MPI2_POINTER pMpi2FWImageHeader_t; | ||
| 1327 | |||
| 1328 | /* Signature field */ | ||
| 1329 | #define MPI2_FW_HEADER_SIGNATURE_OFFSET (0x00) | ||
| 1330 | #define MPI2_FW_HEADER_SIGNATURE_MASK (0xFF000000) | ||
| 1331 | #define MPI2_FW_HEADER_SIGNATURE (0xEA000000) | ||
| 1332 | |||
| 1333 | /* Signature0 field */ | ||
| 1334 | #define MPI2_FW_HEADER_SIGNATURE0_OFFSET (0x04) | ||
| 1335 | #define MPI2_FW_HEADER_SIGNATURE0 (0x5AFAA55A) | ||
| 1336 | |||
| 1337 | /* Signature1 field */ | ||
| 1338 | #define MPI2_FW_HEADER_SIGNATURE1_OFFSET (0x08) | ||
| 1339 | #define MPI2_FW_HEADER_SIGNATURE1 (0xA55AFAA5) | ||
| 1340 | |||
| 1341 | /* Signature2 field */ | ||
| 1342 | #define MPI2_FW_HEADER_SIGNATURE2_OFFSET (0x0C) | ||
| 1343 | #define MPI2_FW_HEADER_SIGNATURE2 (0x5AA55AFA) | ||
| 1344 | |||
| 1345 | |||
| 1346 | /* defines for using the ProductID field */ | ||
| 1347 | #define MPI2_FW_HEADER_PID_TYPE_MASK (0xF000) | ||
| 1348 | #define MPI2_FW_HEADER_PID_TYPE_SAS (0x2000) | ||
| 1349 | |||
| 1350 | #define MPI2_FW_HEADER_PID_PROD_MASK (0x0F00) | ||
| 1351 | #define MPI2_FW_HEADER_PID_PROD_A (0x0000) | ||
| 1352 | #define MPI2_FW_HEADER_PID_PROD_TARGET_INITIATOR_SCSI (0x0200) | ||
| 1353 | #define MPI2_FW_HEADER_PID_PROD_IR_SCSI (0x0700) | ||
| 1354 | |||
| 1355 | |||
| 1356 | #define MPI2_FW_HEADER_PID_FAMILY_MASK (0x00FF) | ||
| 1357 | /* SAS */ | ||
| 1358 | #define MPI2_FW_HEADER_PID_FAMILY_2108_SAS (0x0013) | ||
| 1359 | #define MPI2_FW_HEADER_PID_FAMILY_2208_SAS (0x0014) | ||
| 1360 | |||
| 1361 | /* use MPI2_IOCFACTS_PROTOCOL_ defines for ProtocolFlags field */ | ||
| 1362 | |||
| 1363 | /* use MPI2_IOCFACTS_CAPABILITY_ defines for IOCCapabilities field */ | ||
| 1364 | |||
| 1365 | |||
| 1366 | #define MPI2_FW_HEADER_IMAGESIZE_OFFSET (0x2C) | ||
| 1367 | #define MPI2_FW_HEADER_NEXTIMAGE_OFFSET (0x30) | ||
| 1368 | #define MPI2_FW_HEADER_VERNMHWAT_OFFSET (0x64) | ||
| 1369 | |||
| 1370 | #define MPI2_FW_HEADER_WHAT_SIGNATURE (0x29232840) | ||
| 1371 | |||
| 1372 | #define MPI2_FW_HEADER_SIZE (0x100) | ||
| 1373 | |||
| 1374 | |||
| 1375 | /* Extended Image Header */ | ||
| 1376 | typedef struct _MPI2_EXT_IMAGE_HEADER | ||
| 1377 | |||
| 1378 | { | ||
| 1379 | U8 ImageType; /* 0x00 */ | ||
| 1380 | U8 Reserved1; /* 0x01 */ | ||
| 1381 | U16 Reserved2; /* 0x02 */ | ||
| 1382 | U32 Checksum; /* 0x04 */ | ||
| 1383 | U32 ImageSize; /* 0x08 */ | ||
| 1384 | U32 NextImageHeaderOffset; /* 0x0C */ | ||
| 1385 | U32 PackageVersion; /* 0x10 */ | ||
| 1386 | U32 Reserved3; /* 0x14 */ | ||
| 1387 | U32 Reserved4; /* 0x18 */ | ||
| 1388 | U32 Reserved5; /* 0x1C */ | ||
| 1389 | U8 IdentifyString[32]; /* 0x20 */ | ||
| 1390 | } MPI2_EXT_IMAGE_HEADER, MPI2_POINTER PTR_MPI2_EXT_IMAGE_HEADER, | ||
| 1391 | Mpi2ExtImageHeader_t, MPI2_POINTER pMpi2ExtImageHeader_t; | ||
| 1392 | |||
| 1393 | /* useful offsets */ | ||
| 1394 | #define MPI2_EXT_IMAGE_IMAGETYPE_OFFSET (0x00) | ||
| 1395 | #define MPI2_EXT_IMAGE_IMAGESIZE_OFFSET (0x08) | ||
| 1396 | #define MPI2_EXT_IMAGE_NEXTIMAGE_OFFSET (0x0C) | ||
| 1397 | |||
| 1398 | #define MPI2_EXT_IMAGE_HEADER_SIZE (0x40) | ||
| 1399 | |||
| 1400 | /* defines for the ImageType field */ | ||
| 1401 | #define MPI2_EXT_IMAGE_TYPE_UNSPECIFIED (0x00) | ||
| 1402 | #define MPI2_EXT_IMAGE_TYPE_FW (0x01) | ||
| 1403 | #define MPI2_EXT_IMAGE_TYPE_NVDATA (0x03) | ||
| 1404 | #define MPI2_EXT_IMAGE_TYPE_BOOTLOADER (0x04) | ||
| 1405 | #define MPI2_EXT_IMAGE_TYPE_INITIALIZATION (0x05) | ||
| 1406 | #define MPI2_EXT_IMAGE_TYPE_FLASH_LAYOUT (0x06) | ||
| 1407 | #define MPI2_EXT_IMAGE_TYPE_SUPPORTED_DEVICES (0x07) | ||
| 1408 | #define MPI2_EXT_IMAGE_TYPE_MEGARAID (0x08) | ||
| 1409 | #define MPI2_EXT_IMAGE_TYPE_ENCRYPTED_HASH (0x09) | ||
| 1410 | #define MPI2_EXT_IMAGE_TYPE_MIN_PRODUCT_SPECIFIC (0x80) | ||
| 1411 | #define MPI2_EXT_IMAGE_TYPE_MAX_PRODUCT_SPECIFIC (0xFF) | ||
| 1412 | #define MPI2_EXT_IMAGE_TYPE_MAX \ | ||
| 1413 | (MPI2_EXT_IMAGE_TYPE_MAX_PRODUCT_SPECIFIC) /* deprecated */ | ||
| 1414 | |||
| 1415 | |||
| 1416 | |||
| 1417 | /* FLASH Layout Extended Image Data */ | ||
| 1418 | |||
| 1419 | /* | ||
| 1420 | * Host code (drivers, BIOS, utilities, etc.) should leave this define set to | ||
| 1421 | * one and check RegionsPerLayout at runtime. | ||
| 1422 | */ | ||
| 1423 | #ifndef MPI2_FLASH_NUMBER_OF_REGIONS | ||
| 1424 | #define MPI2_FLASH_NUMBER_OF_REGIONS (1) | ||
| 1425 | #endif | ||
| 1426 | |||
| 1427 | /* | ||
| 1428 | * Host code (drivers, BIOS, utilities, etc.) should leave this define set to | ||
| 1429 | * one and check NumberOfLayouts at runtime. | ||
| 1430 | */ | ||
| 1431 | #ifndef MPI2_FLASH_NUMBER_OF_LAYOUTS | ||
| 1432 | #define MPI2_FLASH_NUMBER_OF_LAYOUTS (1) | ||
| 1433 | #endif | ||
| 1434 | |||
| 1435 | typedef struct _MPI2_FLASH_REGION | ||
| 1436 | { | ||
| 1437 | U8 RegionType; /* 0x00 */ | ||
| 1438 | U8 Reserved1; /* 0x01 */ | ||
| 1439 | U16 Reserved2; /* 0x02 */ | ||
| 1440 | U32 RegionOffset; /* 0x04 */ | ||
| 1441 | U32 RegionSize; /* 0x08 */ | ||
| 1442 | U32 Reserved3; /* 0x0C */ | ||
| 1443 | } MPI2_FLASH_REGION, MPI2_POINTER PTR_MPI2_FLASH_REGION, | ||
| 1444 | Mpi2FlashRegion_t, MPI2_POINTER pMpi2FlashRegion_t; | ||
| 1445 | |||
| 1446 | typedef struct _MPI2_FLASH_LAYOUT | ||
| 1447 | { | ||
| 1448 | U32 FlashSize; /* 0x00 */ | ||
| 1449 | U32 Reserved1; /* 0x04 */ | ||
| 1450 | U32 Reserved2; /* 0x08 */ | ||
| 1451 | U32 Reserved3; /* 0x0C */ | ||
| 1452 | MPI2_FLASH_REGION Region[MPI2_FLASH_NUMBER_OF_REGIONS];/* 0x10 */ | ||
| 1453 | } MPI2_FLASH_LAYOUT, MPI2_POINTER PTR_MPI2_FLASH_LAYOUT, | ||
| 1454 | Mpi2FlashLayout_t, MPI2_POINTER pMpi2FlashLayout_t; | ||
| 1455 | |||
| 1456 | typedef struct _MPI2_FLASH_LAYOUT_DATA | ||
| 1457 | { | ||
| 1458 | U8 ImageRevision; /* 0x00 */ | ||
| 1459 | U8 Reserved1; /* 0x01 */ | ||
| 1460 | U8 SizeOfRegion; /* 0x02 */ | ||
| 1461 | U8 Reserved2; /* 0x03 */ | ||
| 1462 | U16 NumberOfLayouts; /* 0x04 */ | ||
| 1463 | U16 RegionsPerLayout; /* 0x06 */ | ||
| 1464 | U16 MinimumSectorAlignment; /* 0x08 */ | ||
| 1465 | U16 Reserved3; /* 0x0A */ | ||
| 1466 | U32 Reserved4; /* 0x0C */ | ||
| 1467 | MPI2_FLASH_LAYOUT Layout[MPI2_FLASH_NUMBER_OF_LAYOUTS];/* 0x10 */ | ||
| 1468 | } MPI2_FLASH_LAYOUT_DATA, MPI2_POINTER PTR_MPI2_FLASH_LAYOUT_DATA, | ||
| 1469 | Mpi2FlashLayoutData_t, MPI2_POINTER pMpi2FlashLayoutData_t; | ||
| 1470 | |||
| 1471 | /* defines for the RegionType field */ | ||
| 1472 | #define MPI2_FLASH_REGION_UNUSED (0x00) | ||
| 1473 | #define MPI2_FLASH_REGION_FIRMWARE (0x01) | ||
| 1474 | #define MPI2_FLASH_REGION_BIOS (0x02) | ||
| 1475 | #define MPI2_FLASH_REGION_NVDATA (0x03) | ||
| 1476 | #define MPI2_FLASH_REGION_FIRMWARE_BACKUP (0x05) | ||
| 1477 | #define MPI2_FLASH_REGION_MFG_INFORMATION (0x06) | ||
| 1478 | #define MPI2_FLASH_REGION_CONFIG_1 (0x07) | ||
| 1479 | #define MPI2_FLASH_REGION_CONFIG_2 (0x08) | ||
| 1480 | #define MPI2_FLASH_REGION_MEGARAID (0x09) | ||
| 1481 | #define MPI2_FLASH_REGION_INIT (0x0A) | ||
| 1482 | |||
| 1483 | /* ImageRevision */ | ||
| 1484 | #define MPI2_FLASH_LAYOUT_IMAGE_REVISION (0x00) | ||
| 1485 | |||
| 1486 | |||
| 1487 | |||
| 1488 | /* Supported Devices Extended Image Data */ | ||
| 1489 | |||
| 1490 | /* | ||
| 1491 | * Host code (drivers, BIOS, utilities, etc.) should leave this define set to | ||
| 1492 | * one and check NumberOfDevices at runtime. | ||
| 1493 | */ | ||
| 1494 | #ifndef MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES | ||
| 1495 | #define MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES (1) | ||
| 1496 | #endif | ||
| 1497 | |||
| 1498 | typedef struct _MPI2_SUPPORTED_DEVICE | ||
| 1499 | { | ||
| 1500 | U16 DeviceID; /* 0x00 */ | ||
| 1501 | U16 VendorID; /* 0x02 */ | ||
| 1502 | U16 DeviceIDMask; /* 0x04 */ | ||
| 1503 | U16 Reserved1; /* 0x06 */ | ||
| 1504 | U8 LowPCIRev; /* 0x08 */ | ||
| 1505 | U8 HighPCIRev; /* 0x09 */ | ||
| 1506 | U16 Reserved2; /* 0x0A */ | ||
| 1507 | U32 Reserved3; /* 0x0C */ | ||
| 1508 | } MPI2_SUPPORTED_DEVICE, MPI2_POINTER PTR_MPI2_SUPPORTED_DEVICE, | ||
| 1509 | Mpi2SupportedDevice_t, MPI2_POINTER pMpi2SupportedDevice_t; | ||
| 1510 | |||
| 1511 | typedef struct _MPI2_SUPPORTED_DEVICES_DATA | ||
| 1512 | { | ||
| 1513 | U8 ImageRevision; /* 0x00 */ | ||
| 1514 | U8 Reserved1; /* 0x01 */ | ||
| 1515 | U8 NumberOfDevices; /* 0x02 */ | ||
| 1516 | U8 Reserved2; /* 0x03 */ | ||
| 1517 | U32 Reserved3; /* 0x04 */ | ||
| 1518 | MPI2_SUPPORTED_DEVICE SupportedDevice[MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES]; /* 0x08 */ | ||
| 1519 | } MPI2_SUPPORTED_DEVICES_DATA, MPI2_POINTER PTR_MPI2_SUPPORTED_DEVICES_DATA, | ||
| 1520 | Mpi2SupportedDevicesData_t, MPI2_POINTER pMpi2SupportedDevicesData_t; | ||
| 1521 | |||
| 1522 | /* ImageRevision */ | ||
| 1523 | #define MPI2_SUPPORTED_DEVICES_IMAGE_REVISION (0x00) | ||
| 1524 | |||
| 1525 | |||
| 1526 | /* Init Extended Image Data */ | ||
| 1527 | |||
| 1528 | typedef struct _MPI2_INIT_IMAGE_FOOTER | ||
| 1529 | |||
| 1530 | { | ||
| 1531 | U32 BootFlags; /* 0x00 */ | ||
| 1532 | U32 ImageSize; /* 0x04 */ | ||
| 1533 | U32 Signature0; /* 0x08 */ | ||
| 1534 | U32 Signature1; /* 0x0C */ | ||
| 1535 | U32 Signature2; /* 0x10 */ | ||
| 1536 | U32 ResetVector; /* 0x14 */ | ||
| 1537 | } MPI2_INIT_IMAGE_FOOTER, MPI2_POINTER PTR_MPI2_INIT_IMAGE_FOOTER, | ||
| 1538 | Mpi2InitImageFooter_t, MPI2_POINTER pMpi2InitImageFooter_t; | ||
| 1539 | |||
| 1540 | /* defines for the BootFlags field */ | ||
| 1541 | #define MPI2_INIT_IMAGE_BOOTFLAGS_OFFSET (0x00) | ||
| 1542 | |||
| 1543 | /* defines for the ImageSize field */ | ||
| 1544 | #define MPI2_INIT_IMAGE_IMAGESIZE_OFFSET (0x04) | ||
| 1545 | |||
| 1546 | /* defines for the Signature0 field */ | ||
| 1547 | #define MPI2_INIT_IMAGE_SIGNATURE0_OFFSET (0x08) | ||
| 1548 | #define MPI2_INIT_IMAGE_SIGNATURE0 (0x5AA55AEA) | ||
| 1549 | |||
| 1550 | /* defines for the Signature1 field */ | ||
| 1551 | #define MPI2_INIT_IMAGE_SIGNATURE1_OFFSET (0x0C) | ||
| 1552 | #define MPI2_INIT_IMAGE_SIGNATURE1 (0xA55AEAA5) | ||
| 1553 | |||
| 1554 | /* defines for the Signature2 field */ | ||
| 1555 | #define MPI2_INIT_IMAGE_SIGNATURE2_OFFSET (0x10) | ||
| 1556 | #define MPI2_INIT_IMAGE_SIGNATURE2 (0x5AEAA55A) | ||
| 1557 | |||
| 1558 | /* Signature fields as individual bytes */ | ||
| 1559 | #define MPI2_INIT_IMAGE_SIGNATURE_BYTE_0 (0xEA) | ||
| 1560 | #define MPI2_INIT_IMAGE_SIGNATURE_BYTE_1 (0x5A) | ||
| 1561 | #define MPI2_INIT_IMAGE_SIGNATURE_BYTE_2 (0xA5) | ||
| 1562 | #define MPI2_INIT_IMAGE_SIGNATURE_BYTE_3 (0x5A) | ||
| 1563 | |||
| 1564 | #define MPI2_INIT_IMAGE_SIGNATURE_BYTE_4 (0xA5) | ||
| 1565 | #define MPI2_INIT_IMAGE_SIGNATURE_BYTE_5 (0xEA) | ||
| 1566 | #define MPI2_INIT_IMAGE_SIGNATURE_BYTE_6 (0x5A) | ||
| 1567 | #define MPI2_INIT_IMAGE_SIGNATURE_BYTE_7 (0xA5) | ||
| 1568 | |||
| 1569 | #define MPI2_INIT_IMAGE_SIGNATURE_BYTE_8 (0x5A) | ||
| 1570 | #define MPI2_INIT_IMAGE_SIGNATURE_BYTE_9 (0xA5) | ||
| 1571 | #define MPI2_INIT_IMAGE_SIGNATURE_BYTE_A (0xEA) | ||
| 1572 | #define MPI2_INIT_IMAGE_SIGNATURE_BYTE_B (0x5A) | ||
| 1573 | |||
| 1574 | /* defines for the ResetVector field */ | ||
| 1575 | #define MPI2_INIT_IMAGE_RESETVECTOR_OFFSET (0x14) | ||
| 1576 | |||
| 1577 | |||
| 1578 | /* Encrypted Hash Extended Image Data */ | ||
| 1579 | |||
| 1580 | typedef struct _MPI25_ENCRYPTED_HASH_ENTRY { | ||
| 1581 | U8 HashImageType; /* 0x00 */ | ||
| 1582 | U8 HashAlgorithm; /* 0x01 */ | ||
| 1583 | U8 EncryptionAlgorithm; /* 0x02 */ | ||
| 1584 | U8 Reserved1; /* 0x03 */ | ||
| 1585 | U32 Reserved2; /* 0x04 */ | ||
| 1586 | U32 EncryptedHash[1]; /* 0x08 */ | ||
| 1587 | } MPI25_ENCRYPTED_HASH_ENTRY, MPI2_POINTER PTR_MPI25_ENCRYPTED_HASH_ENTRY, | ||
| 1588 | Mpi25EncryptedHashEntry_t, MPI2_POINTER pMpi25EncryptedHashEntry_t; | ||
| 1589 | |||
| 1590 | /* values for HashImageType */ | ||
| 1591 | #define MPI25_HASH_IMAGE_TYPE_UNUSED (0x00) | ||
| 1592 | #define MPI25_HASH_IMAGE_TYPE_FIRMWARE (0x01) | ||
| 1593 | #define MPI25_HASH_IMAGE_TYPE_BIOS (0x02) | ||
| 1594 | |||
| 1595 | /* values for HashAlgorithm */ | ||
| 1596 | #define MPI25_HASH_ALGORITHM_UNUSED (0x00) | ||
| 1597 | #define MPI25_HASH_ALGORITHM_SHA256 (0x01) | ||
| 1598 | |||
| 1599 | /* values for EncryptionAlgorithm */ | ||
| 1600 | #define MPI25_ENCRYPTION_ALG_UNUSED (0x00) | ||
| 1601 | #define MPI25_ENCRYPTION_ALG_RSA256 (0x01) | ||
| 1602 | |||
| 1603 | typedef struct _MPI25_ENCRYPTED_HASH_DATA { | ||
| 1604 | U8 ImageVersion; /* 0x00 */ | ||
| 1605 | U8 NumHash; /* 0x01 */ | ||
| 1606 | U16 Reserved1; /* 0x02 */ | ||
| 1607 | U32 Reserved2; /* 0x04 */ | ||
| 1608 | MPI25_ENCRYPTED_HASH_ENTRY EncryptedHashEntry[1]; /* 0x08 */ | ||
| 1609 | } MPI25_ENCRYPTED_HASH_DATA, MPI2_POINTER PTR_MPI25_ENCRYPTED_HASH_DATA, | ||
| 1610 | Mpi25EncryptedHashData_t, MPI2_POINTER pMpi25EncryptedHashData_t; | ||
| 1611 | |||
| 1612 | /**************************************************************************** | ||
| 1613 | * PowerManagementControl message | ||
| 1614 | ****************************************************************************/ | ||
| 1615 | |||
| 1616 | /* PowerManagementControl Request message */ | ||
| 1617 | typedef struct _MPI2_PWR_MGMT_CONTROL_REQUEST { | ||
| 1618 | U8 Feature; /* 0x00 */ | ||
| 1619 | U8 Reserved1; /* 0x01 */ | ||
| 1620 | U8 ChainOffset; /* 0x02 */ | ||
| 1621 | U8 Function; /* 0x03 */ | ||
| 1622 | U16 Reserved2; /* 0x04 */ | ||
| 1623 | U8 Reserved3; /* 0x06 */ | ||
| 1624 | U8 MsgFlags; /* 0x07 */ | ||
| 1625 | U8 VP_ID; /* 0x08 */ | ||
| 1626 | U8 VF_ID; /* 0x09 */ | ||
| 1627 | U16 Reserved4; /* 0x0A */ | ||
| 1628 | U8 Parameter1; /* 0x0C */ | ||
| 1629 | U8 Parameter2; /* 0x0D */ | ||
| 1630 | U8 Parameter3; /* 0x0E */ | ||
| 1631 | U8 Parameter4; /* 0x0F */ | ||
| 1632 | U32 Reserved5; /* 0x10 */ | ||
| 1633 | U32 Reserved6; /* 0x14 */ | ||
| 1634 | } MPI2_PWR_MGMT_CONTROL_REQUEST, MPI2_POINTER PTR_MPI2_PWR_MGMT_CONTROL_REQUEST, | ||
| 1635 | Mpi2PwrMgmtControlRequest_t, MPI2_POINTER pMpi2PwrMgmtControlRequest_t; | ||
| 1636 | |||
| 1637 | /* defines for the Feature field */ | ||
| 1638 | #define MPI2_PM_CONTROL_FEATURE_DA_PHY_POWER_COND (0x01) | ||
| 1639 | #define MPI2_PM_CONTROL_FEATURE_PORT_WIDTH_MODULATION (0x02) | ||
| 1640 | #define MPI2_PM_CONTROL_FEATURE_PCIE_LINK (0x03) /* obsolete */ | ||
| 1641 | #define MPI2_PM_CONTROL_FEATURE_IOC_SPEED (0x04) | ||
| 1642 | #define MPI2_PM_CONTROL_FEATURE_MIN_PRODUCT_SPECIFIC (0x80) | ||
| 1643 | #define MPI2_PM_CONTROL_FEATURE_MAX_PRODUCT_SPECIFIC (0xFF) | ||
| 1644 | |||
| 1645 | /* parameter usage for the MPI2_PM_CONTROL_FEATURE_DA_PHY_POWER_COND Feature */ | ||
| 1646 | /* Parameter1 contains a PHY number */ | ||
| 1647 | /* Parameter2 indicates power condition action using these defines */ | ||
| 1648 | #define MPI2_PM_CONTROL_PARAM2_PARTIAL (0x01) | ||
| 1649 | #define MPI2_PM_CONTROL_PARAM2_SLUMBER (0x02) | ||
| 1650 | #define MPI2_PM_CONTROL_PARAM2_EXIT_PWR_MGMT (0x03) | ||
| 1651 | /* Parameter3 and Parameter4 are reserved */ | ||
| 1652 | |||
| 1653 | /* parameter usage for the MPI2_PM_CONTROL_FEATURE_PORT_WIDTH_MODULATION | ||
| 1654 | * Feature */ | ||
| 1655 | /* Parameter1 contains SAS port width modulation group number */ | ||
| 1656 | /* Parameter2 indicates IOC action using these defines */ | ||
| 1657 | #define MPI2_PM_CONTROL_PARAM2_REQUEST_OWNERSHIP (0x01) | ||
| 1658 | #define MPI2_PM_CONTROL_PARAM2_CHANGE_MODULATION (0x02) | ||
| 1659 | #define MPI2_PM_CONTROL_PARAM2_RELINQUISH_OWNERSHIP (0x03) | ||
| 1660 | /* Parameter3 indicates desired modulation level using these defines */ | ||
| 1661 | #define MPI2_PM_CONTROL_PARAM3_25_PERCENT (0x00) | ||
| 1662 | #define MPI2_PM_CONTROL_PARAM3_50_PERCENT (0x01) | ||
| 1663 | #define MPI2_PM_CONTROL_PARAM3_75_PERCENT (0x02) | ||
| 1664 | #define MPI2_PM_CONTROL_PARAM3_100_PERCENT (0x03) | ||
| 1665 | /* Parameter4 is reserved */ | ||
| 1666 | |||
| 1667 | /* parameter usage for the MPI2_PM_CONTROL_FEATURE_PCIE_LINK Feature */ | ||
| 1668 | /* Parameter1 indicates desired PCIe link speed using these defines */ | ||
| 1669 | #define MPI2_PM_CONTROL_PARAM1_PCIE_2_5_GBPS (0x00) /* obsolete */ | ||
| 1670 | #define MPI2_PM_CONTROL_PARAM1_PCIE_5_0_GBPS (0x01) /* obsolete */ | ||
| 1671 | #define MPI2_PM_CONTROL_PARAM1_PCIE_8_0_GBPS (0x02) /* obsolete */ | ||
| 1672 | /* Parameter2 indicates desired PCIe link width using these defines */ | ||
| 1673 | #define MPI2_PM_CONTROL_PARAM2_WIDTH_X1 (0x01) /* obsolete */ | ||
| 1674 | #define MPI2_PM_CONTROL_PARAM2_WIDTH_X2 (0x02) /* obsolete */ | ||
| 1675 | #define MPI2_PM_CONTROL_PARAM2_WIDTH_X4 (0x04) /* obsolete */ | ||
| 1676 | #define MPI2_PM_CONTROL_PARAM2_WIDTH_X8 (0x08) /* obsolete */ | ||
| 1677 | /* Parameter3 and Parameter4 are reserved */ | ||
| 1678 | |||
| 1679 | /* parameter usage for the MPI2_PM_CONTROL_FEATURE_IOC_SPEED Feature */ | ||
| 1680 | /* Parameter1 indicates desired IOC hardware clock speed using these defines */ | ||
| 1681 | #define MPI2_PM_CONTROL_PARAM1_FULL_IOC_SPEED (0x01) | ||
| 1682 | #define MPI2_PM_CONTROL_PARAM1_HALF_IOC_SPEED (0x02) | ||
| 1683 | #define MPI2_PM_CONTROL_PARAM1_QUARTER_IOC_SPEED (0x04) | ||
| 1684 | #define MPI2_PM_CONTROL_PARAM1_EIGHTH_IOC_SPEED (0x08) | ||
| 1685 | /* Parameter2, Parameter3, and Parameter4 are reserved */ | ||
| 1686 | |||
| 1687 | |||
| 1688 | /* PowerManagementControl Reply message */ | ||
| 1689 | typedef struct _MPI2_PWR_MGMT_CONTROL_REPLY { | ||
| 1690 | U8 Feature; /* 0x00 */ | ||
| 1691 | U8 Reserved1; /* 0x01 */ | ||
| 1692 | U8 MsgLength; /* 0x02 */ | ||
| 1693 | U8 Function; /* 0x03 */ | ||
| 1694 | U16 Reserved2; /* 0x04 */ | ||
| 1695 | U8 Reserved3; /* 0x06 */ | ||
| 1696 | U8 MsgFlags; /* 0x07 */ | ||
| 1697 | U8 VP_ID; /* 0x08 */ | ||
| 1698 | U8 VF_ID; /* 0x09 */ | ||
| 1699 | U16 Reserved4; /* 0x0A */ | ||
| 1700 | U16 Reserved5; /* 0x0C */ | ||
| 1701 | U16 IOCStatus; /* 0x0E */ | ||
| 1702 | U32 IOCLogInfo; /* 0x10 */ | ||
| 1703 | } MPI2_PWR_MGMT_CONTROL_REPLY, MPI2_POINTER PTR_MPI2_PWR_MGMT_CONTROL_REPLY, | ||
| 1704 | Mpi2PwrMgmtControlReply_t, MPI2_POINTER pMpi2PwrMgmtControlReply_t; | ||
| 1705 | |||
| 1706 | |||
| 1707 | #endif | ||
| 1708 | |||
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_raid.h b/drivers/scsi/mpt2sas/mpi/mpi2_raid.h deleted file mode 100644 index 7efa58ff0d34..000000000000 --- a/drivers/scsi/mpt2sas/mpi/mpi2_raid.h +++ /dev/null | |||
| @@ -1,366 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2000-2014 LSI Corporation. | ||
| 3 | * | ||
| 4 | * | ||
| 5 | * Name: mpi2_raid.h | ||
| 6 | * Title: MPI Integrated RAID messages and structures | ||
| 7 | * Creation Date: April 26, 2007 | ||
| 8 | * | ||
| 9 | * mpi2_raid.h Version: 02.00.10 | ||
| 10 | * | ||
| 11 | * Version History | ||
| 12 | * --------------- | ||
| 13 | * | ||
| 14 | * Date Version Description | ||
| 15 | * -------- -------- ------------------------------------------------------ | ||
| 16 | * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. | ||
| 17 | * 08-31-07 02.00.01 Modifications to RAID Action request and reply, | ||
| 18 | * including the Actions and ActionData. | ||
| 19 | * 02-29-08 02.00.02 Added MPI2_RAID_ACTION_ADATA_DISABL_FULL_REBUILD. | ||
| 20 | * 05-21-08 02.00.03 Added MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS so that | ||
| 21 | * the PhysDisk array in MPI2_RAID_VOLUME_CREATION_STRUCT | ||
| 22 | * can be sized by the build environment. | ||
| 23 | * 07-30-09 02.00.04 Added proper define for the Use Default Settings bit of | ||
| 24 | * VolumeCreationFlags and marked the old one as obsolete. | ||
| 25 | * 05-12-10 02.00.05 Added MPI2_RAID_VOL_FLAGS_OP_MDC define. | ||
| 26 | * 08-24-10 02.00.06 Added MPI2_RAID_ACTION_COMPATIBILITY_CHECK along with | ||
| 27 | * related structures and defines. | ||
| 28 | * Added product-specific range to RAID Action values. | ||
| 29 | * 02-06-12 02.00.08 Added MPI2_RAID_ACTION_PHYSDISK_HIDDEN. | ||
| 30 | * 07-26-12 02.00.09 Added ElapsedSeconds field to MPI2_RAID_VOL_INDICATOR. | ||
| 31 | * Added MPI2_RAID_VOL_FLAGS_ELAPSED_SECONDS_VALID define. | ||
| 32 | * 04-17-13 02.00.10 Added MPI25_RAID_ACTION_ADATA_ALLOW_PI. | ||
| 33 | * -------------------------------------------------------------------------- | ||
| 34 | */ | ||
| 35 | |||
| 36 | #ifndef MPI2_RAID_H | ||
| 37 | #define MPI2_RAID_H | ||
| 38 | |||
| 39 | /***************************************************************************** | ||
| 40 | * | ||
| 41 | * Integrated RAID Messages | ||
| 42 | * | ||
| 43 | *****************************************************************************/ | ||
| 44 | |||
| 45 | /**************************************************************************** | ||
| 46 | * RAID Action messages | ||
| 47 | ****************************************************************************/ | ||
| 48 | |||
| 49 | /* ActionDataWord defines for use with MPI2_RAID_ACTION_CREATE_VOLUME action */ | ||
| 50 | #define MPI25_RAID_ACTION_ADATA_ALLOW_PI (0x80000000) | ||
| 51 | |||
| 52 | /* ActionDataWord defines for use with MPI2_RAID_ACTION_DELETE_VOLUME action */ | ||
| 53 | #define MPI2_RAID_ACTION_ADATA_KEEP_LBA0 (0x00000000) | ||
| 54 | #define MPI2_RAID_ACTION_ADATA_ZERO_LBA0 (0x00000001) | ||
| 55 | |||
| 56 | /* use MPI2_RAIDVOL0_SETTING_ defines from mpi2_cnfg.h for MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE action */ | ||
| 57 | |||
| 58 | /* ActionDataWord defines for use with MPI2_RAID_ACTION_DISABLE_ALL_VOLUMES action */ | ||
| 59 | #define MPI2_RAID_ACTION_ADATA_DISABL_FULL_REBUILD (0x00000001) | ||
| 60 | |||
| 61 | /* ActionDataWord for MPI2_RAID_ACTION_SET_RAID_FUNCTION_RATE Action */ | ||
| 62 | typedef struct _MPI2_RAID_ACTION_RATE_DATA | ||
| 63 | { | ||
| 64 | U8 RateToChange; /* 0x00 */ | ||
| 65 | U8 RateOrMode; /* 0x01 */ | ||
| 66 | U16 DataScrubDuration; /* 0x02 */ | ||
| 67 | } MPI2_RAID_ACTION_RATE_DATA, MPI2_POINTER PTR_MPI2_RAID_ACTION_RATE_DATA, | ||
| 68 | Mpi2RaidActionRateData_t, MPI2_POINTER pMpi2RaidActionRateData_t; | ||
| 69 | |||
| 70 | #define MPI2_RAID_ACTION_SET_RATE_RESYNC (0x00) | ||
| 71 | #define MPI2_RAID_ACTION_SET_RATE_DATA_SCRUB (0x01) | ||
| 72 | #define MPI2_RAID_ACTION_SET_RATE_POWERSAVE_MODE (0x02) | ||
| 73 | |||
| 74 | /* ActionDataWord for MPI2_RAID_ACTION_START_RAID_FUNCTION Action */ | ||
| 75 | typedef struct _MPI2_RAID_ACTION_START_RAID_FUNCTION | ||
| 76 | { | ||
| 77 | U8 RAIDFunction; /* 0x00 */ | ||
| 78 | U8 Flags; /* 0x01 */ | ||
| 79 | U16 Reserved1; /* 0x02 */ | ||
| 80 | } MPI2_RAID_ACTION_START_RAID_FUNCTION, | ||
| 81 | MPI2_POINTER PTR_MPI2_RAID_ACTION_START_RAID_FUNCTION, | ||
| 82 | Mpi2RaidActionStartRaidFunction_t, | ||
| 83 | MPI2_POINTER pMpi2RaidActionStartRaidFunction_t; | ||
| 84 | |||
| 85 | /* defines for the RAIDFunction field */ | ||
| 86 | #define MPI2_RAID_ACTION_START_BACKGROUND_INIT (0x00) | ||
| 87 | #define MPI2_RAID_ACTION_START_ONLINE_CAP_EXPANSION (0x01) | ||
| 88 | #define MPI2_RAID_ACTION_START_CONSISTENCY_CHECK (0x02) | ||
| 89 | |||
| 90 | /* defines for the Flags field */ | ||
| 91 | #define MPI2_RAID_ACTION_START_NEW (0x00) | ||
| 92 | #define MPI2_RAID_ACTION_START_RESUME (0x01) | ||
| 93 | |||
| 94 | /* ActionDataWord for MPI2_RAID_ACTION_STOP_RAID_FUNCTION Action */ | ||
| 95 | typedef struct _MPI2_RAID_ACTION_STOP_RAID_FUNCTION | ||
| 96 | { | ||
| 97 | U8 RAIDFunction; /* 0x00 */ | ||
| 98 | U8 Flags; /* 0x01 */ | ||
| 99 | U16 Reserved1; /* 0x02 */ | ||
| 100 | } MPI2_RAID_ACTION_STOP_RAID_FUNCTION, | ||
| 101 | MPI2_POINTER PTR_MPI2_RAID_ACTION_STOP_RAID_FUNCTION, | ||
| 102 | Mpi2RaidActionStopRaidFunction_t, | ||
| 103 | MPI2_POINTER pMpi2RaidActionStopRaidFunction_t; | ||
| 104 | |||
| 105 | /* defines for the RAIDFunction field */ | ||
| 106 | #define MPI2_RAID_ACTION_STOP_BACKGROUND_INIT (0x00) | ||
| 107 | #define MPI2_RAID_ACTION_STOP_ONLINE_CAP_EXPANSION (0x01) | ||
| 108 | #define MPI2_RAID_ACTION_STOP_CONSISTENCY_CHECK (0x02) | ||
| 109 | |||
| 110 | /* defines for the Flags field */ | ||
| 111 | #define MPI2_RAID_ACTION_STOP_ABORT (0x00) | ||
| 112 | #define MPI2_RAID_ACTION_STOP_PAUSE (0x01) | ||
| 113 | |||
| 114 | /* ActionDataWord for MPI2_RAID_ACTION_CREATE_HOT_SPARE Action */ | ||
| 115 | typedef struct _MPI2_RAID_ACTION_HOT_SPARE | ||
| 116 | { | ||
| 117 | U8 HotSparePool; /* 0x00 */ | ||
| 118 | U8 Reserved1; /* 0x01 */ | ||
| 119 | U16 DevHandle; /* 0x02 */ | ||
| 120 | } MPI2_RAID_ACTION_HOT_SPARE, MPI2_POINTER PTR_MPI2_RAID_ACTION_HOT_SPARE, | ||
| 121 | Mpi2RaidActionHotSpare_t, MPI2_POINTER pMpi2RaidActionHotSpare_t; | ||
| 122 | |||
| 123 | /* ActionDataWord for MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE Action */ | ||
| 124 | typedef struct _MPI2_RAID_ACTION_FW_UPDATE_MODE | ||
| 125 | { | ||
| 126 | U8 Flags; /* 0x00 */ | ||
| 127 | U8 DeviceFirmwareUpdateModeTimeout; /* 0x01 */ | ||
| 128 | U16 Reserved1; /* 0x02 */ | ||
| 129 | } MPI2_RAID_ACTION_FW_UPDATE_MODE, | ||
| 130 | MPI2_POINTER PTR_MPI2_RAID_ACTION_FW_UPDATE_MODE, | ||
| 131 | Mpi2RaidActionFwUpdateMode_t, MPI2_POINTER pMpi2RaidActionFwUpdateMode_t; | ||
| 132 | |||
| 133 | /* ActionDataWord defines for use with MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE action */ | ||
| 134 | #define MPI2_RAID_ACTION_ADATA_DISABLE_FW_UPDATE (0x00) | ||
| 135 | #define MPI2_RAID_ACTION_ADATA_ENABLE_FW_UPDATE (0x01) | ||
| 136 | |||
| 137 | typedef union _MPI2_RAID_ACTION_DATA | ||
| 138 | { | ||
| 139 | U32 Word; | ||
| 140 | MPI2_RAID_ACTION_RATE_DATA Rates; | ||
| 141 | MPI2_RAID_ACTION_START_RAID_FUNCTION StartRaidFunction; | ||
| 142 | MPI2_RAID_ACTION_STOP_RAID_FUNCTION StopRaidFunction; | ||
| 143 | MPI2_RAID_ACTION_HOT_SPARE HotSpare; | ||
| 144 | MPI2_RAID_ACTION_FW_UPDATE_MODE FwUpdateMode; | ||
| 145 | } MPI2_RAID_ACTION_DATA, MPI2_POINTER PTR_MPI2_RAID_ACTION_DATA, | ||
| 146 | Mpi2RaidActionData_t, MPI2_POINTER pMpi2RaidActionData_t; | ||
| 147 | |||
| 148 | |||
| 149 | /* RAID Action Request Message */ | ||
| 150 | typedef struct _MPI2_RAID_ACTION_REQUEST | ||
| 151 | { | ||
| 152 | U8 Action; /* 0x00 */ | ||
| 153 | U8 Reserved1; /* 0x01 */ | ||
| 154 | U8 ChainOffset; /* 0x02 */ | ||
| 155 | U8 Function; /* 0x03 */ | ||
| 156 | U16 VolDevHandle; /* 0x04 */ | ||
| 157 | U8 PhysDiskNum; /* 0x06 */ | ||
| 158 | U8 MsgFlags; /* 0x07 */ | ||
| 159 | U8 VP_ID; /* 0x08 */ | ||
| 160 | U8 VF_ID; /* 0x09 */ | ||
| 161 | U16 Reserved2; /* 0x0A */ | ||
| 162 | U32 Reserved3; /* 0x0C */ | ||
| 163 | MPI2_RAID_ACTION_DATA ActionDataWord; /* 0x10 */ | ||
| 164 | MPI2_SGE_SIMPLE_UNION ActionDataSGE; /* 0x14 */ | ||
| 165 | } MPI2_RAID_ACTION_REQUEST, MPI2_POINTER PTR_MPI2_RAID_ACTION_REQUEST, | ||
| 166 | Mpi2RaidActionRequest_t, MPI2_POINTER pMpi2RaidActionRequest_t; | ||
| 167 | |||
| 168 | /* RAID Action request Action values */ | ||
| 169 | |||
| 170 | #define MPI2_RAID_ACTION_INDICATOR_STRUCT (0x01) | ||
| 171 | #define MPI2_RAID_ACTION_CREATE_VOLUME (0x02) | ||
| 172 | #define MPI2_RAID_ACTION_DELETE_VOLUME (0x03) | ||
| 173 | #define MPI2_RAID_ACTION_DISABLE_ALL_VOLUMES (0x04) | ||
| 174 | #define MPI2_RAID_ACTION_ENABLE_ALL_VOLUMES (0x05) | ||
| 175 | #define MPI2_RAID_ACTION_PHYSDISK_OFFLINE (0x0A) | ||
| 176 | #define MPI2_RAID_ACTION_PHYSDISK_ONLINE (0x0B) | ||
| 177 | #define MPI2_RAID_ACTION_FAIL_PHYSDISK (0x0F) | ||
| 178 | #define MPI2_RAID_ACTION_ACTIVATE_VOLUME (0x11) | ||
| 179 | #define MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE (0x15) | ||
| 180 | #define MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE (0x17) | ||
| 181 | #define MPI2_RAID_ACTION_SET_VOLUME_NAME (0x18) | ||
| 182 | #define MPI2_RAID_ACTION_SET_RAID_FUNCTION_RATE (0x19) | ||
| 183 | #define MPI2_RAID_ACTION_ENABLE_FAILED_VOLUME (0x1C) | ||
| 184 | #define MPI2_RAID_ACTION_CREATE_HOT_SPARE (0x1D) | ||
| 185 | #define MPI2_RAID_ACTION_DELETE_HOT_SPARE (0x1E) | ||
| 186 | #define MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED (0x20) | ||
| 187 | #define MPI2_RAID_ACTION_START_RAID_FUNCTION (0x21) | ||
| 188 | #define MPI2_RAID_ACTION_STOP_RAID_FUNCTION (0x22) | ||
| 189 | #define MPI2_RAID_ACTION_COMPATIBILITY_CHECK (0x23) | ||
| 190 | #define MPI2_RAID_ACTION_PHYSDISK_HIDDEN (0x24) | ||
| 191 | #define MPI2_RAID_ACTION_MIN_PRODUCT_SPECIFIC (0x80) | ||
| 192 | #define MPI2_RAID_ACTION_MAX_PRODUCT_SPECIFIC (0xFF) | ||
| 193 | |||
| 194 | /* RAID Volume Creation Structure */ | ||
| 195 | |||
| 196 | /* | ||
| 197 | * The following define can be customized for the targeted product. | ||
| 198 | */ | ||
| 199 | #ifndef MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS | ||
| 200 | #define MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS (1) | ||
| 201 | #endif | ||
| 202 | |||
| 203 | typedef struct _MPI2_RAID_VOLUME_PHYSDISK | ||
| 204 | { | ||
| 205 | U8 RAIDSetNum; /* 0x00 */ | ||
| 206 | U8 PhysDiskMap; /* 0x01 */ | ||
| 207 | U16 PhysDiskDevHandle; /* 0x02 */ | ||
| 208 | } MPI2_RAID_VOLUME_PHYSDISK, MPI2_POINTER PTR_MPI2_RAID_VOLUME_PHYSDISK, | ||
| 209 | Mpi2RaidVolumePhysDisk_t, MPI2_POINTER pMpi2RaidVolumePhysDisk_t; | ||
| 210 | |||
| 211 | /* defines for the PhysDiskMap field */ | ||
| 212 | #define MPI2_RAIDACTION_PHYSDISK_PRIMARY (0x01) | ||
| 213 | #define MPI2_RAIDACTION_PHYSDISK_SECONDARY (0x02) | ||
| 214 | |||
| 215 | typedef struct _MPI2_RAID_VOLUME_CREATION_STRUCT | ||
| 216 | { | ||
| 217 | U8 NumPhysDisks; /* 0x00 */ | ||
| 218 | U8 VolumeType; /* 0x01 */ | ||
| 219 | U16 Reserved1; /* 0x02 */ | ||
| 220 | U32 VolumeCreationFlags; /* 0x04 */ | ||
| 221 | U32 VolumeSettings; /* 0x08 */ | ||
| 222 | U8 Reserved2; /* 0x0C */ | ||
| 223 | U8 ResyncRate; /* 0x0D */ | ||
| 224 | U16 DataScrubDuration; /* 0x0E */ | ||
| 225 | U64 VolumeMaxLBA; /* 0x10 */ | ||
| 226 | U32 StripeSize; /* 0x18 */ | ||
| 227 | U8 Name[16]; /* 0x1C */ | ||
| 228 | MPI2_RAID_VOLUME_PHYSDISK PhysDisk[MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS];/* 0x2C */ | ||
| 229 | } MPI2_RAID_VOLUME_CREATION_STRUCT, | ||
| 230 | MPI2_POINTER PTR_MPI2_RAID_VOLUME_CREATION_STRUCT, | ||
| 231 | Mpi2RaidVolumeCreationStruct_t, MPI2_POINTER pMpi2RaidVolumeCreationStruct_t; | ||
| 232 | |||
| 233 | /* use MPI2_RAID_VOL_TYPE_ defines from mpi2_cnfg.h for VolumeType */ | ||
| 234 | |||
| 235 | /* defines for the VolumeCreationFlags field */ | ||
| 236 | #define MPI2_RAID_VOL_CREATION_DEFAULT_SETTINGS (0x80000000) | ||
| 237 | #define MPI2_RAID_VOL_CREATION_BACKGROUND_INIT (0x00000004) | ||
| 238 | #define MPI2_RAID_VOL_CREATION_LOW_LEVEL_INIT (0x00000002) | ||
| 239 | #define MPI2_RAID_VOL_CREATION_MIGRATE_DATA (0x00000001) | ||
| 240 | /* The following is an obsolete define. | ||
| 241 | * It must be shifted left 24 bits in order to set the proper bit. | ||
| 242 | */ | ||
| 243 | #define MPI2_RAID_VOL_CREATION_USE_DEFAULT_SETTINGS (0x80) | ||
| 244 | |||
| 245 | |||
| 246 | /* RAID Online Capacity Expansion Structure */ | ||
| 247 | |||
| 248 | typedef struct _MPI2_RAID_ONLINE_CAPACITY_EXPANSION | ||
| 249 | { | ||
| 250 | U32 Flags; /* 0x00 */ | ||
| 251 | U16 DevHandle0; /* 0x04 */ | ||
| 252 | U16 Reserved1; /* 0x06 */ | ||
| 253 | U16 DevHandle1; /* 0x08 */ | ||
| 254 | U16 Reserved2; /* 0x0A */ | ||
| 255 | } MPI2_RAID_ONLINE_CAPACITY_EXPANSION, | ||
| 256 | MPI2_POINTER PTR_MPI2_RAID_ONLINE_CAPACITY_EXPANSION, | ||
| 257 | Mpi2RaidOnlineCapacityExpansion_t, | ||
| 258 | MPI2_POINTER pMpi2RaidOnlineCapacityExpansion_t; | ||
| 259 | |||
| 260 | /* RAID Compatibility Input Structure */ | ||
| 261 | |||
| 262 | typedef struct _MPI2_RAID_COMPATIBILITY_INPUT_STRUCT { | ||
| 263 | U16 SourceDevHandle; /* 0x00 */ | ||
| 264 | U16 CandidateDevHandle; /* 0x02 */ | ||
| 265 | U32 Flags; /* 0x04 */ | ||
| 266 | U32 Reserved1; /* 0x08 */ | ||
| 267 | U32 Reserved2; /* 0x0C */ | ||
| 268 | } MPI2_RAID_COMPATIBILITY_INPUT_STRUCT, | ||
| 269 | MPI2_POINTER PTR_MPI2_RAID_COMPATIBILITY_INPUT_STRUCT, | ||
| 270 | Mpi2RaidCompatibilityInputStruct_t, | ||
| 271 | MPI2_POINTER pMpi2RaidCompatibilityInputStruct_t; | ||
| 272 | |||
| 273 | /* defines for RAID Compatibility Structure Flags field */ | ||
| 274 | #define MPI2_RAID_COMPAT_SOURCE_IS_VOLUME_FLAG (0x00000002) | ||
| 275 | #define MPI2_RAID_COMPAT_REPORT_SOURCE_INFO_FLAG (0x00000001) | ||
| 276 | |||
| 277 | |||
| 278 | /* RAID Volume Indicator Structure */ | ||
| 279 | |||
| 280 | typedef struct _MPI2_RAID_VOL_INDICATOR | ||
| 281 | { | ||
| 282 | U64 TotalBlocks; /* 0x00 */ | ||
| 283 | U64 BlocksRemaining; /* 0x08 */ | ||
| 284 | U32 Flags; /* 0x10 */ | ||
| 285 | U32 ElapsedSeconds; /* 0x14 */ | ||
| 286 | } MPI2_RAID_VOL_INDICATOR, MPI2_POINTER PTR_MPI2_RAID_VOL_INDICATOR, | ||
| 287 | Mpi2RaidVolIndicator_t, MPI2_POINTER pMpi2RaidVolIndicator_t; | ||
| 288 | |||
| 289 | /* defines for RAID Volume Indicator Flags field */ | ||
| 290 | #define MPI2_RAID_VOL_FLAGS_ELAPSED_SECONDS_VALID (0x80000000) | ||
| 291 | |||
| 292 | #define MPI2_RAID_VOL_FLAGS_OP_MASK (0x0000000F) | ||
| 293 | #define MPI2_RAID_VOL_FLAGS_OP_BACKGROUND_INIT (0x00000000) | ||
| 294 | #define MPI2_RAID_VOL_FLAGS_OP_ONLINE_CAP_EXPANSION (0x00000001) | ||
| 295 | #define MPI2_RAID_VOL_FLAGS_OP_CONSISTENCY_CHECK (0x00000002) | ||
| 296 | #define MPI2_RAID_VOL_FLAGS_OP_RESYNC (0x00000003) | ||
| 297 | #define MPI2_RAID_VOL_FLAGS_OP_MDC (0x00000004) | ||
| 298 | |||
| 299 | /* RAID Compatibility Result Structure */ | ||
| 300 | |||
| 301 | typedef struct _MPI2_RAID_COMPATIBILITY_RESULT_STRUCT { | ||
| 302 | U8 State; /* 0x00 */ | ||
| 303 | U8 Reserved1; /* 0x01 */ | ||
| 304 | U16 Reserved2; /* 0x02 */ | ||
| 305 | U32 GenericAttributes; /* 0x04 */ | ||
| 306 | U32 OEMSpecificAttributes; /* 0x08 */ | ||
| 307 | U32 Reserved3; /* 0x0C */ | ||
| 308 | U32 Reserved4; /* 0x10 */ | ||
| 309 | } MPI2_RAID_COMPATIBILITY_RESULT_STRUCT, | ||
| 310 | MPI2_POINTER PTR_MPI2_RAID_COMPATIBILITY_RESULT_STRUCT, | ||
| 311 | Mpi2RaidCompatibilityResultStruct_t, | ||
| 312 | MPI2_POINTER pMpi2RaidCompatibilityResultStruct_t; | ||
| 313 | |||
| 314 | /* defines for RAID Compatibility Result Structure State field */ | ||
| 315 | #define MPI2_RAID_COMPAT_STATE_COMPATIBLE (0x00) | ||
| 316 | #define MPI2_RAID_COMPAT_STATE_NOT_COMPATIBLE (0x01) | ||
| 317 | |||
| 318 | /* defines for RAID Compatibility Result Structure GenericAttributes field */ | ||
| 319 | #define MPI2_RAID_COMPAT_GENATTRIB_4K_SECTOR (0x00000010) | ||
| 320 | |||
| 321 | #define MPI2_RAID_COMPAT_GENATTRIB_MEDIA_MASK (0x0000000C) | ||
| 322 | #define MPI2_RAID_COMPAT_GENATTRIB_SOLID_STATE_DRIVE (0x00000008) | ||
| 323 | #define MPI2_RAID_COMPAT_GENATTRIB_HARD_DISK_DRIVE (0x00000004) | ||
| 324 | |||
| 325 | #define MPI2_RAID_COMPAT_GENATTRIB_PROTOCOL_MASK (0x00000003) | ||
| 326 | #define MPI2_RAID_COMPAT_GENATTRIB_SAS_PROTOCOL (0x00000002) | ||
| 327 | #define MPI2_RAID_COMPAT_GENATTRIB_SATA_PROTOCOL (0x00000001) | ||
| 328 | |||
| 329 | /* RAID Action Reply ActionData union */ | ||
| 330 | typedef union _MPI2_RAID_ACTION_REPLY_DATA | ||
| 331 | { | ||
| 332 | U32 Word[6]; | ||
| 333 | MPI2_RAID_VOL_INDICATOR RaidVolumeIndicator; | ||
| 334 | U16 VolDevHandle; | ||
| 335 | U8 VolumeState; | ||
| 336 | U8 PhysDiskNum; | ||
| 337 | MPI2_RAID_COMPATIBILITY_RESULT_STRUCT RaidCompatibilityResult; | ||
| 338 | } MPI2_RAID_ACTION_REPLY_DATA, MPI2_POINTER PTR_MPI2_RAID_ACTION_REPLY_DATA, | ||
| 339 | Mpi2RaidActionReplyData_t, MPI2_POINTER pMpi2RaidActionReplyData_t; | ||
| 340 | |||
| 341 | /* use MPI2_RAIDVOL0_SETTING_ defines from mpi2_cnfg.h for MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE action */ | ||
| 342 | |||
| 343 | |||
| 344 | /* RAID Action Reply Message */ | ||
| 345 | typedef struct _MPI2_RAID_ACTION_REPLY | ||
| 346 | { | ||
| 347 | U8 Action; /* 0x00 */ | ||
| 348 | U8 Reserved1; /* 0x01 */ | ||
| 349 | U8 MsgLength; /* 0x02 */ | ||
| 350 | U8 Function; /* 0x03 */ | ||
| 351 | U16 VolDevHandle; /* 0x04 */ | ||
| 352 | U8 PhysDiskNum; /* 0x06 */ | ||
| 353 | U8 MsgFlags; /* 0x07 */ | ||
| 354 | U8 VP_ID; /* 0x08 */ | ||
| 355 | U8 VF_ID; /* 0x09 */ | ||
| 356 | U16 Reserved2; /* 0x0A */ | ||
| 357 | U16 Reserved3; /* 0x0C */ | ||
| 358 | U16 IOCStatus; /* 0x0E */ | ||
| 359 | U32 IOCLogInfo; /* 0x10 */ | ||
| 360 | MPI2_RAID_ACTION_REPLY_DATA ActionData; /* 0x14 */ | ||
| 361 | } MPI2_RAID_ACTION_REPLY, MPI2_POINTER PTR_MPI2_RAID_ACTION_REPLY, | ||
| 362 | Mpi2RaidActionReply_t, MPI2_POINTER pMpi2RaidActionReply_t; | ||
| 363 | |||
| 364 | |||
| 365 | #endif | ||
| 366 | |||
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_sas.h b/drivers/scsi/mpt2sas/mpi/mpi2_sas.h deleted file mode 100644 index 45b6fa10b803..000000000000 --- a/drivers/scsi/mpt2sas/mpi/mpi2_sas.h +++ /dev/null | |||
| @@ -1,288 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2000-2014 LSI Corporation. | ||
| 3 | * | ||
| 4 | * | ||
| 5 | * Name: mpi2_sas.h | ||
| 6 | * Title: MPI Serial Attached SCSI structures and definitions | ||
| 7 | * Creation Date: February 9, 2007 | ||
| 8 | * | ||
| 9 | * mpi2_sas.h Version: 02.00.05 | ||
| 10 | * | ||
| 11 | * Version History | ||
| 12 | * --------------- | ||
| 13 | * | ||
| 14 | * Date Version Description | ||
| 15 | * -------- -------- ------------------------------------------------------ | ||
| 16 | * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. | ||
| 17 | * 06-26-07 02.00.01 Added Clear All Persistent Operation to SAS IO Unit | ||
| 18 | * Control Request. | ||
| 19 | * 10-02-08 02.00.02 Added Set IOC Parameter Operation to SAS IO Unit Control | ||
| 20 | * Request. | ||
| 21 | * 10-28-09 02.00.03 Changed the type of SGL in MPI2_SATA_PASSTHROUGH_REQUEST | ||
| 22 | * to MPI2_SGE_IO_UNION since it supports chained SGLs. | ||
| 23 | * 05-12-10 02.00.04 Modified some comments. | ||
| 24 | * 08-11-10 02.00.05 Added NCQ operations to SAS IO Unit Control. | ||
| 25 | * -------------------------------------------------------------------------- | ||
| 26 | */ | ||
| 27 | |||
| 28 | #ifndef MPI2_SAS_H | ||
| 29 | #define MPI2_SAS_H | ||
| 30 | |||
| 31 | /* | ||
| 32 | * Values for SASStatus. | ||
| 33 | */ | ||
| 34 | #define MPI2_SASSTATUS_SUCCESS (0x00) | ||
| 35 | #define MPI2_SASSTATUS_UNKNOWN_ERROR (0x01) | ||
| 36 | #define MPI2_SASSTATUS_INVALID_FRAME (0x02) | ||
| 37 | #define MPI2_SASSTATUS_UTC_BAD_DEST (0x03) | ||
| 38 | #define MPI2_SASSTATUS_UTC_BREAK_RECEIVED (0x04) | ||
| 39 | #define MPI2_SASSTATUS_UTC_CONNECT_RATE_NOT_SUPPORTED (0x05) | ||
| 40 | #define MPI2_SASSTATUS_UTC_PORT_LAYER_REQUEST (0x06) | ||
| 41 | #define MPI2_SASSTATUS_UTC_PROTOCOL_NOT_SUPPORTED (0x07) | ||
| 42 | #define MPI2_SASSTATUS_UTC_STP_RESOURCES_BUSY (0x08) | ||
| 43 | #define MPI2_SASSTATUS_UTC_WRONG_DESTINATION (0x09) | ||
| 44 | #define MPI2_SASSTATUS_SHORT_INFORMATION_UNIT (0x0A) | ||
| 45 | #define MPI2_SASSTATUS_LONG_INFORMATION_UNIT (0x0B) | ||
| 46 | #define MPI2_SASSTATUS_XFER_RDY_INCORRECT_WRITE_DATA (0x0C) | ||
| 47 | #define MPI2_SASSTATUS_XFER_RDY_REQUEST_OFFSET_ERROR (0x0D) | ||
| 48 | #define MPI2_SASSTATUS_XFER_RDY_NOT_EXPECTED (0x0E) | ||
| 49 | #define MPI2_SASSTATUS_DATA_INCORRECT_DATA_LENGTH (0x0F) | ||
| 50 | #define MPI2_SASSTATUS_DATA_TOO_MUCH_READ_DATA (0x10) | ||
| 51 | #define MPI2_SASSTATUS_DATA_OFFSET_ERROR (0x11) | ||
| 52 | #define MPI2_SASSTATUS_SDSF_NAK_RECEIVED (0x12) | ||
| 53 | #define MPI2_SASSTATUS_SDSF_CONNECTION_FAILED (0x13) | ||
| 54 | #define MPI2_SASSTATUS_INITIATOR_RESPONSE_TIMEOUT (0x14) | ||
| 55 | |||
| 56 | |||
| 57 | /* | ||
| 58 | * Values for the SAS DeviceInfo field used in SAS Device Status Change Event | ||
| 59 | * data and SAS Configuration pages. | ||
| 60 | */ | ||
| 61 | #define MPI2_SAS_DEVICE_INFO_SEP (0x00004000) | ||
| 62 | #define MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE (0x00002000) | ||
| 63 | #define MPI2_SAS_DEVICE_INFO_LSI_DEVICE (0x00001000) | ||
| 64 | #define MPI2_SAS_DEVICE_INFO_DIRECT_ATTACH (0x00000800) | ||
| 65 | #define MPI2_SAS_DEVICE_INFO_SSP_TARGET (0x00000400) | ||
| 66 | #define MPI2_SAS_DEVICE_INFO_STP_TARGET (0x00000200) | ||
| 67 | #define MPI2_SAS_DEVICE_INFO_SMP_TARGET (0x00000100) | ||
| 68 | #define MPI2_SAS_DEVICE_INFO_SATA_DEVICE (0x00000080) | ||
| 69 | #define MPI2_SAS_DEVICE_INFO_SSP_INITIATOR (0x00000040) | ||
| 70 | #define MPI2_SAS_DEVICE_INFO_STP_INITIATOR (0x00000020) | ||
| 71 | #define MPI2_SAS_DEVICE_INFO_SMP_INITIATOR (0x00000010) | ||
| 72 | #define MPI2_SAS_DEVICE_INFO_SATA_HOST (0x00000008) | ||
| 73 | |||
| 74 | #define MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE (0x00000007) | ||
| 75 | #define MPI2_SAS_DEVICE_INFO_NO_DEVICE (0x00000000) | ||
| 76 | #define MPI2_SAS_DEVICE_INFO_END_DEVICE (0x00000001) | ||
| 77 | #define MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER (0x00000002) | ||
| 78 | #define MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER (0x00000003) | ||
| 79 | |||
| 80 | |||
| 81 | /***************************************************************************** | ||
| 82 | * | ||
| 83 | * SAS Messages | ||
| 84 | * | ||
| 85 | *****************************************************************************/ | ||
| 86 | |||
| 87 | /**************************************************************************** | ||
| 88 | * SMP Passthrough messages | ||
| 89 | ****************************************************************************/ | ||
| 90 | |||
| 91 | /* SMP Passthrough Request Message */ | ||
| 92 | typedef struct _MPI2_SMP_PASSTHROUGH_REQUEST | ||
| 93 | { | ||
| 94 | U8 PassthroughFlags; /* 0x00 */ | ||
| 95 | U8 PhysicalPort; /* 0x01 */ | ||
| 96 | U8 ChainOffset; /* 0x02 */ | ||
| 97 | U8 Function; /* 0x03 */ | ||
| 98 | U16 RequestDataLength; /* 0x04 */ | ||
| 99 | U8 SGLFlags; /* 0x06 */ | ||
| 100 | U8 MsgFlags; /* 0x07 */ | ||
| 101 | U8 VP_ID; /* 0x08 */ | ||
| 102 | U8 VF_ID; /* 0x09 */ | ||
| 103 | U16 Reserved1; /* 0x0A */ | ||
| 104 | U32 Reserved2; /* 0x0C */ | ||
| 105 | U64 SASAddress; /* 0x10 */ | ||
| 106 | U32 Reserved3; /* 0x18 */ | ||
| 107 | U32 Reserved4; /* 0x1C */ | ||
| 108 | MPI2_SIMPLE_SGE_UNION SGL; /* 0x20 */ | ||
| 109 | } MPI2_SMP_PASSTHROUGH_REQUEST, MPI2_POINTER PTR_MPI2_SMP_PASSTHROUGH_REQUEST, | ||
| 110 | Mpi2SmpPassthroughRequest_t, MPI2_POINTER pMpi2SmpPassthroughRequest_t; | ||
| 111 | |||
| 112 | /* values for PassthroughFlags field */ | ||
| 113 | #define MPI2_SMP_PT_REQ_PT_FLAGS_IMMEDIATE (0x80) | ||
| 114 | |||
| 115 | /* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */ | ||
| 116 | |||
| 117 | |||
| 118 | /* SMP Passthrough Reply Message */ | ||
| 119 | typedef struct _MPI2_SMP_PASSTHROUGH_REPLY | ||
| 120 | { | ||
| 121 | U8 PassthroughFlags; /* 0x00 */ | ||
| 122 | U8 PhysicalPort; /* 0x01 */ | ||
| 123 | U8 MsgLength; /* 0x02 */ | ||
| 124 | U8 Function; /* 0x03 */ | ||
| 125 | U16 ResponseDataLength; /* 0x04 */ | ||
| 126 | U8 SGLFlags; /* 0x06 */ | ||
| 127 | U8 MsgFlags; /* 0x07 */ | ||
| 128 | U8 VP_ID; /* 0x08 */ | ||
| 129 | U8 VF_ID; /* 0x09 */ | ||
| 130 | U16 Reserved1; /* 0x0A */ | ||
| 131 | U8 Reserved2; /* 0x0C */ | ||
| 132 | U8 SASStatus; /* 0x0D */ | ||
| 133 | U16 IOCStatus; /* 0x0E */ | ||
| 134 | U32 IOCLogInfo; /* 0x10 */ | ||
| 135 | U32 Reserved3; /* 0x14 */ | ||
| 136 | U8 ResponseData[4]; /* 0x18 */ | ||
| 137 | } MPI2_SMP_PASSTHROUGH_REPLY, MPI2_POINTER PTR_MPI2_SMP_PASSTHROUGH_REPLY, | ||
| 138 | Mpi2SmpPassthroughReply_t, MPI2_POINTER pMpi2SmpPassthroughReply_t; | ||
| 139 | |||
| 140 | /* values for PassthroughFlags field */ | ||
| 141 | #define MPI2_SMP_PT_REPLY_PT_FLAGS_IMMEDIATE (0x80) | ||
| 142 | |||
| 143 | /* values for SASStatus field are at the top of this file */ | ||
| 144 | |||
| 145 | |||
| 146 | /**************************************************************************** | ||
| 147 | * SATA Passthrough messages | ||
| 148 | ****************************************************************************/ | ||
| 149 | |||
| 150 | /* SATA Passthrough Request Message */ | ||
| 151 | typedef struct _MPI2_SATA_PASSTHROUGH_REQUEST | ||
| 152 | { | ||
| 153 | U16 DevHandle; /* 0x00 */ | ||
| 154 | U8 ChainOffset; /* 0x02 */ | ||
| 155 | U8 Function; /* 0x03 */ | ||
| 156 | U16 PassthroughFlags; /* 0x04 */ | ||
| 157 | U8 SGLFlags; /* 0x06 */ | ||
| 158 | U8 MsgFlags; /* 0x07 */ | ||
| 159 | U8 VP_ID; /* 0x08 */ | ||
| 160 | U8 VF_ID; /* 0x09 */ | ||
| 161 | U16 Reserved1; /* 0x0A */ | ||
| 162 | U32 Reserved2; /* 0x0C */ | ||
| 163 | U32 Reserved3; /* 0x10 */ | ||
| 164 | U32 Reserved4; /* 0x14 */ | ||
| 165 | U32 DataLength; /* 0x18 */ | ||
| 166 | U8 CommandFIS[20]; /* 0x1C */ | ||
| 167 | MPI2_SGE_IO_UNION SGL; /* 0x30 */ | ||
| 168 | } MPI2_SATA_PASSTHROUGH_REQUEST, MPI2_POINTER PTR_MPI2_SATA_PASSTHROUGH_REQUEST, | ||
| 169 | Mpi2SataPassthroughRequest_t, MPI2_POINTER pMpi2SataPassthroughRequest_t; | ||
| 170 | |||
| 171 | /* values for PassthroughFlags field */ | ||
| 172 | #define MPI2_SATA_PT_REQ_PT_FLAGS_EXECUTE_DIAG (0x0100) | ||
| 173 | #define MPI2_SATA_PT_REQ_PT_FLAGS_DMA (0x0020) | ||
| 174 | #define MPI2_SATA_PT_REQ_PT_FLAGS_PIO (0x0010) | ||
| 175 | #define MPI2_SATA_PT_REQ_PT_FLAGS_UNSPECIFIED_VU (0x0004) | ||
| 176 | #define MPI2_SATA_PT_REQ_PT_FLAGS_WRITE (0x0002) | ||
| 177 | #define MPI2_SATA_PT_REQ_PT_FLAGS_READ (0x0001) | ||
| 178 | |||
| 179 | /* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */ | ||
| 180 | |||
| 181 | |||
| 182 | /* SATA Passthrough Reply Message */ | ||
| 183 | typedef struct _MPI2_SATA_PASSTHROUGH_REPLY | ||
| 184 | { | ||
| 185 | U16 DevHandle; /* 0x00 */ | ||
| 186 | U8 MsgLength; /* 0x02 */ | ||
| 187 | U8 Function; /* 0x03 */ | ||
| 188 | U16 PassthroughFlags; /* 0x04 */ | ||
| 189 | U8 SGLFlags; /* 0x06 */ | ||
| 190 | U8 MsgFlags; /* 0x07 */ | ||
| 191 | U8 VP_ID; /* 0x08 */ | ||
| 192 | U8 VF_ID; /* 0x09 */ | ||
| 193 | U16 Reserved1; /* 0x0A */ | ||
| 194 | U8 Reserved2; /* 0x0C */ | ||
| 195 | U8 SASStatus; /* 0x0D */ | ||
| 196 | U16 IOCStatus; /* 0x0E */ | ||
| 197 | U32 IOCLogInfo; /* 0x10 */ | ||
| 198 | U8 StatusFIS[20]; /* 0x14 */ | ||
| 199 | U32 StatusControlRegisters; /* 0x28 */ | ||
| 200 | U32 TransferCount; /* 0x2C */ | ||
| 201 | } MPI2_SATA_PASSTHROUGH_REPLY, MPI2_POINTER PTR_MPI2_SATA_PASSTHROUGH_REPLY, | ||
| 202 | Mpi2SataPassthroughReply_t, MPI2_POINTER pMpi2SataPassthroughReply_t; | ||
| 203 | |||
| 204 | /* values for SASStatus field are at the top of this file */ | ||
| 205 | |||
| 206 | |||
| 207 | /**************************************************************************** | ||
| 208 | * SAS IO Unit Control messages | ||
| 209 | ****************************************************************************/ | ||
| 210 | |||
| 211 | /* SAS IO Unit Control Request Message */ | ||
| 212 | typedef struct _MPI2_SAS_IOUNIT_CONTROL_REQUEST | ||
| 213 | { | ||
| 214 | U8 Operation; /* 0x00 */ | ||
| 215 | U8 Reserved1; /* 0x01 */ | ||
| 216 | U8 ChainOffset; /* 0x02 */ | ||
| 217 | U8 Function; /* 0x03 */ | ||
| 218 | U16 DevHandle; /* 0x04 */ | ||
| 219 | U8 IOCParameter; /* 0x06 */ | ||
| 220 | U8 MsgFlags; /* 0x07 */ | ||
| 221 | U8 VP_ID; /* 0x08 */ | ||
| 222 | U8 VF_ID; /* 0x09 */ | ||
| 223 | U16 Reserved3; /* 0x0A */ | ||
| 224 | U16 Reserved4; /* 0x0C */ | ||
| 225 | U8 PhyNum; /* 0x0E */ | ||
| 226 | U8 PrimFlags; /* 0x0F */ | ||
| 227 | U32 Primitive; /* 0x10 */ | ||
| 228 | U8 LookupMethod; /* 0x14 */ | ||
| 229 | U8 Reserved5; /* 0x15 */ | ||
| 230 | U16 SlotNumber; /* 0x16 */ | ||
| 231 | U64 LookupAddress; /* 0x18 */ | ||
| 232 | U32 IOCParameterValue; /* 0x20 */ | ||
| 233 | U32 Reserved7; /* 0x24 */ | ||
| 234 | U32 Reserved8; /* 0x28 */ | ||
| 235 | } MPI2_SAS_IOUNIT_CONTROL_REQUEST, | ||
| 236 | MPI2_POINTER PTR_MPI2_SAS_IOUNIT_CONTROL_REQUEST, | ||
| 237 | Mpi2SasIoUnitControlRequest_t, MPI2_POINTER pMpi2SasIoUnitControlRequest_t; | ||
| 238 | |||
| 239 | /* values for the Operation field */ | ||
| 240 | #define MPI2_SAS_OP_CLEAR_ALL_PERSISTENT (0x02) | ||
| 241 | #define MPI2_SAS_OP_PHY_LINK_RESET (0x06) | ||
| 242 | #define MPI2_SAS_OP_PHY_HARD_RESET (0x07) | ||
| 243 | #define MPI2_SAS_OP_PHY_CLEAR_ERROR_LOG (0x08) | ||
| 244 | #define MPI2_SAS_OP_SEND_PRIMITIVE (0x0A) | ||
| 245 | #define MPI2_SAS_OP_FORCE_FULL_DISCOVERY (0x0B) | ||
| 246 | #define MPI2_SAS_OP_TRANSMIT_PORT_SELECT_SIGNAL (0x0C) | ||
| 247 | #define MPI2_SAS_OP_REMOVE_DEVICE (0x0D) | ||
| 248 | #define MPI2_SAS_OP_LOOKUP_MAPPING (0x0E) | ||
| 249 | #define MPI2_SAS_OP_SET_IOC_PARAMETER (0x0F) | ||
| 250 | #define MPI2_SAS_OP_DEV_ENABLE_NCQ (0x14) | ||
| 251 | #define MPI2_SAS_OP_DEV_DISABLE_NCQ (0x15) | ||
| 252 | #define MPI2_SAS_OP_PRODUCT_SPECIFIC_MIN (0x80) | ||
| 253 | |||
| 254 | /* values for the PrimFlags field */ | ||
| 255 | #define MPI2_SAS_PRIMFLAGS_SINGLE (0x08) | ||
| 256 | #define MPI2_SAS_PRIMFLAGS_TRIPLE (0x02) | ||
| 257 | #define MPI2_SAS_PRIMFLAGS_REDUNDANT (0x01) | ||
| 258 | |||
| 259 | /* values for the LookupMethod field */ | ||
| 260 | #define MPI2_SAS_LOOKUP_METHOD_SAS_ADDRESS (0x01) | ||
| 261 | #define MPI2_SAS_LOOKUP_METHOD_SAS_ENCLOSURE_SLOT (0x02) | ||
| 262 | #define MPI2_SAS_LOOKUP_METHOD_SAS_DEVICE_NAME (0x03) | ||
| 263 | |||
| 264 | |||
| 265 | /* SAS IO Unit Control Reply Message */ | ||
| 266 | typedef struct _MPI2_SAS_IOUNIT_CONTROL_REPLY | ||
| 267 | { | ||
| 268 | U8 Operation; /* 0x00 */ | ||
| 269 | U8 Reserved1; /* 0x01 */ | ||
| 270 | U8 MsgLength; /* 0x02 */ | ||
| 271 | U8 Function; /* 0x03 */ | ||
| 272 | U16 DevHandle; /* 0x04 */ | ||
| 273 | U8 IOCParameter; /* 0x06 */ | ||
| 274 | U8 MsgFlags; /* 0x07 */ | ||
| 275 | U8 VP_ID; /* 0x08 */ | ||
| 276 | U8 VF_ID; /* 0x09 */ | ||
| 277 | U16 Reserved3; /* 0x0A */ | ||
| 278 | U16 Reserved4; /* 0x0C */ | ||
| 279 | U16 IOCStatus; /* 0x0E */ | ||
| 280 | U32 IOCLogInfo; /* 0x10 */ | ||
| 281 | } MPI2_SAS_IOUNIT_CONTROL_REPLY, | ||
| 282 | MPI2_POINTER PTR_MPI2_SAS_IOUNIT_CONTROL_REPLY, | ||
| 283 | Mpi2SasIoUnitControlReply_t, MPI2_POINTER pMpi2SasIoUnitControlReply_t; | ||
| 284 | |||
| 285 | |||
| 286 | #endif | ||
| 287 | |||
| 288 | |||
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_tool.h b/drivers/scsi/mpt2sas/mpi/mpi2_tool.h deleted file mode 100644 index 659b8ac83ceb..000000000000 --- a/drivers/scsi/mpt2sas/mpi/mpi2_tool.h +++ /dev/null | |||
| @@ -1,481 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2000-2014 LSI Corporation. | ||
| 3 | * | ||
| 4 | * | ||
| 5 | * Name: mpi2_tool.h | ||
| 6 | * Title: MPI diagnostic tool structures and definitions | ||
| 7 | * Creation Date: March 26, 2007 | ||
| 8 | * | ||
| 9 | * mpi2_tool.h Version: 02.00.12 | ||
| 10 | * | ||
| 11 | * Version History | ||
| 12 | * --------------- | ||
| 13 | * | ||
| 14 | * Date Version Description | ||
| 15 | * -------- -------- ------------------------------------------------------ | ||
| 16 | * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. | ||
| 17 | * 12-18-07 02.00.01 Added Diagnostic Buffer Post and Diagnostic Release | ||
| 18 | * structures and defines. | ||
| 19 | * 02-29-08 02.00.02 Modified various names to make them 32-character unique. | ||
| 20 | * 05-06-09 02.00.03 Added ISTWI Read Write Tool and Diagnostic CLI Tool. | ||
| 21 | * 07-30-09 02.00.04 Added ExtendedType field to DiagnosticBufferPost request | ||
| 22 | * and reply messages. | ||
| 23 | * Added MPI2_DIAG_BUF_TYPE_EXTENDED. | ||
| 24 | * Incremented MPI2_DIAG_BUF_TYPE_COUNT. | ||
| 25 | * 05-12-10 02.00.05 Added Diagnostic Data Upload tool. | ||
| 26 | * 08-11-10 02.00.06 Added defines that were missing for Diagnostic Buffer | ||
| 27 | * Post Request. | ||
| 28 | * 05-25-11 02.00.07 Added Flags field and related defines to | ||
| 29 | * MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST. | ||
| 30 | * 07-26-12 02.00.10 Modified MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST so that | ||
| 31 | * it uses MPI Chain SGE as well as MPI Simple SGE. | ||
| 32 | * 08-19-13 02.00.11 Added MPI2_TOOLBOX_TEXT_DISPLAY_TOOL and related info. | ||
| 33 | * 01-08-14 02.00.12 Added MPI2_TOOLBOX_CLEAN_BIT26_PRODUCT_SPECIFIC. | ||
| 34 | * -------------------------------------------------------------------------- | ||
| 35 | */ | ||
| 36 | |||
| 37 | #ifndef MPI2_TOOL_H | ||
| 38 | #define MPI2_TOOL_H | ||
| 39 | |||
| 40 | /***************************************************************************** | ||
| 41 | * | ||
| 42 | * Toolbox Messages | ||
| 43 | * | ||
| 44 | *****************************************************************************/ | ||
| 45 | |||
| 46 | /* defines for the Tools */ | ||
| 47 | #define MPI2_TOOLBOX_CLEAN_TOOL (0x00) | ||
| 48 | #define MPI2_TOOLBOX_MEMORY_MOVE_TOOL (0x01) | ||
| 49 | #define MPI2_TOOLBOX_DIAG_DATA_UPLOAD_TOOL (0x02) | ||
| 50 | #define MPI2_TOOLBOX_ISTWI_READ_WRITE_TOOL (0x03) | ||
| 51 | #define MPI2_TOOLBOX_BEACON_TOOL (0x05) | ||
| 52 | #define MPI2_TOOLBOX_DIAGNOSTIC_CLI_TOOL (0x06) | ||
| 53 | #define MPI2_TOOLBOX_TEXT_DISPLAY_TOOL (0x07) | ||
| 54 | |||
| 55 | |||
| 56 | /**************************************************************************** | ||
| 57 | * Toolbox reply | ||
| 58 | ****************************************************************************/ | ||
| 59 | |||
| 60 | typedef struct _MPI2_TOOLBOX_REPLY | ||
| 61 | { | ||
| 62 | U8 Tool; /* 0x00 */ | ||
| 63 | U8 Reserved1; /* 0x01 */ | ||
| 64 | U8 MsgLength; /* 0x02 */ | ||
| 65 | U8 Function; /* 0x03 */ | ||
| 66 | U16 Reserved2; /* 0x04 */ | ||
| 67 | U8 Reserved3; /* 0x06 */ | ||
| 68 | U8 MsgFlags; /* 0x07 */ | ||
| 69 | U8 VP_ID; /* 0x08 */ | ||
| 70 | U8 VF_ID; /* 0x09 */ | ||
| 71 | U16 Reserved4; /* 0x0A */ | ||
| 72 | U16 Reserved5; /* 0x0C */ | ||
| 73 | U16 IOCStatus; /* 0x0E */ | ||
| 74 | U32 IOCLogInfo; /* 0x10 */ | ||
| 75 | } MPI2_TOOLBOX_REPLY, MPI2_POINTER PTR_MPI2_TOOLBOX_REPLY, | ||
| 76 | Mpi2ToolboxReply_t, MPI2_POINTER pMpi2ToolboxReply_t; | ||
| 77 | |||
| 78 | |||
| 79 | /**************************************************************************** | ||
| 80 | * Toolbox Clean Tool request | ||
| 81 | ****************************************************************************/ | ||
| 82 | |||
| 83 | typedef struct _MPI2_TOOLBOX_CLEAN_REQUEST | ||
| 84 | { | ||
| 85 | U8 Tool; /* 0x00 */ | ||
| 86 | U8 Reserved1; /* 0x01 */ | ||
| 87 | U8 ChainOffset; /* 0x02 */ | ||
| 88 | U8 Function; /* 0x03 */ | ||
| 89 | U16 Reserved2; /* 0x04 */ | ||
| 90 | U8 Reserved3; /* 0x06 */ | ||
| 91 | U8 MsgFlags; /* 0x07 */ | ||
| 92 | U8 VP_ID; /* 0x08 */ | ||
| 93 | U8 VF_ID; /* 0x09 */ | ||
| 94 | U16 Reserved4; /* 0x0A */ | ||
| 95 | U32 Flags; /* 0x0C */ | ||
| 96 | } MPI2_TOOLBOX_CLEAN_REQUEST, MPI2_POINTER PTR_MPI2_TOOLBOX_CLEAN_REQUEST, | ||
| 97 | Mpi2ToolboxCleanRequest_t, MPI2_POINTER pMpi2ToolboxCleanRequest_t; | ||
| 98 | |||
| 99 | /* values for the Flags field */ | ||
| 100 | #define MPI2_TOOLBOX_CLEAN_BOOT_SERVICES (0x80000000) | ||
| 101 | #define MPI2_TOOLBOX_CLEAN_PERSIST_MANUFACT_PAGES (0x40000000) | ||
| 102 | #define MPI2_TOOLBOX_CLEAN_OTHER_PERSIST_PAGES (0x20000000) | ||
| 103 | #define MPI2_TOOLBOX_CLEAN_FW_CURRENT (0x10000000) | ||
| 104 | #define MPI2_TOOLBOX_CLEAN_FW_BACKUP (0x08000000) | ||
| 105 | #define MPI2_TOOLBOX_CLEAN_BIT26_PRODUCT_SPECIFIC (0x04000000) | ||
| 106 | #define MPI2_TOOLBOX_CLEAN_MEGARAID (0x02000000) | ||
| 107 | #define MPI2_TOOLBOX_CLEAN_INITIALIZATION (0x01000000) | ||
| 108 | #define MPI2_TOOLBOX_CLEAN_FLASH (0x00000004) | ||
| 109 | #define MPI2_TOOLBOX_CLEAN_SEEPROM (0x00000002) | ||
| 110 | #define MPI2_TOOLBOX_CLEAN_NVSRAM (0x00000001) | ||
| 111 | |||
| 112 | |||
| 113 | /**************************************************************************** | ||
| 114 | * Toolbox Memory Move request | ||
| 115 | ****************************************************************************/ | ||
| 116 | |||
| 117 | typedef struct _MPI2_TOOLBOX_MEM_MOVE_REQUEST { | ||
| 118 | U8 Tool; /* 0x00 */ | ||
| 119 | U8 Reserved1; /* 0x01 */ | ||
| 120 | U8 ChainOffset; /* 0x02 */ | ||
| 121 | U8 Function; /* 0x03 */ | ||
| 122 | U16 Reserved2; /* 0x04 */ | ||
| 123 | U8 Reserved3; /* 0x06 */ | ||
| 124 | U8 MsgFlags; /* 0x07 */ | ||
| 125 | U8 VP_ID; /* 0x08 */ | ||
| 126 | U8 VF_ID; /* 0x09 */ | ||
| 127 | U16 Reserved4; /* 0x0A */ | ||
| 128 | MPI2_SGE_SIMPLE_UNION SGL; /* 0x0C */ | ||
| 129 | } MPI2_TOOLBOX_MEM_MOVE_REQUEST, MPI2_POINTER PTR_MPI2_TOOLBOX_MEM_MOVE_REQUEST, | ||
| 130 | Mpi2ToolboxMemMoveRequest_t, MPI2_POINTER pMpi2ToolboxMemMoveRequest_t; | ||
| 131 | |||
| 132 | |||
| 133 | /**************************************************************************** | ||
| 134 | * Toolbox Diagnostic Data Upload request | ||
| 135 | ****************************************************************************/ | ||
| 136 | |||
| 137 | typedef struct _MPI2_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST { | ||
| 138 | U8 Tool; /* 0x00 */ | ||
| 139 | U8 Reserved1; /* 0x01 */ | ||
| 140 | U8 ChainOffset; /* 0x02 */ | ||
| 141 | U8 Function; /* 0x03 */ | ||
| 142 | U16 Reserved2; /* 0x04 */ | ||
| 143 | U8 Reserved3; /* 0x06 */ | ||
| 144 | U8 MsgFlags; /* 0x07 */ | ||
| 145 | U8 VP_ID; /* 0x08 */ | ||
| 146 | U8 VF_ID; /* 0x09 */ | ||
| 147 | U16 Reserved4; /* 0x0A */ | ||
| 148 | U8 SGLFlags; /* 0x0C */ | ||
| 149 | U8 Reserved5; /* 0x0D */ | ||
| 150 | U16 Reserved6; /* 0x0E */ | ||
| 151 | U32 Flags; /* 0x10 */ | ||
| 152 | U32 DataLength; /* 0x14 */ | ||
| 153 | MPI2_SGE_SIMPLE_UNION SGL; /* 0x18 */ | ||
| 154 | } MPI2_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST, | ||
| 155 | MPI2_POINTER PTR_MPI2_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST, | ||
| 156 | Mpi2ToolboxDiagDataUploadRequest_t, | ||
| 157 | MPI2_POINTER pMpi2ToolboxDiagDataUploadRequest_t; | ||
| 158 | |||
| 159 | /* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */ | ||
| 160 | |||
| 161 | |||
| 162 | typedef struct _MPI2_DIAG_DATA_UPLOAD_HEADER { | ||
| 163 | U32 DiagDataLength; /* 00h */ | ||
| 164 | U8 FormatCode; /* 04h */ | ||
| 165 | U8 Reserved1; /* 05h */ | ||
| 166 | U16 Reserved2; /* 06h */ | ||
| 167 | } MPI2_DIAG_DATA_UPLOAD_HEADER, MPI2_POINTER PTR_MPI2_DIAG_DATA_UPLOAD_HEADER, | ||
| 168 | Mpi2DiagDataUploadHeader_t, MPI2_POINTER pMpi2DiagDataUploadHeader_t; | ||
| 169 | |||
| 170 | |||
| 171 | /**************************************************************************** | ||
| 172 | * Toolbox ISTWI Read Write Tool | ||
| 173 | ****************************************************************************/ | ||
| 174 | |||
| 175 | /* Toolbox ISTWI Read Write Tool request message */ | ||
| 176 | typedef struct _MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST { | ||
| 177 | U8 Tool; /* 0x00 */ | ||
| 178 | U8 Reserved1; /* 0x01 */ | ||
| 179 | U8 ChainOffset; /* 0x02 */ | ||
| 180 | U8 Function; /* 0x03 */ | ||
| 181 | U16 Reserved2; /* 0x04 */ | ||
| 182 | U8 Reserved3; /* 0x06 */ | ||
| 183 | U8 MsgFlags; /* 0x07 */ | ||
| 184 | U8 VP_ID; /* 0x08 */ | ||
| 185 | U8 VF_ID; /* 0x09 */ | ||
| 186 | U16 Reserved4; /* 0x0A */ | ||
| 187 | U32 Reserved5; /* 0x0C */ | ||
| 188 | U32 Reserved6; /* 0x10 */ | ||
| 189 | U8 DevIndex; /* 0x14 */ | ||
| 190 | U8 Action; /* 0x15 */ | ||
| 191 | U8 SGLFlags; /* 0x16 */ | ||
| 192 | U8 Flags; /* 0x17 */ | ||
| 193 | U16 TxDataLength; /* 0x18 */ | ||
| 194 | U16 RxDataLength; /* 0x1A */ | ||
| 195 | U32 Reserved8; /* 0x1C */ | ||
| 196 | U32 Reserved9; /* 0x20 */ | ||
| 197 | U32 Reserved10; /* 0x24 */ | ||
| 198 | U32 Reserved11; /* 0x28 */ | ||
| 199 | U32 Reserved12; /* 0x2C */ | ||
| 200 | MPI2_SGE_SIMPLE_UNION SGL; /* 0x30 */ | ||
| 201 | } MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST, | ||
| 202 | MPI2_POINTER PTR_MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST, | ||
| 203 | Mpi2ToolboxIstwiReadWriteRequest_t, | ||
| 204 | MPI2_POINTER pMpi2ToolboxIstwiReadWriteRequest_t; | ||
| 205 | |||
| 206 | /* values for the Action field */ | ||
| 207 | #define MPI2_TOOL_ISTWI_ACTION_READ_DATA (0x01) | ||
| 208 | #define MPI2_TOOL_ISTWI_ACTION_WRITE_DATA (0x02) | ||
| 209 | #define MPI2_TOOL_ISTWI_ACTION_SEQUENCE (0x03) | ||
| 210 | #define MPI2_TOOL_ISTWI_ACTION_RESERVE_BUS (0x10) | ||
| 211 | #define MPI2_TOOL_ISTWI_ACTION_RELEASE_BUS (0x11) | ||
| 212 | #define MPI2_TOOL_ISTWI_ACTION_RESET (0x12) | ||
| 213 | |||
| 214 | /* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */ | ||
| 215 | |||
| 216 | /* values for the Flags field */ | ||
| 217 | #define MPI2_TOOL_ISTWI_FLAG_AUTO_RESERVE_RELEASE (0x80) | ||
| 218 | #define MPI2_TOOL_ISTWI_FLAG_PAGE_ADDR_MASK (0x07) | ||
| 219 | |||
| 220 | /* Toolbox ISTWI Read Write Tool reply message */ | ||
| 221 | typedef struct _MPI2_TOOLBOX_ISTWI_REPLY { | ||
| 222 | U8 Tool; /* 0x00 */ | ||
| 223 | U8 Reserved1; /* 0x01 */ | ||
| 224 | U8 MsgLength; /* 0x02 */ | ||
| 225 | U8 Function; /* 0x03 */ | ||
| 226 | U16 Reserved2; /* 0x04 */ | ||
| 227 | U8 Reserved3; /* 0x06 */ | ||
| 228 | U8 MsgFlags; /* 0x07 */ | ||
| 229 | U8 VP_ID; /* 0x08 */ | ||
| 230 | U8 VF_ID; /* 0x09 */ | ||
| 231 | U16 Reserved4; /* 0x0A */ | ||
| 232 | U16 Reserved5; /* 0x0C */ | ||
| 233 | U16 IOCStatus; /* 0x0E */ | ||
| 234 | U32 IOCLogInfo; /* 0x10 */ | ||
| 235 | U8 DevIndex; /* 0x14 */ | ||
| 236 | U8 Action; /* 0x15 */ | ||
| 237 | U8 IstwiStatus; /* 0x16 */ | ||
| 238 | U8 Reserved6; /* 0x17 */ | ||
| 239 | U16 TxDataCount; /* 0x18 */ | ||
| 240 | U16 RxDataCount; /* 0x1A */ | ||
| 241 | } MPI2_TOOLBOX_ISTWI_REPLY, MPI2_POINTER PTR_MPI2_TOOLBOX_ISTWI_REPLY, | ||
| 242 | Mpi2ToolboxIstwiReply_t, MPI2_POINTER pMpi2ToolboxIstwiReply_t; | ||
| 243 | |||
| 244 | |||
| 245 | /**************************************************************************** | ||
| 246 | * Toolbox Beacon Tool request | ||
| 247 | ****************************************************************************/ | ||
| 248 | |||
| 249 | typedef struct _MPI2_TOOLBOX_BEACON_REQUEST | ||
| 250 | { | ||
| 251 | U8 Tool; /* 0x00 */ | ||
| 252 | U8 Reserved1; /* 0x01 */ | ||
| 253 | U8 ChainOffset; /* 0x02 */ | ||
| 254 | U8 Function; /* 0x03 */ | ||
| 255 | U16 Reserved2; /* 0x04 */ | ||
| 256 | U8 Reserved3; /* 0x06 */ | ||
| 257 | U8 MsgFlags; /* 0x07 */ | ||
| 258 | U8 VP_ID; /* 0x08 */ | ||
| 259 | U8 VF_ID; /* 0x09 */ | ||
| 260 | U16 Reserved4; /* 0x0A */ | ||
| 261 | U8 Reserved5; /* 0x0C */ | ||
| 262 | U8 PhysicalPort; /* 0x0D */ | ||
| 263 | U8 Reserved6; /* 0x0E */ | ||
| 264 | U8 Flags; /* 0x0F */ | ||
| 265 | } MPI2_TOOLBOX_BEACON_REQUEST, MPI2_POINTER PTR_MPI2_TOOLBOX_BEACON_REQUEST, | ||
| 266 | Mpi2ToolboxBeaconRequest_t, MPI2_POINTER pMpi2ToolboxBeaconRequest_t; | ||
| 267 | |||
| 268 | /* values for the Flags field */ | ||
| 269 | #define MPI2_TOOLBOX_FLAGS_BEACONMODE_OFF (0x00) | ||
| 270 | #define MPI2_TOOLBOX_FLAGS_BEACONMODE_ON (0x01) | ||
| 271 | |||
| 272 | |||
| 273 | /**************************************************************************** | ||
| 274 | * Toolbox Diagnostic CLI Tool | ||
| 275 | ****************************************************************************/ | ||
| 276 | |||
| 277 | #define MPI2_TOOLBOX_DIAG_CLI_CMD_LENGTH (0x5C) | ||
| 278 | |||
| 279 | /* MPI v2.0 Toolbox Diagnostic CLI Tool request message */ | ||
| 280 | typedef struct _MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST { | ||
| 281 | U8 Tool; /* 0x00 */ | ||
| 282 | U8 Reserved1; /* 0x01 */ | ||
| 283 | U8 ChainOffset; /* 0x02 */ | ||
| 284 | U8 Function; /* 0x03 */ | ||
| 285 | U16 Reserved2; /* 0x04 */ | ||
| 286 | U8 Reserved3; /* 0x06 */ | ||
| 287 | U8 MsgFlags; /* 0x07 */ | ||
| 288 | U8 VP_ID; /* 0x08 */ | ||
| 289 | U8 VF_ID; /* 0x09 */ | ||
| 290 | U16 Reserved4; /* 0x0A */ | ||
| 291 | U8 SGLFlags; /* 0x0C */ | ||
| 292 | U8 Reserved5; /* 0x0D */ | ||
| 293 | U16 Reserved6; /* 0x0E */ | ||
| 294 | U32 DataLength; /* 0x10 */ | ||
| 295 | U8 DiagnosticCliCommand | ||
| 296 | [MPI2_TOOLBOX_DIAG_CLI_CMD_LENGTH]; /* 0x14 */ | ||
| 297 | MPI2_MPI_SGE_IO_UNION SGL; /* 0x70 */ | ||
| 298 | } MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST, | ||
| 299 | MPI2_POINTER PTR_MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST, | ||
| 300 | Mpi2ToolboxDiagnosticCliRequest_t, | ||
| 301 | MPI2_POINTER pMpi2ToolboxDiagnosticCliRequest_t; | ||
| 302 | |||
| 303 | /* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */ | ||
| 304 | |||
| 305 | |||
| 306 | /* Toolbox Diagnostic CLI Tool reply message */ | ||
| 307 | typedef struct _MPI2_TOOLBOX_DIAGNOSTIC_CLI_REPLY { | ||
| 308 | U8 Tool; /* 0x00 */ | ||
| 309 | U8 Reserved1; /* 0x01 */ | ||
| 310 | U8 MsgLength; /* 0x02 */ | ||
| 311 | U8 Function; /* 0x03 */ | ||
| 312 | U16 Reserved2; /* 0x04 */ | ||
| 313 | U8 Reserved3; /* 0x06 */ | ||
| 314 | U8 MsgFlags; /* 0x07 */ | ||
| 315 | U8 VP_ID; /* 0x08 */ | ||
| 316 | U8 VF_ID; /* 0x09 */ | ||
| 317 | U16 Reserved4; /* 0x0A */ | ||
| 318 | U16 Reserved5; /* 0x0C */ | ||
| 319 | U16 IOCStatus; /* 0x0E */ | ||
| 320 | U32 IOCLogInfo; /* 0x10 */ | ||
| 321 | U32 ReturnedDataLength; /* 0x14 */ | ||
| 322 | } MPI2_TOOLBOX_DIAGNOSTIC_CLI_REPLY, | ||
| 323 | MPI2_POINTER PTR_MPI2_TOOLBOX_DIAG_CLI_REPLY, | ||
| 324 | Mpi2ToolboxDiagnosticCliReply_t, | ||
| 325 | MPI2_POINTER pMpi2ToolboxDiagnosticCliReply_t; | ||
| 326 | |||
| 327 | |||
| 328 | /**************************************************************************** | ||
| 329 | * Toolbox Console Text Display Tool | ||
| 330 | ****************************************************************************/ | ||
| 331 | |||
| 332 | /* Toolbox Console Text Display Tool request message */ | ||
| 333 | typedef struct _MPI2_TOOLBOX_TEXT_DISPLAY_REQUEST { | ||
| 334 | U8 Tool; /* 0x00 */ | ||
| 335 | U8 Reserved1; /* 0x01 */ | ||
| 336 | U8 ChainOffset; /* 0x02 */ | ||
| 337 | U8 Function; /* 0x03 */ | ||
| 338 | U16 Reserved2; /* 0x04 */ | ||
| 339 | U8 Reserved3; /* 0x06 */ | ||
| 340 | U8 MsgFlags; /* 0x07 */ | ||
| 341 | U8 VP_ID; /* 0x08 */ | ||
| 342 | U8 VF_ID; /* 0x09 */ | ||
| 343 | U16 Reserved4; /* 0x0A */ | ||
| 344 | U8 Console; /* 0x0C */ | ||
| 345 | U8 Flags; /* 0x0D */ | ||
| 346 | U16 Reserved6; /* 0x0E */ | ||
| 347 | U8 TextToDisplay[4]; /* 0x10 */ | ||
| 348 | } MPI2_TOOLBOX_TEXT_DISPLAY_REQUEST, | ||
| 349 | MPI2_POINTER PTR_MPI2_TOOLBOX_TEXT_DISPLAY_REQUEST, | ||
| 350 | Mpi2ToolboxTextDisplayRequest_t, | ||
| 351 | MPI2_POINTER pMpi2ToolboxTextDisplayRequest_t; | ||
| 352 | |||
| 353 | /* defines for the Console field */ | ||
| 354 | #define MPI2_TOOLBOX_CONSOLE_TYPE_MASK (0xF0) | ||
| 355 | #define MPI2_TOOLBOX_CONSOLE_TYPE_DEFAULT (0x00) | ||
| 356 | #define MPI2_TOOLBOX_CONSOLE_TYPE_UART (0x10) | ||
| 357 | #define MPI2_TOOLBOX_CONSOLE_TYPE_ETHERNET (0x20) | ||
| 358 | |||
| 359 | #define MPI2_TOOLBOX_CONSOLE_NUMBER_MASK (0x0F) | ||
| 360 | |||
| 361 | /* defines for the Flags field */ | ||
| 362 | #define MPI2_TOOLBOX_CONSOLE_FLAG_TIMESTAMP (0x01) | ||
| 363 | |||
| 364 | |||
| 365 | |||
| 366 | /***************************************************************************** | ||
| 367 | * | ||
| 368 | * Diagnostic Buffer Messages | ||
| 369 | * | ||
| 370 | *****************************************************************************/ | ||
| 371 | |||
| 372 | |||
| 373 | /**************************************************************************** | ||
| 374 | * Diagnostic Buffer Post request | ||
| 375 | ****************************************************************************/ | ||
| 376 | |||
| 377 | typedef struct _MPI2_DIAG_BUFFER_POST_REQUEST | ||
| 378 | { | ||
| 379 | U8 ExtendedType; /* 0x00 */ | ||
| 380 | U8 BufferType; /* 0x01 */ | ||
| 381 | U8 ChainOffset; /* 0x02 */ | ||
| 382 | U8 Function; /* 0x03 */ | ||
| 383 | U16 Reserved2; /* 0x04 */ | ||
| 384 | U8 Reserved3; /* 0x06 */ | ||
| 385 | U8 MsgFlags; /* 0x07 */ | ||
| 386 | U8 VP_ID; /* 0x08 */ | ||
| 387 | U8 VF_ID; /* 0x09 */ | ||
| 388 | U16 Reserved4; /* 0x0A */ | ||
| 389 | U64 BufferAddress; /* 0x0C */ | ||
| 390 | U32 BufferLength; /* 0x14 */ | ||
| 391 | U32 Reserved5; /* 0x18 */ | ||
| 392 | U32 Reserved6; /* 0x1C */ | ||
| 393 | U32 Flags; /* 0x20 */ | ||
| 394 | U32 ProductSpecific[23]; /* 0x24 */ | ||
| 395 | } MPI2_DIAG_BUFFER_POST_REQUEST, MPI2_POINTER PTR_MPI2_DIAG_BUFFER_POST_REQUEST, | ||
| 396 | Mpi2DiagBufferPostRequest_t, MPI2_POINTER pMpi2DiagBufferPostRequest_t; | ||
| 397 | |||
| 398 | /* values for the ExtendedType field */ | ||
| 399 | #define MPI2_DIAG_EXTENDED_TYPE_UTILIZATION (0x02) | ||
| 400 | |||
| 401 | /* values for the BufferType field */ | ||
| 402 | #define MPI2_DIAG_BUF_TYPE_TRACE (0x00) | ||
| 403 | #define MPI2_DIAG_BUF_TYPE_SNAPSHOT (0x01) | ||
| 404 | #define MPI2_DIAG_BUF_TYPE_EXTENDED (0x02) | ||
| 405 | /* count of the number of buffer types */ | ||
| 406 | #define MPI2_DIAG_BUF_TYPE_COUNT (0x03) | ||
| 407 | |||
| 408 | /* values for the Flags field */ | ||
| 409 | #define MPI2_DIAG_BUF_FLAG_RELEASE_ON_FULL (0x00000002) | ||
| 410 | #define MPI2_DIAG_BUF_FLAG_IMMEDIATE_RELEASE (0x00000001) | ||
| 411 | |||
| 412 | |||
| 413 | /**************************************************************************** | ||
| 414 | * Diagnostic Buffer Post reply | ||
| 415 | ****************************************************************************/ | ||
| 416 | |||
| 417 | typedef struct _MPI2_DIAG_BUFFER_POST_REPLY | ||
| 418 | { | ||
| 419 | U8 ExtendedType; /* 0x00 */ | ||
| 420 | U8 BufferType; /* 0x01 */ | ||
| 421 | U8 MsgLength; /* 0x02 */ | ||
| 422 | U8 Function; /* 0x03 */ | ||
| 423 | U16 Reserved2; /* 0x04 */ | ||
| 424 | U8 Reserved3; /* 0x06 */ | ||
| 425 | U8 MsgFlags; /* 0x07 */ | ||
| 426 | U8 VP_ID; /* 0x08 */ | ||
| 427 | U8 VF_ID; /* 0x09 */ | ||
| 428 | U16 Reserved4; /* 0x0A */ | ||
| 429 | U16 Reserved5; /* 0x0C */ | ||
| 430 | U16 IOCStatus; /* 0x0E */ | ||
| 431 | U32 IOCLogInfo; /* 0x10 */ | ||
| 432 | U32 TransferLength; /* 0x14 */ | ||
| 433 | } MPI2_DIAG_BUFFER_POST_REPLY, MPI2_POINTER PTR_MPI2_DIAG_BUFFER_POST_REPLY, | ||
| 434 | Mpi2DiagBufferPostReply_t, MPI2_POINTER pMpi2DiagBufferPostReply_t; | ||
| 435 | |||
| 436 | |||
| 437 | /**************************************************************************** | ||
| 438 | * Diagnostic Release request | ||
| 439 | ****************************************************************************/ | ||
| 440 | |||
| 441 | typedef struct _MPI2_DIAG_RELEASE_REQUEST | ||
| 442 | { | ||
| 443 | U8 Reserved1; /* 0x00 */ | ||
| 444 | U8 BufferType; /* 0x01 */ | ||
| 445 | U8 ChainOffset; /* 0x02 */ | ||
| 446 | U8 Function; /* 0x03 */ | ||
| 447 | U16 Reserved2; /* 0x04 */ | ||
| 448 | U8 Reserved3; /* 0x06 */ | ||
| 449 | U8 MsgFlags; /* 0x07 */ | ||
| 450 | U8 VP_ID; /* 0x08 */ | ||
| 451 | U8 VF_ID; /* 0x09 */ | ||
| 452 | U16 Reserved4; /* 0x0A */ | ||
| 453 | } MPI2_DIAG_RELEASE_REQUEST, MPI2_POINTER PTR_MPI2_DIAG_RELEASE_REQUEST, | ||
| 454 | Mpi2DiagReleaseRequest_t, MPI2_POINTER pMpi2DiagReleaseRequest_t; | ||
| 455 | |||
| 456 | |||
| 457 | /**************************************************************************** | ||
| 458 | * Diagnostic Buffer Post reply | ||
| 459 | ****************************************************************************/ | ||
| 460 | |||
| 461 | typedef struct _MPI2_DIAG_RELEASE_REPLY | ||
| 462 | { | ||
| 463 | U8 Reserved1; /* 0x00 */ | ||
| 464 | U8 BufferType; /* 0x01 */ | ||
| 465 | U8 MsgLength; /* 0x02 */ | ||
| 466 | U8 Function; /* 0x03 */ | ||
| 467 | U16 Reserved2; /* 0x04 */ | ||
| 468 | U8 Reserved3; /* 0x06 */ | ||
| 469 | U8 MsgFlags; /* 0x07 */ | ||
| 470 | U8 VP_ID; /* 0x08 */ | ||
| 471 | U8 VF_ID; /* 0x09 */ | ||
| 472 | U16 Reserved4; /* 0x0A */ | ||
| 473 | U16 Reserved5; /* 0x0C */ | ||
| 474 | U16 IOCStatus; /* 0x0E */ | ||
| 475 | U32 IOCLogInfo; /* 0x10 */ | ||
| 476 | } MPI2_DIAG_RELEASE_REPLY, MPI2_POINTER PTR_MPI2_DIAG_RELEASE_REPLY, | ||
| 477 | Mpi2DiagReleaseReply_t, MPI2_POINTER pMpi2DiagReleaseReply_t; | ||
| 478 | |||
| 479 | |||
| 480 | #endif | ||
| 481 | |||
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_type.h b/drivers/scsi/mpt2sas/mpi/mpi2_type.h deleted file mode 100644 index 6b0dcdd02f68..000000000000 --- a/drivers/scsi/mpt2sas/mpi/mpi2_type.h +++ /dev/null | |||
| @@ -1,61 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2000-2014 LSI Corporation. | ||
| 3 | * | ||
| 4 | * | ||
| 5 | * Name: mpi2_type.h | ||
| 6 | * Title: MPI basic type definitions | ||
| 7 | * Creation Date: August 16, 2006 | ||
| 8 | * | ||
| 9 | * mpi2_type.h Version: 02.00.00 | ||
| 10 | * | ||
| 11 | * Version History | ||
| 12 | * --------------- | ||
| 13 | * | ||
| 14 | * Date Version Description | ||
| 15 | * -------- -------- ------------------------------------------------------ | ||
| 16 | * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. | ||
| 17 | * -------------------------------------------------------------------------- | ||
| 18 | */ | ||
| 19 | |||
| 20 | #ifndef MPI2_TYPE_H | ||
| 21 | #define MPI2_TYPE_H | ||
| 22 | |||
| 23 | |||
| 24 | /******************************************************************************* | ||
| 25 | * Define MPI2_POINTER if it hasn't already been defined. By default | ||
| 26 | * MPI2_POINTER is defined to be a near pointer. MPI2_POINTER can be defined as | ||
| 27 | * a far pointer by defining MPI2_POINTER as "far *" before this header file is | ||
| 28 | * included. | ||
| 29 | */ | ||
| 30 | #ifndef MPI2_POINTER | ||
| 31 | #define MPI2_POINTER * | ||
| 32 | #endif | ||
| 33 | |||
| 34 | /* the basic types may have already been included by mpi_type.h */ | ||
| 35 | #ifndef MPI_TYPE_H | ||
| 36 | /***************************************************************************** | ||
| 37 | * | ||
| 38 | * Basic Types | ||
| 39 | * | ||
| 40 | *****************************************************************************/ | ||
| 41 | |||
| 42 | typedef u8 U8; | ||
| 43 | typedef __le16 U16; | ||
| 44 | typedef __le32 U32; | ||
| 45 | typedef __le64 U64 __attribute__((aligned(4))); | ||
| 46 | |||
| 47 | /***************************************************************************** | ||
| 48 | * | ||
| 49 | * Pointer Types | ||
| 50 | * | ||
| 51 | *****************************************************************************/ | ||
| 52 | |||
| 53 | typedef U8 *PU8; | ||
| 54 | typedef U16 *PU16; | ||
| 55 | typedef U32 *PU32; | ||
| 56 | typedef U64 *PU64; | ||
| 57 | |||
| 58 | #endif | ||
| 59 | |||
| 60 | #endif | ||
| 61 | |||
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c deleted file mode 100644 index c167911221e9..000000000000 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ /dev/null | |||
| @@ -1,4899 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * This is the Fusion MPT base driver providing common API layer interface | ||
| 3 | * for access to MPT (Message Passing Technology) firmware. | ||
| 4 | * | ||
| 5 | * This code is based on drivers/scsi/mpt2sas/mpt2_base.c | ||
| 6 | * Copyright (C) 2007-2014 LSI Corporation | ||
| 7 | * Copyright (C) 20013-2014 Avago Technologies | ||
| 8 | * (mailto: MPT-FusionLinux.pdl@avagotech.com) | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or | ||
| 11 | * modify it under the terms of the GNU General Public License | ||
| 12 | * as published by the Free Software Foundation; either version 2 | ||
| 13 | * of the License, or (at your option) any later version. | ||
| 14 | * | ||
| 15 | * This program is distributed in the hope that it will be useful, | ||
| 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | * GNU General Public License for more details. | ||
| 19 | * | ||
| 20 | * NO WARRANTY | ||
| 21 | * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR | ||
| 22 | * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT | ||
| 23 | * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, | ||
| 24 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is | ||
| 25 | * solely responsible for determining the appropriateness of using and | ||
| 26 | * distributing the Program and assumes all risks associated with its | ||
| 27 | * exercise of rights under this Agreement, including but not limited to | ||
| 28 | * the risks and costs of program errors, damage to or loss of data, | ||
| 29 | * programs or equipment, and unavailability or interruption of operations. | ||
| 30 | |||
| 31 | * DISCLAIMER OF LIABILITY | ||
| 32 | * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY | ||
| 33 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 34 | * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND | ||
| 35 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR | ||
| 36 | * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | ||
| 37 | * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED | ||
| 38 | * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES | ||
| 39 | |||
| 40 | * You should have received a copy of the GNU General Public License | ||
| 41 | * along with this program; if not, write to the Free Software | ||
| 42 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
| 43 | * USA. | ||
| 44 | */ | ||
| 45 | |||
| 46 | #include <linux/kernel.h> | ||
| 47 | #include <linux/module.h> | ||
| 48 | #include <linux/errno.h> | ||
| 49 | #include <linux/init.h> | ||
| 50 | #include <linux/slab.h> | ||
| 51 | #include <linux/types.h> | ||
| 52 | #include <linux/pci.h> | ||
| 53 | #include <linux/kdev_t.h> | ||
| 54 | #include <linux/blkdev.h> | ||
| 55 | #include <linux/delay.h> | ||
| 56 | #include <linux/interrupt.h> | ||
| 57 | #include <linux/dma-mapping.h> | ||
| 58 | #include <linux/sort.h> | ||
| 59 | #include <linux/io.h> | ||
| 60 | #include <linux/time.h> | ||
| 61 | #include <linux/kthread.h> | ||
| 62 | #include <linux/aer.h> | ||
| 63 | |||
| 64 | #include "mpt2sas_base.h" | ||
| 65 | |||
| 66 | static MPT_CALLBACK mpt_callbacks[MPT_MAX_CALLBACKS]; | ||
| 67 | |||
| 68 | #define FAULT_POLLING_INTERVAL 1000 /* in milliseconds */ | ||
| 69 | |||
| 70 | #define MAX_HBA_QUEUE_DEPTH 30000 | ||
| 71 | #define MAX_CHAIN_DEPTH 100000 | ||
| 72 | static int max_queue_depth = -1; | ||
| 73 | module_param(max_queue_depth, int, 0); | ||
| 74 | MODULE_PARM_DESC(max_queue_depth, " max controller queue depth "); | ||
| 75 | |||
| 76 | static int max_sgl_entries = -1; | ||
| 77 | module_param(max_sgl_entries, int, 0); | ||
| 78 | MODULE_PARM_DESC(max_sgl_entries, " max sg entries "); | ||
| 79 | |||
| 80 | static int msix_disable = -1; | ||
| 81 | module_param(msix_disable, int, 0); | ||
| 82 | MODULE_PARM_DESC(msix_disable, " disable msix routed interrupts (default=0)"); | ||
| 83 | |||
| 84 | static int max_msix_vectors = -1; | ||
| 85 | module_param(max_msix_vectors, int, 0); | ||
| 86 | MODULE_PARM_DESC(max_msix_vectors, " max msix vectors "); | ||
| 87 | |||
| 88 | static int mpt2sas_fwfault_debug; | ||
| 89 | MODULE_PARM_DESC(mpt2sas_fwfault_debug, " enable detection of firmware fault " | ||
| 90 | "and halt firmware - (default=0)"); | ||
| 91 | |||
| 92 | static int disable_discovery = -1; | ||
| 93 | module_param(disable_discovery, int, 0); | ||
| 94 | MODULE_PARM_DESC(disable_discovery, " disable discovery "); | ||
| 95 | |||
| 96 | static int | ||
| 97 | _base_get_ioc_facts(struct MPT2SAS_ADAPTER *ioc, int sleep_flag); | ||
| 98 | |||
| 99 | static int | ||
| 100 | _base_diag_reset(struct MPT2SAS_ADAPTER *ioc, int sleep_flag); | ||
| 101 | |||
| 102 | /** | ||
| 103 | * _scsih_set_fwfault_debug - global setting of ioc->fwfault_debug. | ||
| 104 | * | ||
| 105 | */ | ||
| 106 | static int | ||
| 107 | _scsih_set_fwfault_debug(const char *val, struct kernel_param *kp) | ||
| 108 | { | ||
| 109 | int ret = param_set_int(val, kp); | ||
| 110 | struct MPT2SAS_ADAPTER *ioc; | ||
| 111 | |||
| 112 | if (ret) | ||
| 113 | return ret; | ||
| 114 | |||
| 115 | /* global ioc spinlock to protect controller list on list operations */ | ||
| 116 | printk(KERN_INFO "setting fwfault_debug(%d)\n", mpt2sas_fwfault_debug); | ||
| 117 | spin_lock(&gioc_lock); | ||
| 118 | list_for_each_entry(ioc, &mpt2sas_ioc_list, list) | ||
| 119 | ioc->fwfault_debug = mpt2sas_fwfault_debug; | ||
| 120 | spin_unlock(&gioc_lock); | ||
| 121 | return 0; | ||
| 122 | } | ||
| 123 | |||
| 124 | module_param_call(mpt2sas_fwfault_debug, _scsih_set_fwfault_debug, | ||
| 125 | param_get_int, &mpt2sas_fwfault_debug, 0644); | ||
| 126 | |||
| 127 | /** | ||
| 128 | * mpt2sas_remove_dead_ioc_func - kthread context to remove dead ioc | ||
| 129 | * @arg: input argument, used to derive ioc | ||
| 130 | * | ||
| 131 | * Return 0 if controller is removed from pci subsystem. | ||
| 132 | * Return -1 for other case. | ||
| 133 | */ | ||
| 134 | static int mpt2sas_remove_dead_ioc_func(void *arg) | ||
| 135 | { | ||
| 136 | struct MPT2SAS_ADAPTER *ioc = (struct MPT2SAS_ADAPTER *)arg; | ||
| 137 | struct pci_dev *pdev; | ||
| 138 | |||
| 139 | if ((ioc == NULL)) | ||
| 140 | return -1; | ||
| 141 | |||
| 142 | pdev = ioc->pdev; | ||
| 143 | if ((pdev == NULL)) | ||
| 144 | return -1; | ||
| 145 | pci_stop_and_remove_bus_device_locked(pdev); | ||
| 146 | return 0; | ||
| 147 | } | ||
| 148 | |||
| 149 | |||
| 150 | /** | ||
| 151 | * _base_fault_reset_work - workq handling ioc fault conditions | ||
| 152 | * @work: input argument, used to derive ioc | ||
| 153 | * Context: sleep. | ||
| 154 | * | ||
| 155 | * Return nothing. | ||
| 156 | */ | ||
| 157 | static void | ||
| 158 | _base_fault_reset_work(struct work_struct *work) | ||
| 159 | { | ||
| 160 | struct MPT2SAS_ADAPTER *ioc = | ||
| 161 | container_of(work, struct MPT2SAS_ADAPTER, fault_reset_work.work); | ||
| 162 | unsigned long flags; | ||
| 163 | u32 doorbell; | ||
| 164 | int rc; | ||
| 165 | struct task_struct *p; | ||
| 166 | |||
| 167 | spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); | ||
| 168 | if (ioc->shost_recovery || ioc->pci_error_recovery) | ||
| 169 | goto rearm_timer; | ||
| 170 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); | ||
| 171 | |||
| 172 | doorbell = mpt2sas_base_get_iocstate(ioc, 0); | ||
| 173 | if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_MASK) { | ||
| 174 | printk(MPT2SAS_INFO_FMT "%s : SAS host is non-operational !!!!\n", | ||
| 175 | ioc->name, __func__); | ||
| 176 | |||
| 177 | /* It may be possible that EEH recovery can resolve some of | ||
| 178 | * pci bus failure issues rather removing the dead ioc function | ||
| 179 | * by considering controller is in a non-operational state. So | ||
| 180 | * here priority is given to the EEH recovery. If it doesn't | ||
| 181 | * not resolve this issue, mpt2sas driver will consider this | ||
| 182 | * controller to non-operational state and remove the dead ioc | ||
| 183 | * function. | ||
| 184 | */ | ||
| 185 | if (ioc->non_operational_loop++ < 5) { | ||
| 186 | spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, | ||
| 187 | flags); | ||
| 188 | goto rearm_timer; | ||
| 189 | } | ||
| 190 | |||
| 191 | /* | ||
| 192 | * Call _scsih_flush_pending_cmds callback so that we flush all | ||
| 193 | * pending commands back to OS. This call is required to aovid | ||
| 194 | * deadlock at block layer. Dead IOC will fail to do diag reset, | ||
| 195 | * and this call is safe since dead ioc will never return any | ||
| 196 | * command back from HW. | ||
| 197 | */ | ||
| 198 | ioc->schedule_dead_ioc_flush_running_cmds(ioc); | ||
| 199 | /* | ||
| 200 | * Set remove_host flag early since kernel thread will | ||
| 201 | * take some time to execute. | ||
| 202 | */ | ||
| 203 | ioc->remove_host = 1; | ||
| 204 | /*Remove the Dead Host */ | ||
| 205 | p = kthread_run(mpt2sas_remove_dead_ioc_func, ioc, | ||
| 206 | "mpt2sas_dead_ioc_%d", ioc->id); | ||
| 207 | if (IS_ERR(p)) { | ||
| 208 | printk(MPT2SAS_ERR_FMT | ||
| 209 | "%s: Running mpt2sas_dead_ioc thread failed !!!!\n", | ||
| 210 | ioc->name, __func__); | ||
| 211 | } else { | ||
| 212 | printk(MPT2SAS_ERR_FMT | ||
| 213 | "%s: Running mpt2sas_dead_ioc thread success !!!!\n", | ||
| 214 | ioc->name, __func__); | ||
| 215 | } | ||
| 216 | |||
| 217 | return; /* don't rearm timer */ | ||
| 218 | } | ||
| 219 | |||
| 220 | ioc->non_operational_loop = 0; | ||
| 221 | |||
| 222 | if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) { | ||
| 223 | rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, | ||
| 224 | FORCE_BIG_HAMMER); | ||
| 225 | printk(MPT2SAS_WARN_FMT "%s: hard reset: %s\n", ioc->name, | ||
| 226 | __func__, (rc == 0) ? "success" : "failed"); | ||
| 227 | doorbell = mpt2sas_base_get_iocstate(ioc, 0); | ||
| 228 | if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) | ||
| 229 | mpt2sas_base_fault_info(ioc, doorbell & | ||
| 230 | MPI2_DOORBELL_DATA_MASK); | ||
| 231 | } | ||
| 232 | |||
| 233 | spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); | ||
| 234 | rearm_timer: | ||
| 235 | if (ioc->fault_reset_work_q) | ||
| 236 | queue_delayed_work(ioc->fault_reset_work_q, | ||
| 237 | &ioc->fault_reset_work, | ||
| 238 | msecs_to_jiffies(FAULT_POLLING_INTERVAL)); | ||
| 239 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); | ||
| 240 | } | ||
| 241 | |||
| 242 | /** | ||
| 243 | * mpt2sas_base_start_watchdog - start the fault_reset_work_q | ||
| 244 | * @ioc: per adapter object | ||
| 245 | * Context: sleep. | ||
| 246 | * | ||
| 247 | * Return nothing. | ||
| 248 | */ | ||
| 249 | void | ||
| 250 | mpt2sas_base_start_watchdog(struct MPT2SAS_ADAPTER *ioc) | ||
| 251 | { | ||
| 252 | unsigned long flags; | ||
| 253 | |||
| 254 | if (ioc->fault_reset_work_q) | ||
| 255 | return; | ||
| 256 | |||
| 257 | /* initialize fault polling */ | ||
| 258 | INIT_DELAYED_WORK(&ioc->fault_reset_work, _base_fault_reset_work); | ||
| 259 | snprintf(ioc->fault_reset_work_q_name, | ||
| 260 | sizeof(ioc->fault_reset_work_q_name), "poll_%d_status", ioc->id); | ||
| 261 | ioc->fault_reset_work_q = | ||
| 262 | create_singlethread_workqueue(ioc->fault_reset_work_q_name); | ||
| 263 | if (!ioc->fault_reset_work_q) { | ||
| 264 | printk(MPT2SAS_ERR_FMT "%s: failed (line=%d)\n", | ||
| 265 | ioc->name, __func__, __LINE__); | ||
| 266 | return; | ||
| 267 | } | ||
| 268 | spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); | ||
| 269 | if (ioc->fault_reset_work_q) | ||
| 270 | queue_delayed_work(ioc->fault_reset_work_q, | ||
| 271 | &ioc->fault_reset_work, | ||
| 272 | msecs_to_jiffies(FAULT_POLLING_INTERVAL)); | ||
| 273 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); | ||
| 274 | } | ||
| 275 | |||
| 276 | /** | ||
| 277 | * mpt2sas_base_stop_watchdog - stop the fault_reset_work_q | ||
| 278 | * @ioc: per adapter object | ||
| 279 | * Context: sleep. | ||
| 280 | * | ||
| 281 | * Return nothing. | ||
| 282 | */ | ||
| 283 | void | ||
| 284 | mpt2sas_base_stop_watchdog(struct MPT2SAS_ADAPTER *ioc) | ||
| 285 | { | ||
| 286 | unsigned long flags; | ||
| 287 | struct workqueue_struct *wq; | ||
| 288 | |||
| 289 | spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); | ||
| 290 | wq = ioc->fault_reset_work_q; | ||
| 291 | ioc->fault_reset_work_q = NULL; | ||
| 292 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); | ||
| 293 | if (wq) { | ||
| 294 | if (!cancel_delayed_work_sync(&ioc->fault_reset_work)) | ||
| 295 | flush_workqueue(wq); | ||
| 296 | destroy_workqueue(wq); | ||
| 297 | } | ||
| 298 | } | ||
| 299 | |||
| 300 | /** | ||
| 301 | * mpt2sas_base_fault_info - verbose translation of firmware FAULT code | ||
| 302 | * @ioc: per adapter object | ||
| 303 | * @fault_code: fault code | ||
| 304 | * | ||
| 305 | * Return nothing. | ||
| 306 | */ | ||
| 307 | void | ||
| 308 | mpt2sas_base_fault_info(struct MPT2SAS_ADAPTER *ioc , u16 fault_code) | ||
| 309 | { | ||
| 310 | printk(MPT2SAS_ERR_FMT "fault_state(0x%04x)!\n", | ||
| 311 | ioc->name, fault_code); | ||
| 312 | } | ||
| 313 | |||
| 314 | /** | ||
| 315 | * mpt2sas_halt_firmware - halt's mpt controller firmware | ||
| 316 | * @ioc: per adapter object | ||
| 317 | * | ||
| 318 | * For debugging timeout related issues. Writing 0xCOFFEE00 | ||
| 319 | * to the doorbell register will halt controller firmware. With | ||
| 320 | * the purpose to stop both driver and firmware, the enduser can | ||
| 321 | * obtain a ring buffer from controller UART. | ||
| 322 | */ | ||
| 323 | void | ||
| 324 | mpt2sas_halt_firmware(struct MPT2SAS_ADAPTER *ioc) | ||
| 325 | { | ||
| 326 | u32 doorbell; | ||
| 327 | |||
| 328 | if (!ioc->fwfault_debug) | ||
| 329 | return; | ||
| 330 | |||
| 331 | dump_stack(); | ||
| 332 | |||
| 333 | doorbell = readl(&ioc->chip->Doorbell); | ||
| 334 | if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) | ||
| 335 | mpt2sas_base_fault_info(ioc , doorbell); | ||
| 336 | else { | ||
| 337 | writel(0xC0FFEE00, &ioc->chip->Doorbell); | ||
| 338 | printk(MPT2SAS_ERR_FMT "Firmware is halted due to command " | ||
| 339 | "timeout\n", ioc->name); | ||
| 340 | } | ||
| 341 | |||
| 342 | panic("panic in %s\n", __func__); | ||
| 343 | } | ||
| 344 | |||
| 345 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | ||
| 346 | /** | ||
| 347 | * _base_sas_ioc_info - verbose translation of the ioc status | ||
| 348 | * @ioc: per adapter object | ||
| 349 | * @mpi_reply: reply mf payload returned from firmware | ||
| 350 | * @request_hdr: request mf | ||
| 351 | * | ||
| 352 | * Return nothing. | ||
| 353 | */ | ||
| 354 | static void | ||
| 355 | _base_sas_ioc_info(struct MPT2SAS_ADAPTER *ioc, MPI2DefaultReply_t *mpi_reply, | ||
| 356 | MPI2RequestHeader_t *request_hdr) | ||
| 357 | { | ||
| 358 | u16 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & | ||
| 359 | MPI2_IOCSTATUS_MASK; | ||
| 360 | char *desc = NULL; | ||
| 361 | u16 frame_sz; | ||
| 362 | char *func_str = NULL; | ||
| 363 | |||
| 364 | /* SCSI_IO, RAID_PASS are handled from _scsih_scsi_ioc_info */ | ||
| 365 | if (request_hdr->Function == MPI2_FUNCTION_SCSI_IO_REQUEST || | ||
| 366 | request_hdr->Function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH || | ||
| 367 | request_hdr->Function == MPI2_FUNCTION_EVENT_NOTIFICATION) | ||
| 368 | return; | ||
| 369 | |||
| 370 | if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) | ||
| 371 | return; | ||
| 372 | |||
| 373 | switch (ioc_status) { | ||
| 374 | |||
| 375 | /**************************************************************************** | ||
| 376 | * Common IOCStatus values for all replies | ||
| 377 | ****************************************************************************/ | ||
| 378 | |||
| 379 | case MPI2_IOCSTATUS_INVALID_FUNCTION: | ||
| 380 | desc = "invalid function"; | ||
| 381 | break; | ||
| 382 | case MPI2_IOCSTATUS_BUSY: | ||
| 383 | desc = "busy"; | ||
| 384 | break; | ||
| 385 | case MPI2_IOCSTATUS_INVALID_SGL: | ||
| 386 | desc = "invalid sgl"; | ||
| 387 | break; | ||
| 388 | case MPI2_IOCSTATUS_INTERNAL_ERROR: | ||
| 389 | desc = "internal error"; | ||
| 390 | break; | ||
| 391 | case MPI2_IOCSTATUS_INVALID_VPID: | ||
| 392 | desc = "invalid vpid"; | ||
| 393 | break; | ||
| 394 | case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES: | ||
| 395 | desc = "insufficient resources"; | ||
| 396 | break; | ||
| 397 | case MPI2_IOCSTATUS_INVALID_FIELD: | ||
| 398 | desc = "invalid field"; | ||
| 399 | break; | ||
| 400 | case MPI2_IOCSTATUS_INVALID_STATE: | ||
| 401 | desc = "invalid state"; | ||
| 402 | break; | ||
| 403 | case MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED: | ||
| 404 | desc = "op state not supported"; | ||
| 405 | break; | ||
| 406 | |||
| 407 | /**************************************************************************** | ||
| 408 | * Config IOCStatus values | ||
| 409 | ****************************************************************************/ | ||
| 410 | |||
| 411 | case MPI2_IOCSTATUS_CONFIG_INVALID_ACTION: | ||
| 412 | desc = "config invalid action"; | ||
| 413 | break; | ||
| 414 | case MPI2_IOCSTATUS_CONFIG_INVALID_TYPE: | ||
| 415 | desc = "config invalid type"; | ||
| 416 | break; | ||
| 417 | case MPI2_IOCSTATUS_CONFIG_INVALID_PAGE: | ||
| 418 | desc = "config invalid page"; | ||
| 419 | break; | ||
| 420 | case MPI2_IOCSTATUS_CONFIG_INVALID_DATA: | ||
| 421 | desc = "config invalid data"; | ||
| 422 | break; | ||
| 423 | case MPI2_IOCSTATUS_CONFIG_NO_DEFAULTS: | ||
| 424 | desc = "config no defaults"; | ||
| 425 | break; | ||
| 426 | case MPI2_IOCSTATUS_CONFIG_CANT_COMMIT: | ||
| 427 | desc = "config cant commit"; | ||
| 428 | break; | ||
| 429 | |||
| 430 | /**************************************************************************** | ||
| 431 | * SCSI IO Reply | ||
| 432 | ****************************************************************************/ | ||
| 433 | |||
| 434 | case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR: | ||
| 435 | case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE: | ||
| 436 | case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE: | ||
| 437 | case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN: | ||
| 438 | case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN: | ||
| 439 | case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR: | ||
| 440 | case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR: | ||
| 441 | case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED: | ||
| 442 | case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: | ||
| 443 | case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED: | ||
| 444 | case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED: | ||
| 445 | case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED: | ||
| 446 | break; | ||
| 447 | |||
| 448 | /**************************************************************************** | ||
| 449 | * For use by SCSI Initiator and SCSI Target end-to-end data protection | ||
| 450 | ****************************************************************************/ | ||
| 451 | |||
| 452 | case MPI2_IOCSTATUS_EEDP_GUARD_ERROR: | ||
| 453 | desc = "eedp guard error"; | ||
| 454 | break; | ||
| 455 | case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR: | ||
| 456 | desc = "eedp ref tag error"; | ||
| 457 | break; | ||
| 458 | case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR: | ||
| 459 | desc = "eedp app tag error"; | ||
| 460 | break; | ||
| 461 | |||
| 462 | /**************************************************************************** | ||
| 463 | * SCSI Target values | ||
| 464 | ****************************************************************************/ | ||
| 465 | |||
| 466 | case MPI2_IOCSTATUS_TARGET_INVALID_IO_INDEX: | ||
| 467 | desc = "target invalid io index"; | ||
| 468 | break; | ||
| 469 | case MPI2_IOCSTATUS_TARGET_ABORTED: | ||
| 470 | desc = "target aborted"; | ||
| 471 | break; | ||
| 472 | case MPI2_IOCSTATUS_TARGET_NO_CONN_RETRYABLE: | ||
| 473 | desc = "target no conn retryable"; | ||
| 474 | break; | ||
| 475 | case MPI2_IOCSTATUS_TARGET_NO_CONNECTION: | ||
| 476 | desc = "target no connection"; | ||
| 477 | break; | ||
| 478 | case MPI2_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH: | ||
| 479 | desc = "target xfer count mismatch"; | ||
| 480 | break; | ||
| 481 | case MPI2_IOCSTATUS_TARGET_DATA_OFFSET_ERROR: | ||
| 482 | desc = "target data offset error"; | ||
| 483 | break; | ||
| 484 | case MPI2_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA: | ||
| 485 | desc = "target too much write data"; | ||
| 486 | break; | ||
| 487 | case MPI2_IOCSTATUS_TARGET_IU_TOO_SHORT: | ||
| 488 | desc = "target iu too short"; | ||
| 489 | break; | ||
| 490 | case MPI2_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT: | ||
| 491 | desc = "target ack nak timeout"; | ||
| 492 | break; | ||
| 493 | case MPI2_IOCSTATUS_TARGET_NAK_RECEIVED: | ||
| 494 | desc = "target nak received"; | ||
| 495 | break; | ||
| 496 | |||
| 497 | /**************************************************************************** | ||
| 498 | * Serial Attached SCSI values | ||
| 499 | ****************************************************************************/ | ||
| 500 | |||
| 501 | case MPI2_IOCSTATUS_SAS_SMP_REQUEST_FAILED: | ||
| 502 | desc = "smp request failed"; | ||
| 503 | break; | ||
| 504 | case MPI2_IOCSTATUS_SAS_SMP_DATA_OVERRUN: | ||
| 505 | desc = "smp data overrun"; | ||
| 506 | break; | ||
| 507 | |||
| 508 | /**************************************************************************** | ||
| 509 | * Diagnostic Buffer Post / Diagnostic Release values | ||
| 510 | ****************************************************************************/ | ||
| 511 | |||
| 512 | case MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED: | ||
| 513 | desc = "diagnostic released"; | ||
| 514 | break; | ||
| 515 | default: | ||
| 516 | break; | ||
| 517 | } | ||
| 518 | |||
| 519 | if (!desc) | ||
| 520 | return; | ||
| 521 | |||
| 522 | switch (request_hdr->Function) { | ||
| 523 | case MPI2_FUNCTION_CONFIG: | ||
| 524 | frame_sz = sizeof(Mpi2ConfigRequest_t) + ioc->sge_size; | ||
| 525 | func_str = "config_page"; | ||
| 526 | break; | ||
| 527 | case MPI2_FUNCTION_SCSI_TASK_MGMT: | ||
| 528 | frame_sz = sizeof(Mpi2SCSITaskManagementRequest_t); | ||
| 529 | func_str = "task_mgmt"; | ||
| 530 | break; | ||
| 531 | case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL: | ||
| 532 | frame_sz = sizeof(Mpi2SasIoUnitControlRequest_t); | ||
| 533 | func_str = "sas_iounit_ctl"; | ||
| 534 | break; | ||
| 535 | case MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR: | ||
| 536 | frame_sz = sizeof(Mpi2SepRequest_t); | ||
| 537 | func_str = "enclosure"; | ||
| 538 | break; | ||
| 539 | case MPI2_FUNCTION_IOC_INIT: | ||
| 540 | frame_sz = sizeof(Mpi2IOCInitRequest_t); | ||
| 541 | func_str = "ioc_init"; | ||
| 542 | break; | ||
| 543 | case MPI2_FUNCTION_PORT_ENABLE: | ||
| 544 | frame_sz = sizeof(Mpi2PortEnableRequest_t); | ||
| 545 | func_str = "port_enable"; | ||
| 546 | break; | ||
| 547 | case MPI2_FUNCTION_SMP_PASSTHROUGH: | ||
| 548 | frame_sz = sizeof(Mpi2SmpPassthroughRequest_t) + ioc->sge_size; | ||
| 549 | func_str = "smp_passthru"; | ||
| 550 | break; | ||
| 551 | default: | ||
| 552 | frame_sz = 32; | ||
| 553 | func_str = "unknown"; | ||
| 554 | break; | ||
| 555 | } | ||
| 556 | |||
| 557 | printk(MPT2SAS_WARN_FMT "ioc_status: %s(0x%04x), request(0x%p)," | ||
| 558 | " (%s)\n", ioc->name, desc, ioc_status, request_hdr, func_str); | ||
| 559 | |||
| 560 | _debug_dump_mf(request_hdr, frame_sz/4); | ||
| 561 | } | ||
| 562 | |||
| 563 | /** | ||
| 564 | * _base_display_event_data - verbose translation of firmware asyn events | ||
| 565 | * @ioc: per adapter object | ||
| 566 | * @mpi_reply: reply mf payload returned from firmware | ||
| 567 | * | ||
| 568 | * Return nothing. | ||
| 569 | */ | ||
| 570 | static void | ||
| 571 | _base_display_event_data(struct MPT2SAS_ADAPTER *ioc, | ||
| 572 | Mpi2EventNotificationReply_t *mpi_reply) | ||
| 573 | { | ||
| 574 | char *desc = NULL; | ||
| 575 | u16 event; | ||
| 576 | |||
| 577 | if (!(ioc->logging_level & MPT_DEBUG_EVENTS)) | ||
| 578 | return; | ||
| 579 | |||
| 580 | event = le16_to_cpu(mpi_reply->Event); | ||
| 581 | |||
| 582 | switch (event) { | ||
| 583 | case MPI2_EVENT_LOG_DATA: | ||
| 584 | desc = "Log Data"; | ||
| 585 | break; | ||
| 586 | case MPI2_EVENT_STATE_CHANGE: | ||
| 587 | desc = "Status Change"; | ||
| 588 | break; | ||
| 589 | case MPI2_EVENT_HARD_RESET_RECEIVED: | ||
| 590 | desc = "Hard Reset Received"; | ||
| 591 | break; | ||
| 592 | case MPI2_EVENT_EVENT_CHANGE: | ||
| 593 | desc = "Event Change"; | ||
| 594 | break; | ||
| 595 | case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE: | ||
| 596 | desc = "Device Status Change"; | ||
| 597 | break; | ||
| 598 | case MPI2_EVENT_IR_OPERATION_STATUS: | ||
| 599 | if (!ioc->hide_ir_msg) | ||
| 600 | desc = "IR Operation Status"; | ||
| 601 | break; | ||
| 602 | case MPI2_EVENT_SAS_DISCOVERY: | ||
| 603 | { | ||
| 604 | Mpi2EventDataSasDiscovery_t *event_data = | ||
| 605 | (Mpi2EventDataSasDiscovery_t *)mpi_reply->EventData; | ||
| 606 | printk(MPT2SAS_INFO_FMT "Discovery: (%s)", ioc->name, | ||
| 607 | (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED) ? | ||
| 608 | "start" : "stop"); | ||
| 609 | if (event_data->DiscoveryStatus) | ||
| 610 | printk("discovery_status(0x%08x)", | ||
| 611 | le32_to_cpu(event_data->DiscoveryStatus)); | ||
| 612 | printk("\n"); | ||
| 613 | return; | ||
| 614 | } | ||
| 615 | case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE: | ||
| 616 | desc = "SAS Broadcast Primitive"; | ||
| 617 | break; | ||
| 618 | case MPI2_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE: | ||
| 619 | desc = "SAS Init Device Status Change"; | ||
| 620 | break; | ||
| 621 | case MPI2_EVENT_SAS_INIT_TABLE_OVERFLOW: | ||
| 622 | desc = "SAS Init Table Overflow"; | ||
| 623 | break; | ||
| 624 | case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST: | ||
| 625 | desc = "SAS Topology Change List"; | ||
| 626 | break; | ||
| 627 | case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE: | ||
| 628 | desc = "SAS Enclosure Device Status Change"; | ||
| 629 | break; | ||
| 630 | case MPI2_EVENT_IR_VOLUME: | ||
| 631 | if (!ioc->hide_ir_msg) | ||
| 632 | desc = "IR Volume"; | ||
| 633 | break; | ||
| 634 | case MPI2_EVENT_IR_PHYSICAL_DISK: | ||
| 635 | if (!ioc->hide_ir_msg) | ||
| 636 | desc = "IR Physical Disk"; | ||
| 637 | break; | ||
| 638 | case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST: | ||
| 639 | if (!ioc->hide_ir_msg) | ||
| 640 | desc = "IR Configuration Change List"; | ||
| 641 | break; | ||
| 642 | case MPI2_EVENT_LOG_ENTRY_ADDED: | ||
| 643 | if (!ioc->hide_ir_msg) | ||
| 644 | desc = "Log Entry Added"; | ||
| 645 | break; | ||
| 646 | case MPI2_EVENT_TEMP_THRESHOLD: | ||
| 647 | desc = "Temperature Threshold"; | ||
| 648 | break; | ||
| 649 | } | ||
| 650 | |||
| 651 | if (!desc) | ||
| 652 | return; | ||
| 653 | |||
| 654 | printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, desc); | ||
| 655 | } | ||
| 656 | #endif | ||
| 657 | |||
| 658 | /** | ||
| 659 | * _base_sas_log_info - verbose translation of firmware log info | ||
| 660 | * @ioc: per adapter object | ||
| 661 | * @log_info: log info | ||
| 662 | * | ||
| 663 | * Return nothing. | ||
| 664 | */ | ||
| 665 | static void | ||
| 666 | _base_sas_log_info(struct MPT2SAS_ADAPTER *ioc , u32 log_info) | ||
| 667 | { | ||
| 668 | union loginfo_type { | ||
| 669 | u32 loginfo; | ||
| 670 | struct { | ||
| 671 | u32 subcode:16; | ||
| 672 | u32 code:8; | ||
| 673 | u32 originator:4; | ||
| 674 | u32 bus_type:4; | ||
| 675 | } dw; | ||
| 676 | }; | ||
| 677 | union loginfo_type sas_loginfo; | ||
| 678 | char *originator_str = NULL; | ||
| 679 | |||
| 680 | sas_loginfo.loginfo = log_info; | ||
| 681 | if (sas_loginfo.dw.bus_type != 3 /*SAS*/) | ||
| 682 | return; | ||
| 683 | |||
| 684 | /* each nexus loss loginfo */ | ||
| 685 | if (log_info == 0x31170000) | ||
| 686 | return; | ||
| 687 | |||
| 688 | /* eat the loginfos associated with task aborts */ | ||
| 689 | if (ioc->ignore_loginfos && (log_info == 0x30050000 || log_info == | ||
| 690 | 0x31140000 || log_info == 0x31130000)) | ||
| 691 | return; | ||
| 692 | |||
| 693 | switch (sas_loginfo.dw.originator) { | ||
| 694 | case 0: | ||
| 695 | originator_str = "IOP"; | ||
| 696 | break; | ||
| 697 | case 1: | ||
| 698 | originator_str = "PL"; | ||
| 699 | break; | ||
| 700 | case 2: | ||
| 701 | if (!ioc->hide_ir_msg) | ||
| 702 | originator_str = "IR"; | ||
| 703 | else | ||
| 704 | originator_str = "WarpDrive"; | ||
| 705 | break; | ||
| 706 | } | ||
| 707 | |||
| 708 | printk(MPT2SAS_WARN_FMT "log_info(0x%08x): originator(%s), " | ||
| 709 | "code(0x%02x), sub_code(0x%04x)\n", ioc->name, log_info, | ||
| 710 | originator_str, sas_loginfo.dw.code, | ||
| 711 | sas_loginfo.dw.subcode); | ||
| 712 | } | ||
| 713 | |||
| 714 | /** | ||
| 715 | * _base_display_reply_info - | ||
| 716 | * @ioc: per adapter object | ||
| 717 | * @smid: system request message index | ||
| 718 | * @msix_index: MSIX table index supplied by the OS | ||
| 719 | * @reply: reply message frame(lower 32bit addr) | ||
| 720 | * | ||
| 721 | * Return nothing. | ||
| 722 | */ | ||
| 723 | static void | ||
| 724 | _base_display_reply_info(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | ||
| 725 | u32 reply) | ||
| 726 | { | ||
| 727 | MPI2DefaultReply_t *mpi_reply; | ||
| 728 | u16 ioc_status; | ||
| 729 | |||
| 730 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | ||
| 731 | if (unlikely(!mpi_reply)) { | ||
| 732 | printk(MPT2SAS_ERR_FMT "mpi_reply not valid at %s:%d/%s()!\n", | ||
| 733 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 734 | return; | ||
| 735 | } | ||
| 736 | ioc_status = le16_to_cpu(mpi_reply->IOCStatus); | ||
| 737 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | ||
| 738 | if ((ioc_status & MPI2_IOCSTATUS_MASK) && | ||
| 739 | (ioc->logging_level & MPT_DEBUG_REPLY)) { | ||
| 740 | _base_sas_ioc_info(ioc , mpi_reply, | ||
| 741 | mpt2sas_base_get_msg_frame(ioc, smid)); | ||
| 742 | } | ||
| 743 | #endif | ||
| 744 | if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) | ||
| 745 | _base_sas_log_info(ioc, le32_to_cpu(mpi_reply->IOCLogInfo)); | ||
| 746 | } | ||
| 747 | |||
| 748 | /** | ||
| 749 | * mpt2sas_base_done - base internal command completion routine | ||
| 750 | * @ioc: per adapter object | ||
| 751 | * @smid: system request message index | ||
| 752 | * @msix_index: MSIX table index supplied by the OS | ||
| 753 | * @reply: reply message frame(lower 32bit addr) | ||
| 754 | * | ||
| 755 | * Return 1 meaning mf should be freed from _base_interrupt | ||
| 756 | * 0 means the mf is freed from this function. | ||
| 757 | */ | ||
| 758 | u8 | ||
| 759 | mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | ||
| 760 | u32 reply) | ||
| 761 | { | ||
| 762 | MPI2DefaultReply_t *mpi_reply; | ||
| 763 | |||
| 764 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | ||
| 765 | if (mpi_reply && mpi_reply->Function == MPI2_FUNCTION_EVENT_ACK) | ||
| 766 | return 1; | ||
| 767 | |||
| 768 | if (ioc->base_cmds.status == MPT2_CMD_NOT_USED) | ||
| 769 | return 1; | ||
| 770 | |||
| 771 | ioc->base_cmds.status |= MPT2_CMD_COMPLETE; | ||
| 772 | if (mpi_reply) { | ||
| 773 | ioc->base_cmds.status |= MPT2_CMD_REPLY_VALID; | ||
| 774 | memcpy(ioc->base_cmds.reply, mpi_reply, mpi_reply->MsgLength*4); | ||
| 775 | } | ||
| 776 | ioc->base_cmds.status &= ~MPT2_CMD_PENDING; | ||
| 777 | |||
| 778 | complete(&ioc->base_cmds.done); | ||
| 779 | return 1; | ||
| 780 | } | ||
| 781 | |||
| 782 | /** | ||
| 783 | * _base_async_event - main callback handler for firmware asyn events | ||
| 784 | * @ioc: per adapter object | ||
| 785 | * @msix_index: MSIX table index supplied by the OS | ||
| 786 | * @reply: reply message frame(lower 32bit addr) | ||
| 787 | * | ||
| 788 | * Returns void. | ||
| 789 | */ | ||
| 790 | static void | ||
| 791 | _base_async_event(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, u32 reply) | ||
| 792 | { | ||
| 793 | Mpi2EventNotificationReply_t *mpi_reply; | ||
| 794 | Mpi2EventAckRequest_t *ack_request; | ||
| 795 | u16 smid; | ||
| 796 | |||
| 797 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | ||
| 798 | if (!mpi_reply) | ||
| 799 | return; | ||
| 800 | if (mpi_reply->Function != MPI2_FUNCTION_EVENT_NOTIFICATION) | ||
| 801 | return; | ||
| 802 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | ||
| 803 | _base_display_event_data(ioc, mpi_reply); | ||
| 804 | #endif | ||
| 805 | if (!(mpi_reply->AckRequired & MPI2_EVENT_NOTIFICATION_ACK_REQUIRED)) | ||
| 806 | goto out; | ||
| 807 | smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx); | ||
| 808 | if (!smid) { | ||
| 809 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", | ||
| 810 | ioc->name, __func__); | ||
| 811 | goto out; | ||
| 812 | } | ||
| 813 | |||
| 814 | ack_request = mpt2sas_base_get_msg_frame(ioc, smid); | ||
| 815 | memset(ack_request, 0, sizeof(Mpi2EventAckRequest_t)); | ||
| 816 | ack_request->Function = MPI2_FUNCTION_EVENT_ACK; | ||
| 817 | ack_request->Event = mpi_reply->Event; | ||
| 818 | ack_request->EventContext = mpi_reply->EventContext; | ||
| 819 | ack_request->VF_ID = 0; /* TODO */ | ||
| 820 | ack_request->VP_ID = 0; | ||
| 821 | mpt2sas_base_put_smid_default(ioc, smid); | ||
| 822 | |||
| 823 | out: | ||
| 824 | |||
| 825 | /* scsih callback handler */ | ||
| 826 | mpt2sas_scsih_event_callback(ioc, msix_index, reply); | ||
| 827 | |||
| 828 | /* ctl callback handler */ | ||
| 829 | mpt2sas_ctl_event_callback(ioc, msix_index, reply); | ||
| 830 | |||
| 831 | return; | ||
| 832 | } | ||
| 833 | |||
| 834 | /** | ||
| 835 | * _base_get_cb_idx - obtain the callback index | ||
| 836 | * @ioc: per adapter object | ||
| 837 | * @smid: system request message index | ||
| 838 | * | ||
| 839 | * Return callback index. | ||
| 840 | */ | ||
| 841 | static u8 | ||
| 842 | _base_get_cb_idx(struct MPT2SAS_ADAPTER *ioc, u16 smid) | ||
| 843 | { | ||
| 844 | int i; | ||
| 845 | u8 cb_idx; | ||
| 846 | |||
| 847 | if (smid < ioc->hi_priority_smid) { | ||
| 848 | i = smid - 1; | ||
| 849 | cb_idx = ioc->scsi_lookup[i].cb_idx; | ||
| 850 | } else if (smid < ioc->internal_smid) { | ||
| 851 | i = smid - ioc->hi_priority_smid; | ||
| 852 | cb_idx = ioc->hpr_lookup[i].cb_idx; | ||
| 853 | } else if (smid <= ioc->hba_queue_depth) { | ||
| 854 | i = smid - ioc->internal_smid; | ||
| 855 | cb_idx = ioc->internal_lookup[i].cb_idx; | ||
| 856 | } else | ||
| 857 | cb_idx = 0xFF; | ||
| 858 | return cb_idx; | ||
| 859 | } | ||
| 860 | |||
| 861 | /** | ||
| 862 | * _base_mask_interrupts - disable interrupts | ||
| 863 | * @ioc: per adapter object | ||
| 864 | * | ||
| 865 | * Disabling ResetIRQ, Reply and Doorbell Interrupts | ||
| 866 | * | ||
| 867 | * Return nothing. | ||
| 868 | */ | ||
| 869 | static void | ||
| 870 | _base_mask_interrupts(struct MPT2SAS_ADAPTER *ioc) | ||
| 871 | { | ||
| 872 | u32 him_register; | ||
| 873 | |||
| 874 | ioc->mask_interrupts = 1; | ||
| 875 | him_register = readl(&ioc->chip->HostInterruptMask); | ||
| 876 | him_register |= MPI2_HIM_DIM + MPI2_HIM_RIM + MPI2_HIM_RESET_IRQ_MASK; | ||
| 877 | writel(him_register, &ioc->chip->HostInterruptMask); | ||
| 878 | readl(&ioc->chip->HostInterruptMask); | ||
| 879 | } | ||
| 880 | |||
| 881 | /** | ||
| 882 | * _base_unmask_interrupts - enable interrupts | ||
| 883 | * @ioc: per adapter object | ||
| 884 | * | ||
| 885 | * Enabling only Reply Interrupts | ||
| 886 | * | ||
| 887 | * Return nothing. | ||
| 888 | */ | ||
| 889 | static void | ||
| 890 | _base_unmask_interrupts(struct MPT2SAS_ADAPTER *ioc) | ||
| 891 | { | ||
| 892 | u32 him_register; | ||
| 893 | |||
| 894 | him_register = readl(&ioc->chip->HostInterruptMask); | ||
| 895 | him_register &= ~MPI2_HIM_RIM; | ||
| 896 | writel(him_register, &ioc->chip->HostInterruptMask); | ||
| 897 | ioc->mask_interrupts = 0; | ||
| 898 | } | ||
| 899 | |||
| 900 | union reply_descriptor { | ||
| 901 | u64 word; | ||
| 902 | struct { | ||
| 903 | u32 low; | ||
| 904 | u32 high; | ||
| 905 | } u; | ||
| 906 | }; | ||
| 907 | |||
| 908 | /** | ||
| 909 | * _base_interrupt - MPT adapter (IOC) specific interrupt handler. | ||
| 910 | * @irq: irq number (not used) | ||
| 911 | * @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure | ||
| 912 | * @r: pt_regs pointer (not used) | ||
| 913 | * | ||
| 914 | * Return IRQ_HANDLE if processed, else IRQ_NONE. | ||
| 915 | */ | ||
| 916 | static irqreturn_t | ||
| 917 | _base_interrupt(int irq, void *bus_id) | ||
| 918 | { | ||
| 919 | struct adapter_reply_queue *reply_q = bus_id; | ||
| 920 | union reply_descriptor rd; | ||
| 921 | u32 completed_cmds; | ||
| 922 | u8 request_desript_type; | ||
| 923 | u16 smid; | ||
| 924 | u8 cb_idx; | ||
| 925 | u32 reply; | ||
| 926 | u8 msix_index = reply_q->msix_index; | ||
| 927 | struct MPT2SAS_ADAPTER *ioc = reply_q->ioc; | ||
| 928 | Mpi2ReplyDescriptorsUnion_t *rpf; | ||
| 929 | u8 rc; | ||
| 930 | |||
| 931 | if (ioc->mask_interrupts) | ||
| 932 | return IRQ_NONE; | ||
| 933 | |||
| 934 | if (!atomic_add_unless(&reply_q->busy, 1, 1)) | ||
| 935 | return IRQ_NONE; | ||
| 936 | |||
| 937 | rpf = &reply_q->reply_post_free[reply_q->reply_post_host_index]; | ||
| 938 | request_desript_type = rpf->Default.ReplyFlags | ||
| 939 | & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK; | ||
| 940 | if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) { | ||
| 941 | atomic_dec(&reply_q->busy); | ||
| 942 | return IRQ_NONE; | ||
| 943 | } | ||
| 944 | |||
| 945 | completed_cmds = 0; | ||
| 946 | cb_idx = 0xFF; | ||
| 947 | do { | ||
| 948 | rd.word = le64_to_cpu(rpf->Words); | ||
| 949 | if (rd.u.low == UINT_MAX || rd.u.high == UINT_MAX) | ||
| 950 | goto out; | ||
| 951 | reply = 0; | ||
| 952 | smid = le16_to_cpu(rpf->Default.DescriptorTypeDependent1); | ||
| 953 | if (request_desript_type == | ||
| 954 | MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) { | ||
| 955 | reply = le32_to_cpu | ||
| 956 | (rpf->AddressReply.ReplyFrameAddress); | ||
| 957 | if (reply > ioc->reply_dma_max_address || | ||
| 958 | reply < ioc->reply_dma_min_address) | ||
| 959 | reply = 0; | ||
| 960 | } else if (request_desript_type == | ||
| 961 | MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER) | ||
| 962 | goto next; | ||
| 963 | else if (request_desript_type == | ||
| 964 | MPI2_RPY_DESCRIPT_FLAGS_TARGETASSIST_SUCCESS) | ||
| 965 | goto next; | ||
| 966 | if (smid) { | ||
| 967 | cb_idx = _base_get_cb_idx(ioc, smid); | ||
| 968 | if ((likely(cb_idx < MPT_MAX_CALLBACKS)) | ||
| 969 | && (likely(mpt_callbacks[cb_idx] != NULL))) { | ||
| 970 | rc = mpt_callbacks[cb_idx](ioc, smid, | ||
| 971 | msix_index, reply); | ||
| 972 | if (reply) | ||
| 973 | _base_display_reply_info(ioc, smid, | ||
| 974 | msix_index, reply); | ||
| 975 | if (rc) | ||
| 976 | mpt2sas_base_free_smid(ioc, smid); | ||
| 977 | } | ||
| 978 | } | ||
| 979 | if (!smid) | ||
| 980 | _base_async_event(ioc, msix_index, reply); | ||
| 981 | |||
| 982 | /* reply free queue handling */ | ||
| 983 | if (reply) { | ||
| 984 | ioc->reply_free_host_index = | ||
| 985 | (ioc->reply_free_host_index == | ||
| 986 | (ioc->reply_free_queue_depth - 1)) ? | ||
| 987 | 0 : ioc->reply_free_host_index + 1; | ||
| 988 | ioc->reply_free[ioc->reply_free_host_index] = | ||
| 989 | cpu_to_le32(reply); | ||
| 990 | wmb(); | ||
| 991 | writel(ioc->reply_free_host_index, | ||
| 992 | &ioc->chip->ReplyFreeHostIndex); | ||
| 993 | } | ||
| 994 | |||
| 995 | next: | ||
| 996 | |||
| 997 | rpf->Words = cpu_to_le64(ULLONG_MAX); | ||
| 998 | reply_q->reply_post_host_index = | ||
| 999 | (reply_q->reply_post_host_index == | ||
| 1000 | (ioc->reply_post_queue_depth - 1)) ? 0 : | ||
| 1001 | reply_q->reply_post_host_index + 1; | ||
| 1002 | request_desript_type = | ||
| 1003 | reply_q->reply_post_free[reply_q->reply_post_host_index]. | ||
| 1004 | Default.ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK; | ||
| 1005 | completed_cmds++; | ||
| 1006 | if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) | ||
| 1007 | goto out; | ||
| 1008 | if (!reply_q->reply_post_host_index) | ||
| 1009 | rpf = reply_q->reply_post_free; | ||
| 1010 | else | ||
| 1011 | rpf++; | ||
| 1012 | } while (1); | ||
| 1013 | |||
| 1014 | out: | ||
| 1015 | |||
| 1016 | if (!completed_cmds) { | ||
| 1017 | atomic_dec(&reply_q->busy); | ||
| 1018 | return IRQ_NONE; | ||
| 1019 | } | ||
| 1020 | wmb(); | ||
| 1021 | if (ioc->is_warpdrive) { | ||
| 1022 | writel(reply_q->reply_post_host_index, | ||
| 1023 | ioc->reply_post_host_index[msix_index]); | ||
| 1024 | atomic_dec(&reply_q->busy); | ||
| 1025 | return IRQ_HANDLED; | ||
| 1026 | } | ||
| 1027 | writel(reply_q->reply_post_host_index | (msix_index << | ||
| 1028 | MPI2_RPHI_MSIX_INDEX_SHIFT), &ioc->chip->ReplyPostHostIndex); | ||
| 1029 | atomic_dec(&reply_q->busy); | ||
| 1030 | return IRQ_HANDLED; | ||
| 1031 | } | ||
| 1032 | |||
| 1033 | /** | ||
| 1034 | * _base_is_controller_msix_enabled - is controller support muli-reply queues | ||
| 1035 | * @ioc: per adapter object | ||
| 1036 | * | ||
| 1037 | */ | ||
| 1038 | static inline int | ||
| 1039 | _base_is_controller_msix_enabled(struct MPT2SAS_ADAPTER *ioc) | ||
| 1040 | { | ||
| 1041 | return (ioc->facts.IOCCapabilities & | ||
| 1042 | MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX) && ioc->msix_enable; | ||
| 1043 | } | ||
| 1044 | |||
| 1045 | /** | ||
| 1046 | * mpt2sas_base_flush_reply_queues - flushing the MSIX reply queues | ||
| 1047 | * @ioc: per adapter object | ||
| 1048 | * Context: ISR conext | ||
| 1049 | * | ||
| 1050 | * Called when a Task Management request has completed. We want | ||
| 1051 | * to flush the other reply queues so all the outstanding IO has been | ||
| 1052 | * completed back to OS before we process the TM completetion. | ||
| 1053 | * | ||
| 1054 | * Return nothing. | ||
| 1055 | */ | ||
| 1056 | void | ||
| 1057 | mpt2sas_base_flush_reply_queues(struct MPT2SAS_ADAPTER *ioc) | ||
| 1058 | { | ||
| 1059 | struct adapter_reply_queue *reply_q; | ||
| 1060 | |||
| 1061 | /* If MSIX capability is turned off | ||
| 1062 | * then multi-queues are not enabled | ||
| 1063 | */ | ||
| 1064 | if (!_base_is_controller_msix_enabled(ioc)) | ||
| 1065 | return; | ||
| 1066 | |||
| 1067 | list_for_each_entry(reply_q, &ioc->reply_queue_list, list) { | ||
| 1068 | if (ioc->shost_recovery) | ||
| 1069 | return; | ||
| 1070 | /* TMs are on msix_index == 0 */ | ||
| 1071 | if (reply_q->msix_index == 0) | ||
| 1072 | continue; | ||
| 1073 | _base_interrupt(reply_q->vector, (void *)reply_q); | ||
| 1074 | } | ||
| 1075 | } | ||
| 1076 | |||
| 1077 | /** | ||
| 1078 | * mpt2sas_base_release_callback_handler - clear interrupt callback handler | ||
| 1079 | * @cb_idx: callback index | ||
| 1080 | * | ||
| 1081 | * Return nothing. | ||
| 1082 | */ | ||
| 1083 | void | ||
| 1084 | mpt2sas_base_release_callback_handler(u8 cb_idx) | ||
| 1085 | { | ||
| 1086 | mpt_callbacks[cb_idx] = NULL; | ||
| 1087 | } | ||
| 1088 | |||
| 1089 | /** | ||
| 1090 | * mpt2sas_base_register_callback_handler - obtain index for the interrupt callback handler | ||
| 1091 | * @cb_func: callback function | ||
| 1092 | * | ||
| 1093 | * Returns cb_func. | ||
| 1094 | */ | ||
| 1095 | u8 | ||
| 1096 | mpt2sas_base_register_callback_handler(MPT_CALLBACK cb_func) | ||
| 1097 | { | ||
| 1098 | u8 cb_idx; | ||
| 1099 | |||
| 1100 | for (cb_idx = MPT_MAX_CALLBACKS-1; cb_idx; cb_idx--) | ||
| 1101 | if (mpt_callbacks[cb_idx] == NULL) | ||
| 1102 | break; | ||
| 1103 | |||
| 1104 | mpt_callbacks[cb_idx] = cb_func; | ||
| 1105 | return cb_idx; | ||
| 1106 | } | ||
| 1107 | |||
| 1108 | /** | ||
| 1109 | * mpt2sas_base_initialize_callback_handler - initialize the interrupt callback handler | ||
| 1110 | * | ||
| 1111 | * Return nothing. | ||
| 1112 | */ | ||
| 1113 | void | ||
| 1114 | mpt2sas_base_initialize_callback_handler(void) | ||
| 1115 | { | ||
| 1116 | u8 cb_idx; | ||
| 1117 | |||
| 1118 | for (cb_idx = 0; cb_idx < MPT_MAX_CALLBACKS; cb_idx++) | ||
| 1119 | mpt2sas_base_release_callback_handler(cb_idx); | ||
| 1120 | } | ||
| 1121 | |||
| 1122 | /** | ||
| 1123 | * mpt2sas_base_build_zero_len_sge - build zero length sg entry | ||
| 1124 | * @ioc: per adapter object | ||
| 1125 | * @paddr: virtual address for SGE | ||
| 1126 | * | ||
| 1127 | * Create a zero length scatter gather entry to insure the IOCs hardware has | ||
| 1128 | * something to use if the target device goes brain dead and tries | ||
| 1129 | * to send data even when none is asked for. | ||
| 1130 | * | ||
| 1131 | * Return nothing. | ||
| 1132 | */ | ||
| 1133 | void | ||
| 1134 | mpt2sas_base_build_zero_len_sge(struct MPT2SAS_ADAPTER *ioc, void *paddr) | ||
| 1135 | { | ||
| 1136 | u32 flags_length = (u32)((MPI2_SGE_FLAGS_LAST_ELEMENT | | ||
| 1137 | MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_END_OF_LIST | | ||
| 1138 | MPI2_SGE_FLAGS_SIMPLE_ELEMENT) << | ||
| 1139 | MPI2_SGE_FLAGS_SHIFT); | ||
| 1140 | ioc->base_add_sg_single(paddr, flags_length, -1); | ||
| 1141 | } | ||
| 1142 | |||
| 1143 | /** | ||
| 1144 | * _base_add_sg_single_32 - Place a simple 32 bit SGE at address pAddr. | ||
| 1145 | * @paddr: virtual address for SGE | ||
| 1146 | * @flags_length: SGE flags and data transfer length | ||
| 1147 | * @dma_addr: Physical address | ||
| 1148 | * | ||
| 1149 | * Return nothing. | ||
| 1150 | */ | ||
| 1151 | static void | ||
| 1152 | _base_add_sg_single_32(void *paddr, u32 flags_length, dma_addr_t dma_addr) | ||
| 1153 | { | ||
| 1154 | Mpi2SGESimple32_t *sgel = paddr; | ||
| 1155 | |||
| 1156 | flags_length |= (MPI2_SGE_FLAGS_32_BIT_ADDRESSING | | ||
| 1157 | MPI2_SGE_FLAGS_SYSTEM_ADDRESS) << MPI2_SGE_FLAGS_SHIFT; | ||
| 1158 | sgel->FlagsLength = cpu_to_le32(flags_length); | ||
| 1159 | sgel->Address = cpu_to_le32(dma_addr); | ||
| 1160 | } | ||
| 1161 | |||
| 1162 | |||
| 1163 | /** | ||
| 1164 | * _base_add_sg_single_64 - Place a simple 64 bit SGE at address pAddr. | ||
| 1165 | * @paddr: virtual address for SGE | ||
| 1166 | * @flags_length: SGE flags and data transfer length | ||
| 1167 | * @dma_addr: Physical address | ||
| 1168 | * | ||
| 1169 | * Return nothing. | ||
| 1170 | */ | ||
| 1171 | static void | ||
| 1172 | _base_add_sg_single_64(void *paddr, u32 flags_length, dma_addr_t dma_addr) | ||
| 1173 | { | ||
| 1174 | Mpi2SGESimple64_t *sgel = paddr; | ||
| 1175 | |||
| 1176 | flags_length |= (MPI2_SGE_FLAGS_64_BIT_ADDRESSING | | ||
| 1177 | MPI2_SGE_FLAGS_SYSTEM_ADDRESS) << MPI2_SGE_FLAGS_SHIFT; | ||
| 1178 | sgel->FlagsLength = cpu_to_le32(flags_length); | ||
| 1179 | sgel->Address = cpu_to_le64(dma_addr); | ||
| 1180 | } | ||
| 1181 | |||
| 1182 | #define convert_to_kb(x) ((x) << (PAGE_SHIFT - 10)) | ||
| 1183 | |||
| 1184 | /** | ||
| 1185 | * _base_config_dma_addressing - set dma addressing | ||
| 1186 | * @ioc: per adapter object | ||
| 1187 | * @pdev: PCI device struct | ||
| 1188 | * | ||
| 1189 | * Returns 0 for success, non-zero for failure. | ||
| 1190 | */ | ||
| 1191 | static int | ||
| 1192 | _base_config_dma_addressing(struct MPT2SAS_ADAPTER *ioc, struct pci_dev *pdev) | ||
| 1193 | { | ||
| 1194 | struct sysinfo s; | ||
| 1195 | u64 consistent_dma_mask; | ||
| 1196 | |||
| 1197 | if (ioc->dma_mask) | ||
| 1198 | consistent_dma_mask = DMA_BIT_MASK(64); | ||
| 1199 | else | ||
| 1200 | consistent_dma_mask = DMA_BIT_MASK(32); | ||
| 1201 | |||
| 1202 | if (sizeof(dma_addr_t) > 4) { | ||
| 1203 | const uint64_t required_mask = | ||
| 1204 | dma_get_required_mask(&pdev->dev); | ||
| 1205 | if ((required_mask > DMA_BIT_MASK(32)) && | ||
| 1206 | !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && | ||
| 1207 | !pci_set_consistent_dma_mask(pdev, consistent_dma_mask)) { | ||
| 1208 | ioc->base_add_sg_single = &_base_add_sg_single_64; | ||
| 1209 | ioc->sge_size = sizeof(Mpi2SGESimple64_t); | ||
| 1210 | ioc->dma_mask = 64; | ||
| 1211 | goto out; | ||
| 1212 | } | ||
| 1213 | } | ||
| 1214 | |||
| 1215 | if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) | ||
| 1216 | && !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) { | ||
| 1217 | ioc->base_add_sg_single = &_base_add_sg_single_32; | ||
| 1218 | ioc->sge_size = sizeof(Mpi2SGESimple32_t); | ||
| 1219 | ioc->dma_mask = 32; | ||
| 1220 | } else | ||
| 1221 | return -ENODEV; | ||
| 1222 | |||
| 1223 | out: | ||
| 1224 | si_meminfo(&s); | ||
| 1225 | printk(MPT2SAS_INFO_FMT | ||
| 1226 | "%d BIT PCI BUS DMA ADDRESSING SUPPORTED, total mem (%ld kB)\n", | ||
| 1227 | ioc->name, ioc->dma_mask, convert_to_kb(s.totalram)); | ||
| 1228 | |||
| 1229 | return 0; | ||
| 1230 | } | ||
| 1231 | |||
| 1232 | static int | ||
| 1233 | _base_change_consistent_dma_mask(struct MPT2SAS_ADAPTER *ioc, | ||
| 1234 | struct pci_dev *pdev) | ||
| 1235 | { | ||
| 1236 | if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) { | ||
| 1237 | if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) | ||
| 1238 | return -ENODEV; | ||
| 1239 | } | ||
| 1240 | return 0; | ||
| 1241 | } | ||
| 1242 | /** | ||
| 1243 | * _base_check_enable_msix - checks MSIX capabable. | ||
| 1244 | * @ioc: per adapter object | ||
| 1245 | * | ||
| 1246 | * Check to see if card is capable of MSIX, and set number | ||
| 1247 | * of available msix vectors | ||
| 1248 | */ | ||
| 1249 | static int | ||
| 1250 | _base_check_enable_msix(struct MPT2SAS_ADAPTER *ioc) | ||
| 1251 | { | ||
| 1252 | int base; | ||
| 1253 | u16 message_control; | ||
| 1254 | |||
| 1255 | |||
| 1256 | /* Check whether controller SAS2008 B0 controller, | ||
| 1257 | if it is SAS2008 B0 controller use IO-APIC instead of MSIX */ | ||
| 1258 | if (ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2008 && | ||
| 1259 | ioc->pdev->revision == 0x01) { | ||
| 1260 | return -EINVAL; | ||
| 1261 | } | ||
| 1262 | |||
| 1263 | base = pci_find_capability(ioc->pdev, PCI_CAP_ID_MSIX); | ||
| 1264 | if (!base) { | ||
| 1265 | dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "msix not " | ||
| 1266 | "supported\n", ioc->name)); | ||
| 1267 | return -EINVAL; | ||
| 1268 | } | ||
| 1269 | |||
| 1270 | /* get msix vector count */ | ||
| 1271 | /* NUMA_IO not supported for older controllers */ | ||
| 1272 | if (ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2004 || | ||
| 1273 | ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2008 || | ||
| 1274 | ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2108_1 || | ||
| 1275 | ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2108_2 || | ||
| 1276 | ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2108_3 || | ||
| 1277 | ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2116_1 || | ||
| 1278 | ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2116_2) | ||
| 1279 | ioc->msix_vector_count = 1; | ||
| 1280 | else { | ||
| 1281 | pci_read_config_word(ioc->pdev, base + 2, &message_control); | ||
| 1282 | ioc->msix_vector_count = (message_control & 0x3FF) + 1; | ||
| 1283 | } | ||
| 1284 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "msix is supported, " | ||
| 1285 | "vector_count(%d)\n", ioc->name, ioc->msix_vector_count)); | ||
| 1286 | |||
| 1287 | return 0; | ||
| 1288 | } | ||
| 1289 | |||
| 1290 | /** | ||
| 1291 | * _base_free_irq - free irq | ||
| 1292 | * @ioc: per adapter object | ||
| 1293 | * | ||
| 1294 | * Freeing respective reply_queue from the list. | ||
| 1295 | */ | ||
| 1296 | static void | ||
| 1297 | _base_free_irq(struct MPT2SAS_ADAPTER *ioc) | ||
| 1298 | { | ||
| 1299 | struct adapter_reply_queue *reply_q, *next; | ||
| 1300 | |||
| 1301 | if (list_empty(&ioc->reply_queue_list)) | ||
| 1302 | return; | ||
| 1303 | |||
| 1304 | list_for_each_entry_safe(reply_q, next, &ioc->reply_queue_list, list) { | ||
| 1305 | list_del(&reply_q->list); | ||
| 1306 | irq_set_affinity_hint(reply_q->vector, NULL); | ||
| 1307 | free_cpumask_var(reply_q->affinity_hint); | ||
| 1308 | synchronize_irq(reply_q->vector); | ||
| 1309 | free_irq(reply_q->vector, reply_q); | ||
| 1310 | kfree(reply_q); | ||
| 1311 | } | ||
| 1312 | } | ||
| 1313 | |||
| 1314 | /** | ||
| 1315 | * _base_request_irq - request irq | ||
| 1316 | * @ioc: per adapter object | ||
| 1317 | * @index: msix index into vector table | ||
| 1318 | * @vector: irq vector | ||
| 1319 | * | ||
| 1320 | * Inserting respective reply_queue into the list. | ||
| 1321 | */ | ||
| 1322 | static int | ||
| 1323 | _base_request_irq(struct MPT2SAS_ADAPTER *ioc, u8 index, u32 vector) | ||
| 1324 | { | ||
| 1325 | struct adapter_reply_queue *reply_q; | ||
| 1326 | int r; | ||
| 1327 | |||
| 1328 | reply_q = kzalloc(sizeof(struct adapter_reply_queue), GFP_KERNEL); | ||
| 1329 | if (!reply_q) { | ||
| 1330 | printk(MPT2SAS_ERR_FMT "unable to allocate memory %d!\n", | ||
| 1331 | ioc->name, (int)sizeof(struct adapter_reply_queue)); | ||
| 1332 | return -ENOMEM; | ||
| 1333 | } | ||
| 1334 | reply_q->ioc = ioc; | ||
| 1335 | reply_q->msix_index = index; | ||
| 1336 | reply_q->vector = vector; | ||
| 1337 | |||
| 1338 | if (!alloc_cpumask_var(&reply_q->affinity_hint, GFP_KERNEL)) | ||
| 1339 | return -ENOMEM; | ||
| 1340 | cpumask_clear(reply_q->affinity_hint); | ||
| 1341 | |||
| 1342 | atomic_set(&reply_q->busy, 0); | ||
| 1343 | if (ioc->msix_enable) | ||
| 1344 | snprintf(reply_q->name, MPT_NAME_LENGTH, "%s%d-msix%d", | ||
| 1345 | MPT2SAS_DRIVER_NAME, ioc->id, index); | ||
| 1346 | else | ||
| 1347 | snprintf(reply_q->name, MPT_NAME_LENGTH, "%s%d", | ||
| 1348 | MPT2SAS_DRIVER_NAME, ioc->id); | ||
| 1349 | r = request_irq(vector, _base_interrupt, IRQF_SHARED, reply_q->name, | ||
| 1350 | reply_q); | ||
| 1351 | if (r) { | ||
| 1352 | printk(MPT2SAS_ERR_FMT "unable to allocate interrupt %d!\n", | ||
| 1353 | reply_q->name, vector); | ||
| 1354 | kfree(reply_q); | ||
| 1355 | return -EBUSY; | ||
| 1356 | } | ||
| 1357 | |||
| 1358 | INIT_LIST_HEAD(&reply_q->list); | ||
| 1359 | list_add_tail(&reply_q->list, &ioc->reply_queue_list); | ||
| 1360 | return 0; | ||
| 1361 | } | ||
| 1362 | |||
| 1363 | /** | ||
| 1364 | * _base_assign_reply_queues - assigning msix index for each cpu | ||
| 1365 | * @ioc: per adapter object | ||
| 1366 | * | ||
| 1367 | * The enduser would need to set the affinity via /proc/irq/#/smp_affinity | ||
| 1368 | * | ||
| 1369 | * It would nice if we could call irq_set_affinity, however it is not | ||
| 1370 | * an exported symbol | ||
| 1371 | */ | ||
| 1372 | static void | ||
| 1373 | _base_assign_reply_queues(struct MPT2SAS_ADAPTER *ioc) | ||
| 1374 | { | ||
| 1375 | unsigned int cpu, nr_cpus, nr_msix, index = 0; | ||
| 1376 | struct adapter_reply_queue *reply_q; | ||
| 1377 | |||
| 1378 | if (!_base_is_controller_msix_enabled(ioc)) | ||
| 1379 | return; | ||
| 1380 | |||
| 1381 | memset(ioc->cpu_msix_table, 0, ioc->cpu_msix_table_sz); | ||
| 1382 | |||
| 1383 | nr_cpus = num_online_cpus(); | ||
| 1384 | nr_msix = ioc->reply_queue_count = min(ioc->reply_queue_count, | ||
| 1385 | ioc->facts.MaxMSIxVectors); | ||
| 1386 | if (!nr_msix) | ||
| 1387 | return; | ||
| 1388 | |||
| 1389 | cpu = cpumask_first(cpu_online_mask); | ||
| 1390 | |||
| 1391 | list_for_each_entry(reply_q, &ioc->reply_queue_list, list) { | ||
| 1392 | |||
| 1393 | unsigned int i, group = nr_cpus / nr_msix; | ||
| 1394 | |||
| 1395 | if (cpu >= nr_cpus) | ||
| 1396 | break; | ||
| 1397 | |||
| 1398 | if (index < nr_cpus % nr_msix) | ||
| 1399 | group++; | ||
| 1400 | |||
| 1401 | for (i = 0 ; i < group ; i++) { | ||
| 1402 | ioc->cpu_msix_table[cpu] = index; | ||
| 1403 | cpumask_or(reply_q->affinity_hint, | ||
| 1404 | reply_q->affinity_hint, get_cpu_mask(cpu)); | ||
| 1405 | cpu = cpumask_next(cpu, cpu_online_mask); | ||
| 1406 | } | ||
| 1407 | |||
| 1408 | if (irq_set_affinity_hint(reply_q->vector, | ||
| 1409 | reply_q->affinity_hint)) | ||
| 1410 | dinitprintk(ioc, pr_info(MPT2SAS_FMT | ||
| 1411 | "error setting affinity hint for irq vector %d\n", | ||
| 1412 | ioc->name, reply_q->vector)); | ||
| 1413 | index++; | ||
| 1414 | } | ||
| 1415 | } | ||
| 1416 | |||
| 1417 | /** | ||
| 1418 | * _base_disable_msix - disables msix | ||
| 1419 | * @ioc: per adapter object | ||
| 1420 | * | ||
| 1421 | */ | ||
| 1422 | static void | ||
| 1423 | _base_disable_msix(struct MPT2SAS_ADAPTER *ioc) | ||
| 1424 | { | ||
| 1425 | if (ioc->msix_enable) { | ||
| 1426 | pci_disable_msix(ioc->pdev); | ||
| 1427 | ioc->msix_enable = 0; | ||
| 1428 | } | ||
| 1429 | } | ||
| 1430 | |||
| 1431 | /** | ||
| 1432 | * _base_enable_msix - enables msix, failback to io_apic | ||
| 1433 | * @ioc: per adapter object | ||
| 1434 | * | ||
| 1435 | */ | ||
| 1436 | static int | ||
| 1437 | _base_enable_msix(struct MPT2SAS_ADAPTER *ioc) | ||
| 1438 | { | ||
| 1439 | struct msix_entry *entries, *a; | ||
| 1440 | int r; | ||
| 1441 | int i; | ||
| 1442 | u8 try_msix = 0; | ||
| 1443 | |||
| 1444 | if (msix_disable == -1 || msix_disable == 0) | ||
| 1445 | try_msix = 1; | ||
| 1446 | |||
| 1447 | if (!try_msix) | ||
| 1448 | goto try_ioapic; | ||
| 1449 | |||
| 1450 | if (_base_check_enable_msix(ioc) != 0) | ||
| 1451 | goto try_ioapic; | ||
| 1452 | |||
| 1453 | ioc->reply_queue_count = min_t(int, ioc->cpu_count, | ||
| 1454 | ioc->msix_vector_count); | ||
| 1455 | |||
| 1456 | if (!ioc->rdpq_array_enable && max_msix_vectors == -1) | ||
| 1457 | max_msix_vectors = 8; | ||
| 1458 | |||
| 1459 | if (max_msix_vectors > 0) { | ||
| 1460 | ioc->reply_queue_count = min_t(int, max_msix_vectors, | ||
| 1461 | ioc->reply_queue_count); | ||
| 1462 | ioc->msix_vector_count = ioc->reply_queue_count; | ||
| 1463 | } else if (max_msix_vectors == 0) | ||
| 1464 | goto try_ioapic; | ||
| 1465 | |||
| 1466 | printk(MPT2SAS_INFO_FMT | ||
| 1467 | "MSI-X vectors supported: %d, no of cores: %d, max_msix_vectors: %d\n", | ||
| 1468 | ioc->name, ioc->msix_vector_count, ioc->cpu_count, max_msix_vectors); | ||
| 1469 | |||
| 1470 | entries = kcalloc(ioc->reply_queue_count, sizeof(struct msix_entry), | ||
| 1471 | GFP_KERNEL); | ||
| 1472 | if (!entries) { | ||
| 1473 | dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "kcalloc " | ||
| 1474 | "failed @ at %s:%d/%s() !!!\n", ioc->name, __FILE__, | ||
| 1475 | __LINE__, __func__)); | ||
| 1476 | goto try_ioapic; | ||
| 1477 | } | ||
| 1478 | |||
| 1479 | for (i = 0, a = entries; i < ioc->reply_queue_count; i++, a++) | ||
| 1480 | a->entry = i; | ||
| 1481 | |||
| 1482 | r = pci_enable_msix_exact(ioc->pdev, entries, ioc->reply_queue_count); | ||
| 1483 | if (r) { | ||
| 1484 | dfailprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 1485 | "pci_enable_msix_exact failed (r=%d) !!!\n", ioc->name, r)); | ||
| 1486 | kfree(entries); | ||
| 1487 | goto try_ioapic; | ||
| 1488 | } | ||
| 1489 | |||
| 1490 | ioc->msix_enable = 1; | ||
| 1491 | for (i = 0, a = entries; i < ioc->reply_queue_count; i++, a++) { | ||
| 1492 | r = _base_request_irq(ioc, i, a->vector); | ||
| 1493 | if (r) { | ||
| 1494 | _base_free_irq(ioc); | ||
| 1495 | _base_disable_msix(ioc); | ||
| 1496 | kfree(entries); | ||
| 1497 | goto try_ioapic; | ||
| 1498 | } | ||
| 1499 | } | ||
| 1500 | |||
| 1501 | kfree(entries); | ||
| 1502 | return 0; | ||
| 1503 | |||
| 1504 | /* failback to io_apic interrupt routing */ | ||
| 1505 | try_ioapic: | ||
| 1506 | |||
| 1507 | ioc->reply_queue_count = 1; | ||
| 1508 | r = _base_request_irq(ioc, 0, ioc->pdev->irq); | ||
| 1509 | |||
| 1510 | return r; | ||
| 1511 | } | ||
| 1512 | |||
| 1513 | /** | ||
| 1514 | * mpt2sas_base_map_resources - map in controller resources (io/irq/memap) | ||
| 1515 | * @ioc: per adapter object | ||
| 1516 | * | ||
| 1517 | * Returns 0 for success, non-zero for failure. | ||
| 1518 | */ | ||
| 1519 | int | ||
| 1520 | mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc) | ||
| 1521 | { | ||
| 1522 | struct pci_dev *pdev = ioc->pdev; | ||
| 1523 | u32 memap_sz; | ||
| 1524 | u32 pio_sz; | ||
| 1525 | int i, r = 0; | ||
| 1526 | u64 pio_chip = 0; | ||
| 1527 | u64 chip_phys = 0; | ||
| 1528 | struct adapter_reply_queue *reply_q; | ||
| 1529 | |||
| 1530 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", | ||
| 1531 | ioc->name, __func__)); | ||
| 1532 | |||
| 1533 | ioc->bars = pci_select_bars(pdev, IORESOURCE_MEM); | ||
| 1534 | if (pci_enable_device_mem(pdev)) { | ||
| 1535 | printk(MPT2SAS_WARN_FMT "pci_enable_device_mem: " | ||
| 1536 | "failed\n", ioc->name); | ||
| 1537 | ioc->bars = 0; | ||
| 1538 | return -ENODEV; | ||
| 1539 | } | ||
| 1540 | |||
| 1541 | |||
| 1542 | if (pci_request_selected_regions(pdev, ioc->bars, | ||
| 1543 | MPT2SAS_DRIVER_NAME)) { | ||
| 1544 | printk(MPT2SAS_WARN_FMT "pci_request_selected_regions: " | ||
| 1545 | "failed\n", ioc->name); | ||
| 1546 | ioc->bars = 0; | ||
| 1547 | r = -ENODEV; | ||
| 1548 | goto out_fail; | ||
| 1549 | } | ||
| 1550 | |||
| 1551 | /* AER (Advanced Error Reporting) hooks */ | ||
| 1552 | pci_enable_pcie_error_reporting(pdev); | ||
| 1553 | |||
| 1554 | pci_set_master(pdev); | ||
| 1555 | |||
| 1556 | if (_base_config_dma_addressing(ioc, pdev) != 0) { | ||
| 1557 | printk(MPT2SAS_WARN_FMT "no suitable DMA mask for %s\n", | ||
| 1558 | ioc->name, pci_name(pdev)); | ||
| 1559 | r = -ENODEV; | ||
| 1560 | goto out_fail; | ||
| 1561 | } | ||
| 1562 | |||
| 1563 | for (i = 0, memap_sz = 0, pio_sz = 0; (i < DEVICE_COUNT_RESOURCE) && | ||
| 1564 | (!memap_sz || !pio_sz); i++) { | ||
| 1565 | if (pci_resource_flags(pdev, i) & IORESOURCE_IO) { | ||
| 1566 | if (pio_sz) | ||
| 1567 | continue; | ||
| 1568 | pio_chip = (u64)pci_resource_start(pdev, i); | ||
| 1569 | pio_sz = pci_resource_len(pdev, i); | ||
| 1570 | } else { | ||
| 1571 | if (memap_sz) | ||
| 1572 | continue; | ||
| 1573 | /* verify memory resource is valid before using */ | ||
| 1574 | if (pci_resource_flags(pdev, i) & IORESOURCE_MEM) { | ||
| 1575 | ioc->chip_phys = pci_resource_start(pdev, i); | ||
| 1576 | chip_phys = (u64)ioc->chip_phys; | ||
| 1577 | memap_sz = pci_resource_len(pdev, i); | ||
| 1578 | ioc->chip = ioremap(ioc->chip_phys, memap_sz); | ||
| 1579 | } | ||
| 1580 | } | ||
| 1581 | } | ||
| 1582 | |||
| 1583 | if (ioc->chip == NULL) { | ||
| 1584 | printk(MPT2SAS_ERR_FMT "unable to map adapter memory! " | ||
| 1585 | "or resource not found\n", ioc->name); | ||
| 1586 | r = -EINVAL; | ||
| 1587 | goto out_fail; | ||
| 1588 | } | ||
| 1589 | |||
| 1590 | _base_mask_interrupts(ioc); | ||
| 1591 | |||
| 1592 | r = _base_get_ioc_facts(ioc, CAN_SLEEP); | ||
| 1593 | if (r) | ||
| 1594 | goto out_fail; | ||
| 1595 | |||
| 1596 | if (!ioc->rdpq_array_enable_assigned) { | ||
| 1597 | ioc->rdpq_array_enable = ioc->rdpq_array_capable; | ||
| 1598 | ioc->rdpq_array_enable_assigned = 1; | ||
| 1599 | } | ||
| 1600 | |||
| 1601 | r = _base_enable_msix(ioc); | ||
| 1602 | if (r) | ||
| 1603 | goto out_fail; | ||
| 1604 | |||
| 1605 | list_for_each_entry(reply_q, &ioc->reply_queue_list, list) | ||
| 1606 | printk(MPT2SAS_INFO_FMT "%s: IRQ %d\n", | ||
| 1607 | reply_q->name, ((ioc->msix_enable) ? "PCI-MSI-X enabled" : | ||
| 1608 | "IO-APIC enabled"), reply_q->vector); | ||
| 1609 | |||
| 1610 | printk(MPT2SAS_INFO_FMT "iomem(0x%016llx), mapped(0x%p), size(%d)\n", | ||
| 1611 | ioc->name, (unsigned long long)chip_phys, ioc->chip, memap_sz); | ||
| 1612 | printk(MPT2SAS_INFO_FMT "ioport(0x%016llx), size(%d)\n", | ||
| 1613 | ioc->name, (unsigned long long)pio_chip, pio_sz); | ||
| 1614 | |||
| 1615 | /* Save PCI configuration state for recovery from PCI AER/EEH errors */ | ||
| 1616 | pci_save_state(pdev); | ||
| 1617 | |||
| 1618 | return 0; | ||
| 1619 | |||
| 1620 | out_fail: | ||
| 1621 | if (ioc->chip_phys) | ||
| 1622 | iounmap(ioc->chip); | ||
| 1623 | ioc->chip_phys = 0; | ||
| 1624 | pci_release_selected_regions(ioc->pdev, ioc->bars); | ||
| 1625 | pci_disable_pcie_error_reporting(pdev); | ||
| 1626 | pci_disable_device(pdev); | ||
| 1627 | return r; | ||
| 1628 | } | ||
| 1629 | |||
| 1630 | /** | ||
| 1631 | * mpt2sas_base_get_msg_frame - obtain request mf pointer | ||
| 1632 | * @ioc: per adapter object | ||
| 1633 | * @smid: system request message index(smid zero is invalid) | ||
| 1634 | * | ||
| 1635 | * Returns virt pointer to message frame. | ||
| 1636 | */ | ||
| 1637 | void * | ||
| 1638 | mpt2sas_base_get_msg_frame(struct MPT2SAS_ADAPTER *ioc, u16 smid) | ||
| 1639 | { | ||
| 1640 | return (void *)(ioc->request + (smid * ioc->request_sz)); | ||
| 1641 | } | ||
| 1642 | |||
| 1643 | /** | ||
| 1644 | * mpt2sas_base_get_sense_buffer - obtain a sense buffer assigned to a mf request | ||
| 1645 | * @ioc: per adapter object | ||
| 1646 | * @smid: system request message index | ||
| 1647 | * | ||
| 1648 | * Returns virt pointer to sense buffer. | ||
| 1649 | */ | ||
| 1650 | void * | ||
| 1651 | mpt2sas_base_get_sense_buffer(struct MPT2SAS_ADAPTER *ioc, u16 smid) | ||
| 1652 | { | ||
| 1653 | return (void *)(ioc->sense + ((smid - 1) * SCSI_SENSE_BUFFERSIZE)); | ||
| 1654 | } | ||
| 1655 | |||
| 1656 | /** | ||
| 1657 | * mpt2sas_base_get_sense_buffer_dma - obtain a sense buffer assigned to a mf request | ||
| 1658 | * @ioc: per adapter object | ||
| 1659 | * @smid: system request message index | ||
| 1660 | * | ||
| 1661 | * Returns phys pointer to the low 32bit address of the sense buffer. | ||
| 1662 | */ | ||
| 1663 | __le32 | ||
| 1664 | mpt2sas_base_get_sense_buffer_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid) | ||
| 1665 | { | ||
| 1666 | return cpu_to_le32(ioc->sense_dma + | ||
| 1667 | ((smid - 1) * SCSI_SENSE_BUFFERSIZE)); | ||
| 1668 | } | ||
| 1669 | |||
| 1670 | /** | ||
| 1671 | * mpt2sas_base_get_reply_virt_addr - obtain reply frames virt address | ||
| 1672 | * @ioc: per adapter object | ||
| 1673 | * @phys_addr: lower 32 physical addr of the reply | ||
| 1674 | * | ||
| 1675 | * Converts 32bit lower physical addr into a virt address. | ||
| 1676 | */ | ||
| 1677 | void * | ||
| 1678 | mpt2sas_base_get_reply_virt_addr(struct MPT2SAS_ADAPTER *ioc, u32 phys_addr) | ||
| 1679 | { | ||
| 1680 | if (!phys_addr) | ||
| 1681 | return NULL; | ||
| 1682 | return ioc->reply + (phys_addr - (u32)ioc->reply_dma); | ||
| 1683 | } | ||
| 1684 | |||
| 1685 | /** | ||
| 1686 | * mpt2sas_base_get_smid - obtain a free smid from internal queue | ||
| 1687 | * @ioc: per adapter object | ||
| 1688 | * @cb_idx: callback index | ||
| 1689 | * | ||
| 1690 | * Returns smid (zero is invalid) | ||
| 1691 | */ | ||
| 1692 | u16 | ||
| 1693 | mpt2sas_base_get_smid(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx) | ||
| 1694 | { | ||
| 1695 | unsigned long flags; | ||
| 1696 | struct request_tracker *request; | ||
| 1697 | u16 smid; | ||
| 1698 | |||
| 1699 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | ||
| 1700 | if (list_empty(&ioc->internal_free_list)) { | ||
| 1701 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | ||
| 1702 | printk(MPT2SAS_ERR_FMT "%s: smid not available\n", | ||
| 1703 | ioc->name, __func__); | ||
| 1704 | return 0; | ||
| 1705 | } | ||
| 1706 | |||
| 1707 | request = list_entry(ioc->internal_free_list.next, | ||
| 1708 | struct request_tracker, tracker_list); | ||
| 1709 | request->cb_idx = cb_idx; | ||
| 1710 | smid = request->smid; | ||
| 1711 | list_del(&request->tracker_list); | ||
| 1712 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | ||
| 1713 | return smid; | ||
| 1714 | } | ||
| 1715 | |||
| 1716 | /** | ||
| 1717 | * mpt2sas_base_get_smid_scsiio - obtain a free smid from scsiio queue | ||
| 1718 | * @ioc: per adapter object | ||
| 1719 | * @cb_idx: callback index | ||
| 1720 | * @scmd: pointer to scsi command object | ||
| 1721 | * | ||
| 1722 | * Returns smid (zero is invalid) | ||
| 1723 | */ | ||
| 1724 | u16 | ||
| 1725 | mpt2sas_base_get_smid_scsiio(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx, | ||
| 1726 | struct scsi_cmnd *scmd) | ||
| 1727 | { | ||
| 1728 | unsigned long flags; | ||
| 1729 | struct scsiio_tracker *request; | ||
| 1730 | u16 smid; | ||
| 1731 | |||
| 1732 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | ||
| 1733 | if (list_empty(&ioc->free_list)) { | ||
| 1734 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | ||
| 1735 | printk(MPT2SAS_ERR_FMT "%s: smid not available\n", | ||
| 1736 | ioc->name, __func__); | ||
| 1737 | return 0; | ||
| 1738 | } | ||
| 1739 | |||
| 1740 | request = list_entry(ioc->free_list.next, | ||
| 1741 | struct scsiio_tracker, tracker_list); | ||
| 1742 | request->scmd = scmd; | ||
| 1743 | request->cb_idx = cb_idx; | ||
| 1744 | smid = request->smid; | ||
| 1745 | list_del(&request->tracker_list); | ||
| 1746 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | ||
| 1747 | return smid; | ||
| 1748 | } | ||
| 1749 | |||
| 1750 | /** | ||
| 1751 | * mpt2sas_base_get_smid_hpr - obtain a free smid from hi-priority queue | ||
| 1752 | * @ioc: per adapter object | ||
| 1753 | * @cb_idx: callback index | ||
| 1754 | * | ||
| 1755 | * Returns smid (zero is invalid) | ||
| 1756 | */ | ||
| 1757 | u16 | ||
| 1758 | mpt2sas_base_get_smid_hpr(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx) | ||
| 1759 | { | ||
| 1760 | unsigned long flags; | ||
| 1761 | struct request_tracker *request; | ||
| 1762 | u16 smid; | ||
| 1763 | |||
| 1764 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | ||
| 1765 | if (list_empty(&ioc->hpr_free_list)) { | ||
| 1766 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | ||
| 1767 | return 0; | ||
| 1768 | } | ||
| 1769 | |||
| 1770 | request = list_entry(ioc->hpr_free_list.next, | ||
| 1771 | struct request_tracker, tracker_list); | ||
| 1772 | request->cb_idx = cb_idx; | ||
| 1773 | smid = request->smid; | ||
| 1774 | list_del(&request->tracker_list); | ||
| 1775 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | ||
| 1776 | return smid; | ||
| 1777 | } | ||
| 1778 | |||
| 1779 | |||
| 1780 | /** | ||
| 1781 | * mpt2sas_base_free_smid - put smid back on free_list | ||
| 1782 | * @ioc: per adapter object | ||
| 1783 | * @smid: system request message index | ||
| 1784 | * | ||
| 1785 | * Return nothing. | ||
| 1786 | */ | ||
| 1787 | void | ||
| 1788 | mpt2sas_base_free_smid(struct MPT2SAS_ADAPTER *ioc, u16 smid) | ||
| 1789 | { | ||
| 1790 | unsigned long flags; | ||
| 1791 | int i; | ||
| 1792 | struct chain_tracker *chain_req, *next; | ||
| 1793 | |||
| 1794 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | ||
| 1795 | if (smid < ioc->hi_priority_smid) { | ||
| 1796 | /* scsiio queue */ | ||
| 1797 | i = smid - 1; | ||
| 1798 | if (!list_empty(&ioc->scsi_lookup[i].chain_list)) { | ||
| 1799 | list_for_each_entry_safe(chain_req, next, | ||
| 1800 | &ioc->scsi_lookup[i].chain_list, tracker_list) { | ||
| 1801 | list_del_init(&chain_req->tracker_list); | ||
| 1802 | list_add(&chain_req->tracker_list, | ||
| 1803 | &ioc->free_chain_list); | ||
| 1804 | } | ||
| 1805 | } | ||
| 1806 | ioc->scsi_lookup[i].cb_idx = 0xFF; | ||
| 1807 | ioc->scsi_lookup[i].scmd = NULL; | ||
| 1808 | ioc->scsi_lookup[i].direct_io = 0; | ||
| 1809 | list_add(&ioc->scsi_lookup[i].tracker_list, | ||
| 1810 | &ioc->free_list); | ||
| 1811 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | ||
| 1812 | |||
| 1813 | /* | ||
| 1814 | * See _wait_for_commands_to_complete() call with regards | ||
| 1815 | * to this code. | ||
| 1816 | */ | ||
| 1817 | if (ioc->shost_recovery && ioc->pending_io_count) { | ||
| 1818 | if (ioc->pending_io_count == 1) | ||
| 1819 | wake_up(&ioc->reset_wq); | ||
| 1820 | ioc->pending_io_count--; | ||
| 1821 | } | ||
| 1822 | return; | ||
| 1823 | } else if (smid < ioc->internal_smid) { | ||
| 1824 | /* hi-priority */ | ||
| 1825 | i = smid - ioc->hi_priority_smid; | ||
| 1826 | ioc->hpr_lookup[i].cb_idx = 0xFF; | ||
| 1827 | list_add(&ioc->hpr_lookup[i].tracker_list, | ||
| 1828 | &ioc->hpr_free_list); | ||
| 1829 | } else if (smid <= ioc->hba_queue_depth) { | ||
| 1830 | /* internal queue */ | ||
| 1831 | i = smid - ioc->internal_smid; | ||
| 1832 | ioc->internal_lookup[i].cb_idx = 0xFF; | ||
| 1833 | list_add(&ioc->internal_lookup[i].tracker_list, | ||
| 1834 | &ioc->internal_free_list); | ||
| 1835 | } | ||
| 1836 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | ||
| 1837 | } | ||
| 1838 | |||
| 1839 | /** | ||
| 1840 | * _base_writeq - 64 bit write to MMIO | ||
| 1841 | * @ioc: per adapter object | ||
| 1842 | * @b: data payload | ||
| 1843 | * @addr: address in MMIO space | ||
| 1844 | * @writeq_lock: spin lock | ||
| 1845 | * | ||
| 1846 | * Glue for handling an atomic 64 bit word to MMIO. This special handling takes | ||
| 1847 | * care of 32 bit environment where its not quarenteed to send the entire word | ||
| 1848 | * in one transfer. | ||
| 1849 | */ | ||
| 1850 | #ifndef writeq | ||
| 1851 | static inline void _base_writeq(__u64 b, volatile void __iomem *addr, | ||
| 1852 | spinlock_t *writeq_lock) | ||
| 1853 | { | ||
| 1854 | unsigned long flags; | ||
| 1855 | __u64 data_out = cpu_to_le64(b); | ||
| 1856 | |||
| 1857 | spin_lock_irqsave(writeq_lock, flags); | ||
| 1858 | writel((u32)(data_out), addr); | ||
| 1859 | writel((u32)(data_out >> 32), (addr + 4)); | ||
| 1860 | spin_unlock_irqrestore(writeq_lock, flags); | ||
| 1861 | } | ||
| 1862 | #else | ||
| 1863 | static inline void _base_writeq(__u64 b, volatile void __iomem *addr, | ||
| 1864 | spinlock_t *writeq_lock) | ||
| 1865 | { | ||
| 1866 | writeq(cpu_to_le64(b), addr); | ||
| 1867 | } | ||
| 1868 | #endif | ||
| 1869 | |||
| 1870 | static inline u8 | ||
| 1871 | _base_get_msix_index(struct MPT2SAS_ADAPTER *ioc) | ||
| 1872 | { | ||
| 1873 | return ioc->cpu_msix_table[raw_smp_processor_id()]; | ||
| 1874 | } | ||
| 1875 | |||
| 1876 | /** | ||
| 1877 | * mpt2sas_base_put_smid_scsi_io - send SCSI_IO request to firmware | ||
| 1878 | * @ioc: per adapter object | ||
| 1879 | * @smid: system request message index | ||
| 1880 | * @handle: device handle | ||
| 1881 | * | ||
| 1882 | * Return nothing. | ||
| 1883 | */ | ||
| 1884 | void | ||
| 1885 | mpt2sas_base_put_smid_scsi_io(struct MPT2SAS_ADAPTER *ioc, u16 smid, u16 handle) | ||
| 1886 | { | ||
| 1887 | Mpi2RequestDescriptorUnion_t descriptor; | ||
| 1888 | u64 *request = (u64 *)&descriptor; | ||
| 1889 | |||
| 1890 | |||
| 1891 | descriptor.SCSIIO.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO; | ||
| 1892 | descriptor.SCSIIO.MSIxIndex = _base_get_msix_index(ioc); | ||
| 1893 | descriptor.SCSIIO.SMID = cpu_to_le16(smid); | ||
| 1894 | descriptor.SCSIIO.DevHandle = cpu_to_le16(handle); | ||
| 1895 | descriptor.SCSIIO.LMID = 0; | ||
| 1896 | _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow, | ||
| 1897 | &ioc->scsi_lookup_lock); | ||
| 1898 | } | ||
| 1899 | |||
| 1900 | |||
| 1901 | /** | ||
| 1902 | * mpt2sas_base_put_smid_hi_priority - send Task Management request to firmware | ||
| 1903 | * @ioc: per adapter object | ||
| 1904 | * @smid: system request message index | ||
| 1905 | * | ||
| 1906 | * Return nothing. | ||
| 1907 | */ | ||
| 1908 | void | ||
| 1909 | mpt2sas_base_put_smid_hi_priority(struct MPT2SAS_ADAPTER *ioc, u16 smid) | ||
| 1910 | { | ||
| 1911 | Mpi2RequestDescriptorUnion_t descriptor; | ||
| 1912 | u64 *request = (u64 *)&descriptor; | ||
| 1913 | |||
| 1914 | descriptor.HighPriority.RequestFlags = | ||
| 1915 | MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; | ||
| 1916 | descriptor.HighPriority.MSIxIndex = 0; | ||
| 1917 | descriptor.HighPriority.SMID = cpu_to_le16(smid); | ||
| 1918 | descriptor.HighPriority.LMID = 0; | ||
| 1919 | descriptor.HighPriority.Reserved1 = 0; | ||
| 1920 | _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow, | ||
| 1921 | &ioc->scsi_lookup_lock); | ||
| 1922 | } | ||
| 1923 | |||
| 1924 | /** | ||
| 1925 | * mpt2sas_base_put_smid_default - Default, primarily used for config pages | ||
| 1926 | * @ioc: per adapter object | ||
| 1927 | * @smid: system request message index | ||
| 1928 | * | ||
| 1929 | * Return nothing. | ||
| 1930 | */ | ||
| 1931 | void | ||
| 1932 | mpt2sas_base_put_smid_default(struct MPT2SAS_ADAPTER *ioc, u16 smid) | ||
| 1933 | { | ||
| 1934 | Mpi2RequestDescriptorUnion_t descriptor; | ||
| 1935 | u64 *request = (u64 *)&descriptor; | ||
| 1936 | |||
| 1937 | descriptor.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; | ||
| 1938 | descriptor.Default.MSIxIndex = _base_get_msix_index(ioc); | ||
| 1939 | descriptor.Default.SMID = cpu_to_le16(smid); | ||
| 1940 | descriptor.Default.LMID = 0; | ||
| 1941 | descriptor.Default.DescriptorTypeDependent = 0; | ||
| 1942 | _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow, | ||
| 1943 | &ioc->scsi_lookup_lock); | ||
| 1944 | } | ||
| 1945 | |||
| 1946 | /** | ||
| 1947 | * mpt2sas_base_put_smid_target_assist - send Target Assist/Status to firmware | ||
| 1948 | * @ioc: per adapter object | ||
| 1949 | * @smid: system request message index | ||
| 1950 | * @io_index: value used to track the IO | ||
| 1951 | * | ||
| 1952 | * Return nothing. | ||
| 1953 | */ | ||
| 1954 | void | ||
| 1955 | mpt2sas_base_put_smid_target_assist(struct MPT2SAS_ADAPTER *ioc, u16 smid, | ||
| 1956 | u16 io_index) | ||
| 1957 | { | ||
| 1958 | Mpi2RequestDescriptorUnion_t descriptor; | ||
| 1959 | u64 *request = (u64 *)&descriptor; | ||
| 1960 | |||
| 1961 | descriptor.SCSITarget.RequestFlags = | ||
| 1962 | MPI2_REQ_DESCRIPT_FLAGS_SCSI_TARGET; | ||
| 1963 | descriptor.SCSITarget.MSIxIndex = _base_get_msix_index(ioc); | ||
| 1964 | descriptor.SCSITarget.SMID = cpu_to_le16(smid); | ||
| 1965 | descriptor.SCSITarget.LMID = 0; | ||
| 1966 | descriptor.SCSITarget.IoIndex = cpu_to_le16(io_index); | ||
| 1967 | _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow, | ||
| 1968 | &ioc->scsi_lookup_lock); | ||
| 1969 | } | ||
| 1970 | |||
| 1971 | /** | ||
| 1972 | * _base_display_dell_branding - Disply branding string | ||
| 1973 | * @ioc: per adapter object | ||
| 1974 | * | ||
| 1975 | * Return nothing. | ||
| 1976 | */ | ||
| 1977 | static void | ||
| 1978 | _base_display_dell_branding(struct MPT2SAS_ADAPTER *ioc) | ||
| 1979 | { | ||
| 1980 | char dell_branding[MPT2SAS_DELL_BRANDING_SIZE]; | ||
| 1981 | |||
| 1982 | if (ioc->pdev->subsystem_vendor != PCI_VENDOR_ID_DELL) | ||
| 1983 | return; | ||
| 1984 | |||
| 1985 | memset(dell_branding, 0, MPT2SAS_DELL_BRANDING_SIZE); | ||
| 1986 | switch (ioc->pdev->subsystem_device) { | ||
| 1987 | case MPT2SAS_DELL_6GBPS_SAS_HBA_SSDID: | ||
| 1988 | strncpy(dell_branding, MPT2SAS_DELL_6GBPS_SAS_HBA_BRANDING, | ||
| 1989 | MPT2SAS_DELL_BRANDING_SIZE - 1); | ||
| 1990 | break; | ||
| 1991 | case MPT2SAS_DELL_PERC_H200_ADAPTER_SSDID: | ||
| 1992 | strncpy(dell_branding, MPT2SAS_DELL_PERC_H200_ADAPTER_BRANDING, | ||
| 1993 | MPT2SAS_DELL_BRANDING_SIZE - 1); | ||
| 1994 | break; | ||
| 1995 | case MPT2SAS_DELL_PERC_H200_INTEGRATED_SSDID: | ||
| 1996 | strncpy(dell_branding, | ||
| 1997 | MPT2SAS_DELL_PERC_H200_INTEGRATED_BRANDING, | ||
| 1998 | MPT2SAS_DELL_BRANDING_SIZE - 1); | ||
| 1999 | break; | ||
| 2000 | case MPT2SAS_DELL_PERC_H200_MODULAR_SSDID: | ||
| 2001 | strncpy(dell_branding, | ||
| 2002 | MPT2SAS_DELL_PERC_H200_MODULAR_BRANDING, | ||
| 2003 | MPT2SAS_DELL_BRANDING_SIZE - 1); | ||
| 2004 | break; | ||
| 2005 | case MPT2SAS_DELL_PERC_H200_EMBEDDED_SSDID: | ||
| 2006 | strncpy(dell_branding, | ||
| 2007 | MPT2SAS_DELL_PERC_H200_EMBEDDED_BRANDING, | ||
| 2008 | MPT2SAS_DELL_BRANDING_SIZE - 1); | ||
| 2009 | break; | ||
| 2010 | case MPT2SAS_DELL_PERC_H200_SSDID: | ||
| 2011 | strncpy(dell_branding, MPT2SAS_DELL_PERC_H200_BRANDING, | ||
| 2012 | MPT2SAS_DELL_BRANDING_SIZE - 1); | ||
| 2013 | break; | ||
| 2014 | case MPT2SAS_DELL_6GBPS_SAS_SSDID: | ||
| 2015 | strncpy(dell_branding, MPT2SAS_DELL_6GBPS_SAS_BRANDING, | ||
| 2016 | MPT2SAS_DELL_BRANDING_SIZE - 1); | ||
| 2017 | break; | ||
| 2018 | default: | ||
| 2019 | sprintf(dell_branding, "0x%4X", ioc->pdev->subsystem_device); | ||
| 2020 | break; | ||
| 2021 | } | ||
| 2022 | |||
| 2023 | printk(MPT2SAS_INFO_FMT "%s: Vendor(0x%04X), Device(0x%04X)," | ||
| 2024 | " SSVID(0x%04X), SSDID(0x%04X)\n", ioc->name, dell_branding, | ||
| 2025 | ioc->pdev->vendor, ioc->pdev->device, ioc->pdev->subsystem_vendor, | ||
| 2026 | ioc->pdev->subsystem_device); | ||
| 2027 | } | ||
| 2028 | |||
| 2029 | /** | ||
| 2030 | * _base_display_intel_branding - Display branding string | ||
| 2031 | * @ioc: per adapter object | ||
| 2032 | * | ||
| 2033 | * Return nothing. | ||
| 2034 | */ | ||
| 2035 | static void | ||
| 2036 | _base_display_intel_branding(struct MPT2SAS_ADAPTER *ioc) | ||
| 2037 | { | ||
| 2038 | if (ioc->pdev->subsystem_vendor != PCI_VENDOR_ID_INTEL) | ||
| 2039 | return; | ||
| 2040 | |||
| 2041 | switch (ioc->pdev->device) { | ||
| 2042 | case MPI2_MFGPAGE_DEVID_SAS2008: | ||
| 2043 | switch (ioc->pdev->subsystem_device) { | ||
| 2044 | case MPT2SAS_INTEL_RMS2LL080_SSDID: | ||
| 2045 | printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | ||
| 2046 | MPT2SAS_INTEL_RMS2LL080_BRANDING); | ||
| 2047 | break; | ||
| 2048 | case MPT2SAS_INTEL_RMS2LL040_SSDID: | ||
| 2049 | printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | ||
| 2050 | MPT2SAS_INTEL_RMS2LL040_BRANDING); | ||
| 2051 | break; | ||
| 2052 | case MPT2SAS_INTEL_SSD910_SSDID: | ||
| 2053 | printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | ||
| 2054 | MPT2SAS_INTEL_SSD910_BRANDING); | ||
| 2055 | break; | ||
| 2056 | default: | ||
| 2057 | break; | ||
| 2058 | } | ||
| 2059 | case MPI2_MFGPAGE_DEVID_SAS2308_2: | ||
| 2060 | switch (ioc->pdev->subsystem_device) { | ||
| 2061 | case MPT2SAS_INTEL_RS25GB008_SSDID: | ||
| 2062 | printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | ||
| 2063 | MPT2SAS_INTEL_RS25GB008_BRANDING); | ||
| 2064 | break; | ||
| 2065 | case MPT2SAS_INTEL_RMS25JB080_SSDID: | ||
| 2066 | printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | ||
| 2067 | MPT2SAS_INTEL_RMS25JB080_BRANDING); | ||
| 2068 | break; | ||
| 2069 | case MPT2SAS_INTEL_RMS25JB040_SSDID: | ||
| 2070 | printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | ||
| 2071 | MPT2SAS_INTEL_RMS25JB040_BRANDING); | ||
| 2072 | break; | ||
| 2073 | case MPT2SAS_INTEL_RMS25KB080_SSDID: | ||
| 2074 | printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | ||
| 2075 | MPT2SAS_INTEL_RMS25KB080_BRANDING); | ||
| 2076 | break; | ||
| 2077 | case MPT2SAS_INTEL_RMS25KB040_SSDID: | ||
| 2078 | printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | ||
| 2079 | MPT2SAS_INTEL_RMS25KB040_BRANDING); | ||
| 2080 | break; | ||
| 2081 | case MPT2SAS_INTEL_RMS25LB040_SSDID: | ||
| 2082 | printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | ||
| 2083 | MPT2SAS_INTEL_RMS25LB040_BRANDING); | ||
| 2084 | break; | ||
| 2085 | case MPT2SAS_INTEL_RMS25LB080_SSDID: | ||
| 2086 | printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | ||
| 2087 | MPT2SAS_INTEL_RMS25LB080_BRANDING); | ||
| 2088 | break; | ||
| 2089 | default: | ||
| 2090 | break; | ||
| 2091 | } | ||
| 2092 | default: | ||
| 2093 | break; | ||
| 2094 | } | ||
| 2095 | } | ||
| 2096 | |||
| 2097 | /** | ||
| 2098 | * _base_display_hp_branding - Display branding string | ||
| 2099 | * @ioc: per adapter object | ||
| 2100 | * | ||
| 2101 | * Return nothing. | ||
| 2102 | */ | ||
| 2103 | static void | ||
| 2104 | _base_display_hp_branding(struct MPT2SAS_ADAPTER *ioc) | ||
| 2105 | { | ||
| 2106 | if (ioc->pdev->subsystem_vendor != MPT2SAS_HP_3PAR_SSVID) | ||
| 2107 | return; | ||
| 2108 | |||
| 2109 | switch (ioc->pdev->device) { | ||
| 2110 | case MPI2_MFGPAGE_DEVID_SAS2004: | ||
| 2111 | switch (ioc->pdev->subsystem_device) { | ||
| 2112 | case MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_SSDID: | ||
| 2113 | printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | ||
| 2114 | MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_BRANDING); | ||
| 2115 | break; | ||
| 2116 | default: | ||
| 2117 | break; | ||
| 2118 | } | ||
| 2119 | case MPI2_MFGPAGE_DEVID_SAS2308_2: | ||
| 2120 | switch (ioc->pdev->subsystem_device) { | ||
| 2121 | case MPT2SAS_HP_2_4_INTERNAL_SSDID: | ||
| 2122 | printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | ||
| 2123 | MPT2SAS_HP_2_4_INTERNAL_BRANDING); | ||
| 2124 | break; | ||
| 2125 | case MPT2SAS_HP_2_4_EXTERNAL_SSDID: | ||
| 2126 | printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | ||
| 2127 | MPT2SAS_HP_2_4_EXTERNAL_BRANDING); | ||
| 2128 | break; | ||
| 2129 | case MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_SSDID: | ||
| 2130 | printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | ||
| 2131 | MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_BRANDING); | ||
| 2132 | break; | ||
| 2133 | case MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_SSDID: | ||
| 2134 | printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | ||
| 2135 | MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_BRANDING); | ||
| 2136 | break; | ||
| 2137 | default: | ||
| 2138 | break; | ||
| 2139 | } | ||
| 2140 | default: | ||
| 2141 | break; | ||
| 2142 | } | ||
| 2143 | } | ||
| 2144 | |||
| 2145 | /** | ||
| 2146 | * _base_display_ioc_capabilities - Disply IOC's capabilities. | ||
| 2147 | * @ioc: per adapter object | ||
| 2148 | * | ||
| 2149 | * Return nothing. | ||
| 2150 | */ | ||
| 2151 | static void | ||
| 2152 | _base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc) | ||
| 2153 | { | ||
| 2154 | int i = 0; | ||
| 2155 | char desc[16]; | ||
| 2156 | u32 iounit_pg1_flags; | ||
| 2157 | u32 bios_version; | ||
| 2158 | |||
| 2159 | bios_version = le32_to_cpu(ioc->bios_pg3.BiosVersion); | ||
| 2160 | strncpy(desc, ioc->manu_pg0.ChipName, 16); | ||
| 2161 | printk(MPT2SAS_INFO_FMT "%s: FWVersion(%02d.%02d.%02d.%02d), " | ||
| 2162 | "ChipRevision(0x%02x), BiosVersion(%02d.%02d.%02d.%02d)\n", | ||
| 2163 | ioc->name, desc, | ||
| 2164 | (ioc->facts.FWVersion.Word & 0xFF000000) >> 24, | ||
| 2165 | (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16, | ||
| 2166 | (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8, | ||
| 2167 | ioc->facts.FWVersion.Word & 0x000000FF, | ||
| 2168 | ioc->pdev->revision, | ||
| 2169 | (bios_version & 0xFF000000) >> 24, | ||
| 2170 | (bios_version & 0x00FF0000) >> 16, | ||
| 2171 | (bios_version & 0x0000FF00) >> 8, | ||
| 2172 | bios_version & 0x000000FF); | ||
| 2173 | |||
| 2174 | _base_display_dell_branding(ioc); | ||
| 2175 | _base_display_intel_branding(ioc); | ||
| 2176 | _base_display_hp_branding(ioc); | ||
| 2177 | |||
| 2178 | printk(MPT2SAS_INFO_FMT "Protocol=(", ioc->name); | ||
| 2179 | |||
| 2180 | if (ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR) { | ||
| 2181 | printk("Initiator"); | ||
| 2182 | i++; | ||
| 2183 | } | ||
| 2184 | |||
| 2185 | if (ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_TARGET) { | ||
| 2186 | printk("%sTarget", i ? "," : ""); | ||
| 2187 | i++; | ||
| 2188 | } | ||
| 2189 | |||
| 2190 | i = 0; | ||
| 2191 | printk("), "); | ||
| 2192 | printk("Capabilities=("); | ||
| 2193 | |||
| 2194 | if (!ioc->hide_ir_msg) { | ||
| 2195 | if (ioc->facts.IOCCapabilities & | ||
| 2196 | MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID) { | ||
| 2197 | printk("Raid"); | ||
| 2198 | i++; | ||
| 2199 | } | ||
| 2200 | } | ||
| 2201 | |||
| 2202 | if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR) { | ||
| 2203 | printk("%sTLR", i ? "," : ""); | ||
| 2204 | i++; | ||
| 2205 | } | ||
| 2206 | |||
| 2207 | if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_MULTICAST) { | ||
| 2208 | printk("%sMulticast", i ? "," : ""); | ||
| 2209 | i++; | ||
| 2210 | } | ||
| 2211 | |||
| 2212 | if (ioc->facts.IOCCapabilities & | ||
| 2213 | MPI2_IOCFACTS_CAPABILITY_BIDIRECTIONAL_TARGET) { | ||
| 2214 | printk("%sBIDI Target", i ? "," : ""); | ||
| 2215 | i++; | ||
| 2216 | } | ||
| 2217 | |||
| 2218 | if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_EEDP) { | ||
| 2219 | printk("%sEEDP", i ? "," : ""); | ||
| 2220 | i++; | ||
| 2221 | } | ||
| 2222 | |||
| 2223 | if (ioc->facts.IOCCapabilities & | ||
| 2224 | MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER) { | ||
| 2225 | printk("%sSnapshot Buffer", i ? "," : ""); | ||
| 2226 | i++; | ||
| 2227 | } | ||
| 2228 | |||
| 2229 | if (ioc->facts.IOCCapabilities & | ||
| 2230 | MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER) { | ||
| 2231 | printk("%sDiag Trace Buffer", i ? "," : ""); | ||
| 2232 | i++; | ||
| 2233 | } | ||
| 2234 | |||
| 2235 | if (ioc->facts.IOCCapabilities & | ||
| 2236 | MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER) { | ||
| 2237 | printk(KERN_INFO "%sDiag Extended Buffer", i ? "," : ""); | ||
| 2238 | i++; | ||
| 2239 | } | ||
| 2240 | |||
| 2241 | if (ioc->facts.IOCCapabilities & | ||
| 2242 | MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING) { | ||
| 2243 | printk("%sTask Set Full", i ? "," : ""); | ||
| 2244 | i++; | ||
| 2245 | } | ||
| 2246 | |||
| 2247 | iounit_pg1_flags = le32_to_cpu(ioc->iounit_pg1.Flags); | ||
| 2248 | if (!(iounit_pg1_flags & MPI2_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE)) { | ||
| 2249 | printk("%sNCQ", i ? "," : ""); | ||
| 2250 | i++; | ||
| 2251 | } | ||
| 2252 | |||
| 2253 | printk(")\n"); | ||
| 2254 | } | ||
| 2255 | |||
| 2256 | /** | ||
| 2257 | * mpt2sas_base_update_missing_delay - change the missing delay timers | ||
| 2258 | * @ioc: per adapter object | ||
| 2259 | * @device_missing_delay: amount of time till device is reported missing | ||
| 2260 | * @io_missing_delay: interval IO is returned when there is a missing device | ||
| 2261 | * | ||
| 2262 | * Return nothing. | ||
| 2263 | * | ||
| 2264 | * Passed on the command line, this function will modify the device missing | ||
| 2265 | * delay, as well as the io missing delay. This should be called at driver | ||
| 2266 | * load time. | ||
| 2267 | */ | ||
| 2268 | void | ||
| 2269 | mpt2sas_base_update_missing_delay(struct MPT2SAS_ADAPTER *ioc, | ||
| 2270 | u16 device_missing_delay, u8 io_missing_delay) | ||
| 2271 | { | ||
| 2272 | u16 dmd, dmd_new, dmd_orignal; | ||
| 2273 | u8 io_missing_delay_original; | ||
| 2274 | u16 sz; | ||
| 2275 | Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL; | ||
| 2276 | Mpi2ConfigReply_t mpi_reply; | ||
| 2277 | u8 num_phys = 0; | ||
| 2278 | u16 ioc_status; | ||
| 2279 | |||
| 2280 | mpt2sas_config_get_number_hba_phys(ioc, &num_phys); | ||
| 2281 | if (!num_phys) | ||
| 2282 | return; | ||
| 2283 | |||
| 2284 | sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (num_phys * | ||
| 2285 | sizeof(Mpi2SasIOUnit1PhyData_t)); | ||
| 2286 | sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL); | ||
| 2287 | if (!sas_iounit_pg1) { | ||
| 2288 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 2289 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 2290 | goto out; | ||
| 2291 | } | ||
| 2292 | if ((mpt2sas_config_get_sas_iounit_pg1(ioc, &mpi_reply, | ||
| 2293 | sas_iounit_pg1, sz))) { | ||
| 2294 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 2295 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 2296 | goto out; | ||
| 2297 | } | ||
| 2298 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
| 2299 | MPI2_IOCSTATUS_MASK; | ||
| 2300 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { | ||
| 2301 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 2302 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 2303 | goto out; | ||
| 2304 | } | ||
| 2305 | |||
| 2306 | /* device missing delay */ | ||
| 2307 | dmd = sas_iounit_pg1->ReportDeviceMissingDelay; | ||
| 2308 | if (dmd & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16) | ||
| 2309 | dmd = (dmd & MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16; | ||
| 2310 | else | ||
| 2311 | dmd = dmd & MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK; | ||
| 2312 | dmd_orignal = dmd; | ||
| 2313 | if (device_missing_delay > 0x7F) { | ||
| 2314 | dmd = (device_missing_delay > 0x7F0) ? 0x7F0 : | ||
| 2315 | device_missing_delay; | ||
| 2316 | dmd = dmd / 16; | ||
| 2317 | dmd |= MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16; | ||
| 2318 | } else | ||
| 2319 | dmd = device_missing_delay; | ||
| 2320 | sas_iounit_pg1->ReportDeviceMissingDelay = dmd; | ||
| 2321 | |||
| 2322 | /* io missing delay */ | ||
| 2323 | io_missing_delay_original = sas_iounit_pg1->IODeviceMissingDelay; | ||
| 2324 | sas_iounit_pg1->IODeviceMissingDelay = io_missing_delay; | ||
| 2325 | |||
| 2326 | if (!mpt2sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1, | ||
| 2327 | sz)) { | ||
| 2328 | if (dmd & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16) | ||
| 2329 | dmd_new = (dmd & | ||
| 2330 | MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16; | ||
| 2331 | else | ||
| 2332 | dmd_new = | ||
| 2333 | dmd & MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK; | ||
| 2334 | printk(MPT2SAS_INFO_FMT "device_missing_delay: old(%d), " | ||
| 2335 | "new(%d)\n", ioc->name, dmd_orignal, dmd_new); | ||
| 2336 | printk(MPT2SAS_INFO_FMT "ioc_missing_delay: old(%d), " | ||
| 2337 | "new(%d)\n", ioc->name, io_missing_delay_original, | ||
| 2338 | io_missing_delay); | ||
| 2339 | ioc->device_missing_delay = dmd_new; | ||
| 2340 | ioc->io_missing_delay = io_missing_delay; | ||
| 2341 | } | ||
| 2342 | |||
| 2343 | out: | ||
| 2344 | kfree(sas_iounit_pg1); | ||
| 2345 | } | ||
| 2346 | |||
| 2347 | /** | ||
| 2348 | * _base_static_config_pages - static start of day config pages | ||
| 2349 | * @ioc: per adapter object | ||
| 2350 | * | ||
| 2351 | * Return nothing. | ||
| 2352 | */ | ||
| 2353 | static void | ||
| 2354 | _base_static_config_pages(struct MPT2SAS_ADAPTER *ioc) | ||
| 2355 | { | ||
| 2356 | Mpi2ConfigReply_t mpi_reply; | ||
| 2357 | u32 iounit_pg1_flags; | ||
| 2358 | |||
| 2359 | mpt2sas_config_get_manufacturing_pg0(ioc, &mpi_reply, &ioc->manu_pg0); | ||
| 2360 | if (ioc->ir_firmware) | ||
| 2361 | mpt2sas_config_get_manufacturing_pg10(ioc, &mpi_reply, | ||
| 2362 | &ioc->manu_pg10); | ||
| 2363 | mpt2sas_config_get_bios_pg2(ioc, &mpi_reply, &ioc->bios_pg2); | ||
| 2364 | mpt2sas_config_get_bios_pg3(ioc, &mpi_reply, &ioc->bios_pg3); | ||
| 2365 | mpt2sas_config_get_ioc_pg8(ioc, &mpi_reply, &ioc->ioc_pg8); | ||
| 2366 | mpt2sas_config_get_iounit_pg0(ioc, &mpi_reply, &ioc->iounit_pg0); | ||
| 2367 | mpt2sas_config_get_iounit_pg1(ioc, &mpi_reply, &ioc->iounit_pg1); | ||
| 2368 | mpt2sas_config_get_iounit_pg8(ioc, &mpi_reply, &ioc->iounit_pg8); | ||
| 2369 | _base_display_ioc_capabilities(ioc); | ||
| 2370 | |||
| 2371 | /* | ||
| 2372 | * Enable task_set_full handling in iounit_pg1 when the | ||
| 2373 | * facts capabilities indicate that its supported. | ||
| 2374 | */ | ||
| 2375 | iounit_pg1_flags = le32_to_cpu(ioc->iounit_pg1.Flags); | ||
| 2376 | if ((ioc->facts.IOCCapabilities & | ||
| 2377 | MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING)) | ||
| 2378 | iounit_pg1_flags &= | ||
| 2379 | ~MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING; | ||
| 2380 | else | ||
| 2381 | iounit_pg1_flags |= | ||
| 2382 | MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING; | ||
| 2383 | ioc->iounit_pg1.Flags = cpu_to_le32(iounit_pg1_flags); | ||
| 2384 | mpt2sas_config_set_iounit_pg1(ioc, &mpi_reply, &ioc->iounit_pg1); | ||
| 2385 | |||
| 2386 | if (ioc->iounit_pg8.NumSensors) | ||
| 2387 | ioc->temp_sensors_count = ioc->iounit_pg8.NumSensors; | ||
| 2388 | } | ||
| 2389 | |||
| 2390 | /** | ||
| 2391 | * _base_release_memory_pools - release memory | ||
| 2392 | * @ioc: per adapter object | ||
| 2393 | * | ||
| 2394 | * Free memory allocated from _base_allocate_memory_pools. | ||
| 2395 | * | ||
| 2396 | * Return nothing. | ||
| 2397 | */ | ||
| 2398 | static void | ||
| 2399 | _base_release_memory_pools(struct MPT2SAS_ADAPTER *ioc) | ||
| 2400 | { | ||
| 2401 | int i = 0; | ||
| 2402 | struct reply_post_struct *rps; | ||
| 2403 | |||
| 2404 | dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | ||
| 2405 | __func__)); | ||
| 2406 | |||
| 2407 | if (ioc->request) { | ||
| 2408 | pci_free_consistent(ioc->pdev, ioc->request_dma_sz, | ||
| 2409 | ioc->request, ioc->request_dma); | ||
| 2410 | dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "request_pool(0x%p)" | ||
| 2411 | ": free\n", ioc->name, ioc->request)); | ||
| 2412 | ioc->request = NULL; | ||
| 2413 | } | ||
| 2414 | |||
| 2415 | if (ioc->sense) { | ||
| 2416 | pci_pool_free(ioc->sense_dma_pool, ioc->sense, ioc->sense_dma); | ||
| 2417 | if (ioc->sense_dma_pool) | ||
| 2418 | pci_pool_destroy(ioc->sense_dma_pool); | ||
| 2419 | dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "sense_pool(0x%p)" | ||
| 2420 | ": free\n", ioc->name, ioc->sense)); | ||
| 2421 | ioc->sense = NULL; | ||
| 2422 | } | ||
| 2423 | |||
| 2424 | if (ioc->reply) { | ||
| 2425 | pci_pool_free(ioc->reply_dma_pool, ioc->reply, ioc->reply_dma); | ||
| 2426 | if (ioc->reply_dma_pool) | ||
| 2427 | pci_pool_destroy(ioc->reply_dma_pool); | ||
| 2428 | dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_pool(0x%p)" | ||
| 2429 | ": free\n", ioc->name, ioc->reply)); | ||
| 2430 | ioc->reply = NULL; | ||
| 2431 | } | ||
| 2432 | |||
| 2433 | if (ioc->reply_free) { | ||
| 2434 | pci_pool_free(ioc->reply_free_dma_pool, ioc->reply_free, | ||
| 2435 | ioc->reply_free_dma); | ||
| 2436 | if (ioc->reply_free_dma_pool) | ||
| 2437 | pci_pool_destroy(ioc->reply_free_dma_pool); | ||
| 2438 | dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_free_pool" | ||
| 2439 | "(0x%p): free\n", ioc->name, ioc->reply_free)); | ||
| 2440 | ioc->reply_free = NULL; | ||
| 2441 | } | ||
| 2442 | |||
| 2443 | if (ioc->reply_post) { | ||
| 2444 | do { | ||
| 2445 | rps = &ioc->reply_post[i]; | ||
| 2446 | if (rps->reply_post_free) { | ||
| 2447 | pci_pool_free( | ||
| 2448 | ioc->reply_post_free_dma_pool, | ||
| 2449 | rps->reply_post_free, | ||
| 2450 | rps->reply_post_free_dma); | ||
| 2451 | dexitprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 2452 | "reply_post_free_pool(0x%p): free\n", | ||
| 2453 | ioc->name, rps->reply_post_free)); | ||
| 2454 | rps->reply_post_free = NULL; | ||
| 2455 | } | ||
| 2456 | } while (ioc->rdpq_array_enable && | ||
| 2457 | (++i < ioc->reply_queue_count)); | ||
| 2458 | |||
| 2459 | if (ioc->reply_post_free_dma_pool) | ||
| 2460 | pci_pool_destroy(ioc->reply_post_free_dma_pool); | ||
| 2461 | kfree(ioc->reply_post); | ||
| 2462 | } | ||
| 2463 | |||
| 2464 | if (ioc->config_page) { | ||
| 2465 | dexitprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 2466 | "config_page(0x%p): free\n", ioc->name, | ||
| 2467 | ioc->config_page)); | ||
| 2468 | pci_free_consistent(ioc->pdev, ioc->config_page_sz, | ||
| 2469 | ioc->config_page, ioc->config_page_dma); | ||
| 2470 | } | ||
| 2471 | |||
| 2472 | if (ioc->scsi_lookup) { | ||
| 2473 | free_pages((ulong)ioc->scsi_lookup, ioc->scsi_lookup_pages); | ||
| 2474 | ioc->scsi_lookup = NULL; | ||
| 2475 | } | ||
| 2476 | kfree(ioc->hpr_lookup); | ||
| 2477 | kfree(ioc->internal_lookup); | ||
| 2478 | if (ioc->chain_lookup) { | ||
| 2479 | for (i = 0; i < ioc->chain_depth; i++) { | ||
| 2480 | if (ioc->chain_lookup[i].chain_buffer) | ||
| 2481 | pci_pool_free(ioc->chain_dma_pool, | ||
| 2482 | ioc->chain_lookup[i].chain_buffer, | ||
| 2483 | ioc->chain_lookup[i].chain_buffer_dma); | ||
| 2484 | } | ||
| 2485 | if (ioc->chain_dma_pool) | ||
| 2486 | pci_pool_destroy(ioc->chain_dma_pool); | ||
| 2487 | free_pages((ulong)ioc->chain_lookup, ioc->chain_pages); | ||
| 2488 | ioc->chain_lookup = NULL; | ||
| 2489 | } | ||
| 2490 | } | ||
| 2491 | |||
| 2492 | |||
| 2493 | /** | ||
| 2494 | * _base_allocate_memory_pools - allocate start of day memory pools | ||
| 2495 | * @ioc: per adapter object | ||
| 2496 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | ||
| 2497 | * | ||
| 2498 | * Returns 0 success, anything else error | ||
| 2499 | */ | ||
| 2500 | static int | ||
| 2501 | _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | ||
| 2502 | { | ||
| 2503 | struct mpt2sas_facts *facts; | ||
| 2504 | u16 max_sge_elements; | ||
| 2505 | u16 chains_needed_per_io; | ||
| 2506 | u32 sz, total_sz, reply_post_free_sz; | ||
| 2507 | u32 retry_sz; | ||
| 2508 | u16 max_request_credit; | ||
| 2509 | int i; | ||
| 2510 | |||
| 2511 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | ||
| 2512 | __func__)); | ||
| 2513 | |||
| 2514 | retry_sz = 0; | ||
| 2515 | facts = &ioc->facts; | ||
| 2516 | |||
| 2517 | /* command line tunables for max sgl entries */ | ||
| 2518 | if (max_sgl_entries != -1) { | ||
| 2519 | ioc->shost->sg_tablesize = min_t(unsigned short, | ||
| 2520 | max_sgl_entries, SCSI_MAX_SG_CHAIN_SEGMENTS); | ||
| 2521 | if (ioc->shost->sg_tablesize > MPT2SAS_SG_DEPTH) | ||
| 2522 | printk(MPT2SAS_WARN_FMT | ||
| 2523 | "sg_tablesize(%u) is bigger than kernel defined" | ||
| 2524 | " SCSI_MAX_SG_SEGMENTS(%u)\n", ioc->name, | ||
| 2525 | ioc->shost->sg_tablesize, MPT2SAS_SG_DEPTH); | ||
| 2526 | } else { | ||
| 2527 | ioc->shost->sg_tablesize = MPT2SAS_SG_DEPTH; | ||
| 2528 | } | ||
| 2529 | |||
| 2530 | /* command line tunables for max controller queue depth */ | ||
| 2531 | if (max_queue_depth != -1 && max_queue_depth != 0) { | ||
| 2532 | max_request_credit = min_t(u16, max_queue_depth + | ||
| 2533 | ioc->hi_priority_depth + ioc->internal_depth, | ||
| 2534 | facts->RequestCredit); | ||
| 2535 | if (max_request_credit > MAX_HBA_QUEUE_DEPTH) | ||
| 2536 | max_request_credit = MAX_HBA_QUEUE_DEPTH; | ||
| 2537 | } else | ||
| 2538 | max_request_credit = min_t(u16, facts->RequestCredit, | ||
| 2539 | MAX_HBA_QUEUE_DEPTH); | ||
| 2540 | |||
| 2541 | ioc->hba_queue_depth = max_request_credit; | ||
| 2542 | ioc->hi_priority_depth = facts->HighPriorityCredit; | ||
| 2543 | ioc->internal_depth = ioc->hi_priority_depth + 5; | ||
| 2544 | |||
| 2545 | /* request frame size */ | ||
| 2546 | ioc->request_sz = facts->IOCRequestFrameSize * 4; | ||
| 2547 | |||
| 2548 | /* reply frame size */ | ||
| 2549 | ioc->reply_sz = facts->ReplyFrameSize * 4; | ||
| 2550 | |||
| 2551 | retry_allocation: | ||
| 2552 | total_sz = 0; | ||
| 2553 | /* calculate number of sg elements left over in the 1st frame */ | ||
| 2554 | max_sge_elements = ioc->request_sz - ((sizeof(Mpi2SCSIIORequest_t) - | ||
| 2555 | sizeof(Mpi2SGEIOUnion_t)) + ioc->sge_size); | ||
| 2556 | ioc->max_sges_in_main_message = max_sge_elements/ioc->sge_size; | ||
| 2557 | |||
| 2558 | /* now do the same for a chain buffer */ | ||
| 2559 | max_sge_elements = ioc->request_sz - ioc->sge_size; | ||
| 2560 | ioc->max_sges_in_chain_message = max_sge_elements/ioc->sge_size; | ||
| 2561 | |||
| 2562 | ioc->chain_offset_value_for_main_message = | ||
| 2563 | ((sizeof(Mpi2SCSIIORequest_t) - sizeof(Mpi2SGEIOUnion_t)) + | ||
| 2564 | (ioc->max_sges_in_chain_message * ioc->sge_size)) / 4; | ||
| 2565 | |||
| 2566 | /* | ||
| 2567 | * MPT2SAS_SG_DEPTH = CONFIG_FUSION_MAX_SGE | ||
| 2568 | */ | ||
| 2569 | chains_needed_per_io = ((ioc->shost->sg_tablesize - | ||
| 2570 | ioc->max_sges_in_main_message)/ioc->max_sges_in_chain_message) | ||
| 2571 | + 1; | ||
| 2572 | if (chains_needed_per_io > facts->MaxChainDepth) { | ||
| 2573 | chains_needed_per_io = facts->MaxChainDepth; | ||
| 2574 | ioc->shost->sg_tablesize = min_t(u16, | ||
| 2575 | ioc->max_sges_in_main_message + (ioc->max_sges_in_chain_message | ||
| 2576 | * chains_needed_per_io), ioc->shost->sg_tablesize); | ||
| 2577 | } | ||
| 2578 | ioc->chains_needed_per_io = chains_needed_per_io; | ||
| 2579 | |||
| 2580 | /* reply free queue sizing - taking into account for 64 FW events */ | ||
| 2581 | ioc->reply_free_queue_depth = ioc->hba_queue_depth + 64; | ||
| 2582 | |||
| 2583 | /* calculate reply descriptor post queue depth */ | ||
| 2584 | ioc->reply_post_queue_depth = ioc->hba_queue_depth + | ||
| 2585 | ioc->reply_free_queue_depth + 1; | ||
| 2586 | /* align the reply post queue on the next 16 count boundary */ | ||
| 2587 | if (ioc->reply_post_queue_depth % 16) | ||
| 2588 | ioc->reply_post_queue_depth += 16 - | ||
| 2589 | (ioc->reply_post_queue_depth % 16); | ||
| 2590 | |||
| 2591 | |||
| 2592 | if (ioc->reply_post_queue_depth > | ||
| 2593 | facts->MaxReplyDescriptorPostQueueDepth) { | ||
| 2594 | ioc->reply_post_queue_depth = | ||
| 2595 | facts->MaxReplyDescriptorPostQueueDepth - | ||
| 2596 | (facts->MaxReplyDescriptorPostQueueDepth % 16); | ||
| 2597 | ioc->hba_queue_depth = | ||
| 2598 | ((ioc->reply_post_queue_depth - 64) / 2) - 1; | ||
| 2599 | ioc->reply_free_queue_depth = ioc->hba_queue_depth + 64; | ||
| 2600 | } | ||
| 2601 | |||
| 2602 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scatter gather: " | ||
| 2603 | "sge_in_main_msg(%d), sge_per_chain(%d), sge_per_io(%d), " | ||
| 2604 | "chains_per_io(%d)\n", ioc->name, ioc->max_sges_in_main_message, | ||
| 2605 | ioc->max_sges_in_chain_message, ioc->shost->sg_tablesize, | ||
| 2606 | ioc->chains_needed_per_io)); | ||
| 2607 | |||
| 2608 | /* reply post queue, 16 byte align */ | ||
| 2609 | reply_post_free_sz = ioc->reply_post_queue_depth * | ||
| 2610 | sizeof(Mpi2DefaultReplyDescriptor_t); | ||
| 2611 | |||
| 2612 | sz = reply_post_free_sz; | ||
| 2613 | if (_base_is_controller_msix_enabled(ioc) && !ioc->rdpq_array_enable) | ||
| 2614 | sz *= ioc->reply_queue_count; | ||
| 2615 | |||
| 2616 | ioc->reply_post = kcalloc((ioc->rdpq_array_enable) ? | ||
| 2617 | (ioc->reply_queue_count):1, | ||
| 2618 | sizeof(struct reply_post_struct), GFP_KERNEL); | ||
| 2619 | |||
| 2620 | if (!ioc->reply_post) { | ||
| 2621 | printk(MPT2SAS_ERR_FMT "reply_post_free pool: kcalloc failed\n", | ||
| 2622 | ioc->name); | ||
| 2623 | goto out; | ||
| 2624 | } | ||
| 2625 | ioc->reply_post_free_dma_pool = pci_pool_create("reply_post_free pool", | ||
| 2626 | ioc->pdev, sz, 16, 0); | ||
| 2627 | if (!ioc->reply_post_free_dma_pool) { | ||
| 2628 | printk(MPT2SAS_ERR_FMT | ||
| 2629 | "reply_post_free pool: pci_pool_create failed\n", | ||
| 2630 | ioc->name); | ||
| 2631 | goto out; | ||
| 2632 | } | ||
| 2633 | i = 0; | ||
| 2634 | do { | ||
| 2635 | ioc->reply_post[i].reply_post_free = | ||
| 2636 | pci_pool_alloc(ioc->reply_post_free_dma_pool, | ||
| 2637 | GFP_KERNEL, | ||
| 2638 | &ioc->reply_post[i].reply_post_free_dma); | ||
| 2639 | if (!ioc->reply_post[i].reply_post_free) { | ||
| 2640 | printk(MPT2SAS_ERR_FMT | ||
| 2641 | "reply_post_free pool: pci_pool_alloc failed\n", | ||
| 2642 | ioc->name); | ||
| 2643 | goto out; | ||
| 2644 | } | ||
| 2645 | memset(ioc->reply_post[i].reply_post_free, 0, sz); | ||
| 2646 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 2647 | "reply post free pool (0x%p): depth(%d)," | ||
| 2648 | "element_size(%d), pool_size(%d kB)\n", ioc->name, | ||
| 2649 | ioc->reply_post[i].reply_post_free, | ||
| 2650 | ioc->reply_post_queue_depth, 8, sz/1024)); | ||
| 2651 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 2652 | "reply_post_free_dma = (0x%llx)\n", ioc->name, | ||
| 2653 | (unsigned long long) | ||
| 2654 | ioc->reply_post[i].reply_post_free_dma)); | ||
| 2655 | total_sz += sz; | ||
| 2656 | } while (ioc->rdpq_array_enable && (++i < ioc->reply_queue_count)); | ||
| 2657 | |||
| 2658 | if (ioc->dma_mask == 64) { | ||
| 2659 | if (_base_change_consistent_dma_mask(ioc, ioc->pdev) != 0) { | ||
| 2660 | printk(MPT2SAS_WARN_FMT | ||
| 2661 | "no suitable consistent DMA mask for %s\n", | ||
| 2662 | ioc->name, pci_name(ioc->pdev)); | ||
| 2663 | goto out; | ||
| 2664 | } | ||
| 2665 | } | ||
| 2666 | |||
| 2667 | ioc->scsiio_depth = ioc->hba_queue_depth - | ||
| 2668 | ioc->hi_priority_depth - ioc->internal_depth; | ||
| 2669 | |||
| 2670 | /* set the scsi host can_queue depth | ||
| 2671 | * with some internal commands that could be outstanding | ||
| 2672 | */ | ||
| 2673 | ioc->shost->can_queue = ioc->scsiio_depth; | ||
| 2674 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scsi host: " | ||
| 2675 | "can_queue depth (%d)\n", ioc->name, ioc->shost->can_queue)); | ||
| 2676 | |||
| 2677 | /* contiguous pool for request and chains, 16 byte align, one extra " | ||
| 2678 | * "frame for smid=0 | ||
| 2679 | */ | ||
| 2680 | ioc->chain_depth = ioc->chains_needed_per_io * ioc->scsiio_depth; | ||
| 2681 | sz = ((ioc->scsiio_depth + 1) * ioc->request_sz); | ||
| 2682 | |||
| 2683 | /* hi-priority queue */ | ||
| 2684 | sz += (ioc->hi_priority_depth * ioc->request_sz); | ||
| 2685 | |||
| 2686 | /* internal queue */ | ||
| 2687 | sz += (ioc->internal_depth * ioc->request_sz); | ||
| 2688 | |||
| 2689 | ioc->request_dma_sz = sz; | ||
| 2690 | ioc->request = pci_alloc_consistent(ioc->pdev, sz, &ioc->request_dma); | ||
| 2691 | if (!ioc->request) { | ||
| 2692 | printk(MPT2SAS_ERR_FMT "request pool: pci_alloc_consistent " | ||
| 2693 | "failed: hba_depth(%d), chains_per_io(%d), frame_sz(%d), " | ||
| 2694 | "total(%d kB)\n", ioc->name, ioc->hba_queue_depth, | ||
| 2695 | ioc->chains_needed_per_io, ioc->request_sz, sz/1024); | ||
| 2696 | if (ioc->scsiio_depth < MPT2SAS_SAS_QUEUE_DEPTH) | ||
| 2697 | goto out; | ||
| 2698 | retry_sz += 64; | ||
| 2699 | ioc->hba_queue_depth = max_request_credit - retry_sz; | ||
| 2700 | goto retry_allocation; | ||
| 2701 | } | ||
| 2702 | |||
| 2703 | if (retry_sz) | ||
| 2704 | printk(MPT2SAS_ERR_FMT "request pool: pci_alloc_consistent " | ||
| 2705 | "succeed: hba_depth(%d), chains_per_io(%d), frame_sz(%d), " | ||
| 2706 | "total(%d kb)\n", ioc->name, ioc->hba_queue_depth, | ||
| 2707 | ioc->chains_needed_per_io, ioc->request_sz, sz/1024); | ||
| 2708 | |||
| 2709 | |||
| 2710 | /* hi-priority queue */ | ||
| 2711 | ioc->hi_priority = ioc->request + ((ioc->scsiio_depth + 1) * | ||
| 2712 | ioc->request_sz); | ||
| 2713 | ioc->hi_priority_dma = ioc->request_dma + ((ioc->scsiio_depth + 1) * | ||
| 2714 | ioc->request_sz); | ||
| 2715 | |||
| 2716 | /* internal queue */ | ||
| 2717 | ioc->internal = ioc->hi_priority + (ioc->hi_priority_depth * | ||
| 2718 | ioc->request_sz); | ||
| 2719 | ioc->internal_dma = ioc->hi_priority_dma + (ioc->hi_priority_depth * | ||
| 2720 | ioc->request_sz); | ||
| 2721 | |||
| 2722 | |||
| 2723 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request pool(0x%p): " | ||
| 2724 | "depth(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name, | ||
| 2725 | ioc->request, ioc->hba_queue_depth, ioc->request_sz, | ||
| 2726 | (ioc->hba_queue_depth * ioc->request_sz)/1024)); | ||
| 2727 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request pool: dma(0x%llx)\n", | ||
| 2728 | ioc->name, (unsigned long long) ioc->request_dma)); | ||
| 2729 | total_sz += sz; | ||
| 2730 | |||
| 2731 | sz = ioc->scsiio_depth * sizeof(struct scsiio_tracker); | ||
| 2732 | ioc->scsi_lookup_pages = get_order(sz); | ||
| 2733 | ioc->scsi_lookup = (struct scsiio_tracker *)__get_free_pages( | ||
| 2734 | GFP_KERNEL, ioc->scsi_lookup_pages); | ||
| 2735 | if (!ioc->scsi_lookup) { | ||
| 2736 | printk(MPT2SAS_ERR_FMT "scsi_lookup: get_free_pages failed, " | ||
| 2737 | "sz(%d)\n", ioc->name, (int)sz); | ||
| 2738 | goto out; | ||
| 2739 | } | ||
| 2740 | |||
| 2741 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scsiio(0x%p): " | ||
| 2742 | "depth(%d)\n", ioc->name, ioc->request, | ||
| 2743 | ioc->scsiio_depth)); | ||
| 2744 | |||
| 2745 | ioc->chain_depth = min_t(u32, ioc->chain_depth, MAX_CHAIN_DEPTH); | ||
| 2746 | sz = ioc->chain_depth * sizeof(struct chain_tracker); | ||
| 2747 | ioc->chain_pages = get_order(sz); | ||
| 2748 | |||
| 2749 | ioc->chain_lookup = (struct chain_tracker *)__get_free_pages( | ||
| 2750 | GFP_KERNEL, ioc->chain_pages); | ||
| 2751 | if (!ioc->chain_lookup) { | ||
| 2752 | printk(MPT2SAS_ERR_FMT "chain_lookup: get_free_pages failed, " | ||
| 2753 | "sz(%d)\n", ioc->name, (int)sz); | ||
| 2754 | goto out; | ||
| 2755 | } | ||
| 2756 | ioc->chain_dma_pool = pci_pool_create("chain pool", ioc->pdev, | ||
| 2757 | ioc->request_sz, 16, 0); | ||
| 2758 | if (!ioc->chain_dma_pool) { | ||
| 2759 | printk(MPT2SAS_ERR_FMT "chain_dma_pool: pci_pool_create " | ||
| 2760 | "failed\n", ioc->name); | ||
| 2761 | goto out; | ||
| 2762 | } | ||
| 2763 | for (i = 0; i < ioc->chain_depth; i++) { | ||
| 2764 | ioc->chain_lookup[i].chain_buffer = pci_pool_alloc( | ||
| 2765 | ioc->chain_dma_pool , GFP_KERNEL, | ||
| 2766 | &ioc->chain_lookup[i].chain_buffer_dma); | ||
| 2767 | if (!ioc->chain_lookup[i].chain_buffer) { | ||
| 2768 | ioc->chain_depth = i; | ||
| 2769 | goto chain_done; | ||
| 2770 | } | ||
| 2771 | total_sz += ioc->request_sz; | ||
| 2772 | } | ||
| 2773 | chain_done: | ||
| 2774 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "chain pool depth" | ||
| 2775 | "(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name, | ||
| 2776 | ioc->chain_depth, ioc->request_sz, ((ioc->chain_depth * | ||
| 2777 | ioc->request_sz))/1024)); | ||
| 2778 | |||
| 2779 | /* initialize hi-priority queue smid's */ | ||
| 2780 | ioc->hpr_lookup = kcalloc(ioc->hi_priority_depth, | ||
| 2781 | sizeof(struct request_tracker), GFP_KERNEL); | ||
| 2782 | if (!ioc->hpr_lookup) { | ||
| 2783 | printk(MPT2SAS_ERR_FMT "hpr_lookup: kcalloc failed\n", | ||
| 2784 | ioc->name); | ||
| 2785 | goto out; | ||
| 2786 | } | ||
| 2787 | ioc->hi_priority_smid = ioc->scsiio_depth + 1; | ||
| 2788 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "hi_priority(0x%p): " | ||
| 2789 | "depth(%d), start smid(%d)\n", ioc->name, ioc->hi_priority, | ||
| 2790 | ioc->hi_priority_depth, ioc->hi_priority_smid)); | ||
| 2791 | |||
| 2792 | /* initialize internal queue smid's */ | ||
| 2793 | ioc->internal_lookup = kcalloc(ioc->internal_depth, | ||
| 2794 | sizeof(struct request_tracker), GFP_KERNEL); | ||
| 2795 | if (!ioc->internal_lookup) { | ||
| 2796 | printk(MPT2SAS_ERR_FMT "internal_lookup: kcalloc failed\n", | ||
| 2797 | ioc->name); | ||
| 2798 | goto out; | ||
| 2799 | } | ||
| 2800 | ioc->internal_smid = ioc->hi_priority_smid + ioc->hi_priority_depth; | ||
| 2801 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "internal(0x%p): " | ||
| 2802 | "depth(%d), start smid(%d)\n", ioc->name, ioc->internal, | ||
| 2803 | ioc->internal_depth, ioc->internal_smid)); | ||
| 2804 | |||
| 2805 | /* sense buffers, 4 byte align */ | ||
| 2806 | sz = ioc->scsiio_depth * SCSI_SENSE_BUFFERSIZE; | ||
| 2807 | ioc->sense_dma_pool = pci_pool_create("sense pool", ioc->pdev, sz, 4, | ||
| 2808 | 0); | ||
| 2809 | if (!ioc->sense_dma_pool) { | ||
| 2810 | printk(MPT2SAS_ERR_FMT "sense pool: pci_pool_create failed\n", | ||
| 2811 | ioc->name); | ||
| 2812 | goto out; | ||
| 2813 | } | ||
| 2814 | ioc->sense = pci_pool_alloc(ioc->sense_dma_pool , GFP_KERNEL, | ||
| 2815 | &ioc->sense_dma); | ||
| 2816 | if (!ioc->sense) { | ||
| 2817 | printk(MPT2SAS_ERR_FMT "sense pool: pci_pool_alloc failed\n", | ||
| 2818 | ioc->name); | ||
| 2819 | goto out; | ||
| 2820 | } | ||
| 2821 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 2822 | "sense pool(0x%p): depth(%d), element_size(%d), pool_size" | ||
| 2823 | "(%d kB)\n", ioc->name, ioc->sense, ioc->scsiio_depth, | ||
| 2824 | SCSI_SENSE_BUFFERSIZE, sz/1024)); | ||
| 2825 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "sense_dma(0x%llx)\n", | ||
| 2826 | ioc->name, (unsigned long long)ioc->sense_dma)); | ||
| 2827 | total_sz += sz; | ||
| 2828 | |||
| 2829 | /* reply pool, 4 byte align */ | ||
| 2830 | sz = ioc->reply_free_queue_depth * ioc->reply_sz; | ||
| 2831 | ioc->reply_dma_pool = pci_pool_create("reply pool", ioc->pdev, sz, 4, | ||
| 2832 | 0); | ||
| 2833 | if (!ioc->reply_dma_pool) { | ||
| 2834 | printk(MPT2SAS_ERR_FMT "reply pool: pci_pool_create failed\n", | ||
| 2835 | ioc->name); | ||
| 2836 | goto out; | ||
| 2837 | } | ||
| 2838 | ioc->reply = pci_pool_alloc(ioc->reply_dma_pool , GFP_KERNEL, | ||
| 2839 | &ioc->reply_dma); | ||
| 2840 | if (!ioc->reply) { | ||
| 2841 | printk(MPT2SAS_ERR_FMT "reply pool: pci_pool_alloc failed\n", | ||
| 2842 | ioc->name); | ||
| 2843 | goto out; | ||
| 2844 | } | ||
| 2845 | ioc->reply_dma_min_address = (u32)(ioc->reply_dma); | ||
| 2846 | ioc->reply_dma_max_address = (u32)(ioc->reply_dma) + sz; | ||
| 2847 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply pool(0x%p): depth" | ||
| 2848 | "(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name, ioc->reply, | ||
| 2849 | ioc->reply_free_queue_depth, ioc->reply_sz, sz/1024)); | ||
| 2850 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_dma(0x%llx)\n", | ||
| 2851 | ioc->name, (unsigned long long)ioc->reply_dma)); | ||
| 2852 | total_sz += sz; | ||
| 2853 | |||
| 2854 | /* reply free queue, 16 byte align */ | ||
| 2855 | sz = ioc->reply_free_queue_depth * 4; | ||
| 2856 | ioc->reply_free_dma_pool = pci_pool_create("reply_free pool", | ||
| 2857 | ioc->pdev, sz, 16, 0); | ||
| 2858 | if (!ioc->reply_free_dma_pool) { | ||
| 2859 | printk(MPT2SAS_ERR_FMT "reply_free pool: pci_pool_create " | ||
| 2860 | "failed\n", ioc->name); | ||
| 2861 | goto out; | ||
| 2862 | } | ||
| 2863 | ioc->reply_free = pci_pool_alloc(ioc->reply_free_dma_pool , GFP_KERNEL, | ||
| 2864 | &ioc->reply_free_dma); | ||
| 2865 | if (!ioc->reply_free) { | ||
| 2866 | printk(MPT2SAS_ERR_FMT "reply_free pool: pci_pool_alloc " | ||
| 2867 | "failed\n", ioc->name); | ||
| 2868 | goto out; | ||
| 2869 | } | ||
| 2870 | memset(ioc->reply_free, 0, sz); | ||
| 2871 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_free pool(0x%p): " | ||
| 2872 | "depth(%d), element_size(%d), pool_size(%d kB)\n", ioc->name, | ||
| 2873 | ioc->reply_free, ioc->reply_free_queue_depth, 4, sz/1024)); | ||
| 2874 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_free_dma" | ||
| 2875 | "(0x%llx)\n", ioc->name, (unsigned long long)ioc->reply_free_dma)); | ||
| 2876 | total_sz += sz; | ||
| 2877 | |||
| 2878 | ioc->config_page_sz = 512; | ||
| 2879 | ioc->config_page = pci_alloc_consistent(ioc->pdev, | ||
| 2880 | ioc->config_page_sz, &ioc->config_page_dma); | ||
| 2881 | if (!ioc->config_page) { | ||
| 2882 | printk(MPT2SAS_ERR_FMT "config page: pci_pool_alloc " | ||
| 2883 | "failed\n", ioc->name); | ||
| 2884 | goto out; | ||
| 2885 | } | ||
| 2886 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "config page(0x%p): size" | ||
| 2887 | "(%d)\n", ioc->name, ioc->config_page, ioc->config_page_sz)); | ||
| 2888 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "config_page_dma" | ||
| 2889 | "(0x%llx)\n", ioc->name, (unsigned long long)ioc->config_page_dma)); | ||
| 2890 | total_sz += ioc->config_page_sz; | ||
| 2891 | |||
| 2892 | printk(MPT2SAS_INFO_FMT "Allocated physical memory: size(%d kB)\n", | ||
| 2893 | ioc->name, total_sz/1024); | ||
| 2894 | printk(MPT2SAS_INFO_FMT "Current Controller Queue Depth(%d), " | ||
| 2895 | "Max Controller Queue Depth(%d)\n", | ||
| 2896 | ioc->name, ioc->shost->can_queue, facts->RequestCredit); | ||
| 2897 | printk(MPT2SAS_INFO_FMT "Scatter Gather Elements per IO(%d)\n", | ||
| 2898 | ioc->name, ioc->shost->sg_tablesize); | ||
| 2899 | return 0; | ||
| 2900 | |||
| 2901 | out: | ||
| 2902 | return -ENOMEM; | ||
| 2903 | } | ||
| 2904 | |||
| 2905 | |||
| 2906 | /** | ||
| 2907 | * mpt2sas_base_get_iocstate - Get the current state of a MPT adapter. | ||
| 2908 | * @ioc: Pointer to MPT_ADAPTER structure | ||
| 2909 | * @cooked: Request raw or cooked IOC state | ||
| 2910 | * | ||
| 2911 | * Returns all IOC Doorbell register bits if cooked==0, else just the | ||
| 2912 | * Doorbell bits in MPI_IOC_STATE_MASK. | ||
| 2913 | */ | ||
| 2914 | u32 | ||
| 2915 | mpt2sas_base_get_iocstate(struct MPT2SAS_ADAPTER *ioc, int cooked) | ||
| 2916 | { | ||
| 2917 | u32 s, sc; | ||
| 2918 | |||
| 2919 | s = readl(&ioc->chip->Doorbell); | ||
| 2920 | sc = s & MPI2_IOC_STATE_MASK; | ||
| 2921 | return cooked ? sc : s; | ||
| 2922 | } | ||
| 2923 | |||
| 2924 | /** | ||
| 2925 | * _base_wait_on_iocstate - waiting on a particular ioc state | ||
| 2926 | * @ioc_state: controller state { READY, OPERATIONAL, or RESET } | ||
| 2927 | * @timeout: timeout in second | ||
| 2928 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | ||
| 2929 | * | ||
| 2930 | * Returns 0 for success, non-zero for failure. | ||
| 2931 | */ | ||
| 2932 | static int | ||
| 2933 | _base_wait_on_iocstate(struct MPT2SAS_ADAPTER *ioc, u32 ioc_state, int timeout, | ||
| 2934 | int sleep_flag) | ||
| 2935 | { | ||
| 2936 | u32 count, cntdn; | ||
| 2937 | u32 current_state; | ||
| 2938 | |||
| 2939 | count = 0; | ||
| 2940 | cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout; | ||
| 2941 | do { | ||
| 2942 | current_state = mpt2sas_base_get_iocstate(ioc, 1); | ||
| 2943 | if (current_state == ioc_state) | ||
| 2944 | return 0; | ||
| 2945 | if (count && current_state == MPI2_IOC_STATE_FAULT) | ||
| 2946 | break; | ||
| 2947 | if (sleep_flag == CAN_SLEEP) | ||
| 2948 | msleep(1); | ||
| 2949 | else | ||
| 2950 | udelay(500); | ||
| 2951 | count++; | ||
| 2952 | } while (--cntdn); | ||
| 2953 | |||
| 2954 | return current_state; | ||
| 2955 | } | ||
| 2956 | |||
| 2957 | /** | ||
| 2958 | * _base_wait_for_doorbell_int - waiting for controller interrupt(generated by | ||
| 2959 | * a write to the doorbell) | ||
| 2960 | * @ioc: per adapter object | ||
| 2961 | * @timeout: timeout in second | ||
| 2962 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | ||
| 2963 | * | ||
| 2964 | * Returns 0 for success, non-zero for failure. | ||
| 2965 | * | ||
| 2966 | * Notes: MPI2_HIS_IOC2SYS_DB_STATUS - set to one when IOC writes to doorbell. | ||
| 2967 | */ | ||
| 2968 | static int | ||
| 2969 | _base_wait_for_doorbell_int(struct MPT2SAS_ADAPTER *ioc, int timeout, | ||
| 2970 | int sleep_flag) | ||
| 2971 | { | ||
| 2972 | u32 cntdn, count; | ||
| 2973 | u32 int_status; | ||
| 2974 | |||
| 2975 | count = 0; | ||
| 2976 | cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout; | ||
| 2977 | do { | ||
| 2978 | int_status = readl(&ioc->chip->HostInterruptStatus); | ||
| 2979 | if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) { | ||
| 2980 | dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " | ||
| 2981 | "successful count(%d), timeout(%d)\n", ioc->name, | ||
| 2982 | __func__, count, timeout)); | ||
| 2983 | return 0; | ||
| 2984 | } | ||
| 2985 | if (sleep_flag == CAN_SLEEP) | ||
| 2986 | msleep(1); | ||
| 2987 | else | ||
| 2988 | udelay(500); | ||
| 2989 | count++; | ||
| 2990 | } while (--cntdn); | ||
| 2991 | |||
| 2992 | printk(MPT2SAS_ERR_FMT "%s: failed due to timeout count(%d), " | ||
| 2993 | "int_status(%x)!\n", ioc->name, __func__, count, int_status); | ||
| 2994 | return -EFAULT; | ||
| 2995 | } | ||
| 2996 | |||
| 2997 | /** | ||
| 2998 | * _base_wait_for_doorbell_ack - waiting for controller to read the doorbell. | ||
| 2999 | * @ioc: per adapter object | ||
| 3000 | * @timeout: timeout in second | ||
| 3001 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | ||
| 3002 | * | ||
| 3003 | * Returns 0 for success, non-zero for failure. | ||
| 3004 | * | ||
| 3005 | * Notes: MPI2_HIS_SYS2IOC_DB_STATUS - set to one when host writes to | ||
| 3006 | * doorbell. | ||
| 3007 | */ | ||
| 3008 | static int | ||
| 3009 | _base_wait_for_doorbell_ack(struct MPT2SAS_ADAPTER *ioc, int timeout, | ||
| 3010 | int sleep_flag) | ||
| 3011 | { | ||
| 3012 | u32 cntdn, count; | ||
| 3013 | u32 int_status; | ||
| 3014 | u32 doorbell; | ||
| 3015 | |||
| 3016 | count = 0; | ||
| 3017 | cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout; | ||
| 3018 | do { | ||
| 3019 | int_status = readl(&ioc->chip->HostInterruptStatus); | ||
| 3020 | if (!(int_status & MPI2_HIS_SYS2IOC_DB_STATUS)) { | ||
| 3021 | dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " | ||
| 3022 | "successful count(%d), timeout(%d)\n", ioc->name, | ||
| 3023 | __func__, count, timeout)); | ||
| 3024 | return 0; | ||
| 3025 | } else if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) { | ||
| 3026 | doorbell = readl(&ioc->chip->Doorbell); | ||
| 3027 | if ((doorbell & MPI2_IOC_STATE_MASK) == | ||
| 3028 | MPI2_IOC_STATE_FAULT) { | ||
| 3029 | mpt2sas_base_fault_info(ioc , doorbell); | ||
| 3030 | return -EFAULT; | ||
| 3031 | } | ||
| 3032 | } else if (int_status == 0xFFFFFFFF) | ||
| 3033 | goto out; | ||
| 3034 | |||
| 3035 | if (sleep_flag == CAN_SLEEP) | ||
| 3036 | msleep(1); | ||
| 3037 | else | ||
| 3038 | udelay(500); | ||
| 3039 | count++; | ||
| 3040 | } while (--cntdn); | ||
| 3041 | |||
| 3042 | out: | ||
| 3043 | printk(MPT2SAS_ERR_FMT "%s: failed due to timeout count(%d), " | ||
| 3044 | "int_status(%x)!\n", ioc->name, __func__, count, int_status); | ||
| 3045 | return -EFAULT; | ||
| 3046 | } | ||
| 3047 | |||
| 3048 | /** | ||
| 3049 | * _base_wait_for_doorbell_not_used - waiting for doorbell to not be in use | ||
| 3050 | * @ioc: per adapter object | ||
| 3051 | * @timeout: timeout in second | ||
| 3052 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | ||
| 3053 | * | ||
| 3054 | * Returns 0 for success, non-zero for failure. | ||
| 3055 | * | ||
| 3056 | */ | ||
| 3057 | static int | ||
| 3058 | _base_wait_for_doorbell_not_used(struct MPT2SAS_ADAPTER *ioc, int timeout, | ||
| 3059 | int sleep_flag) | ||
| 3060 | { | ||
| 3061 | u32 cntdn, count; | ||
| 3062 | u32 doorbell_reg; | ||
| 3063 | |||
| 3064 | count = 0; | ||
| 3065 | cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout; | ||
| 3066 | do { | ||
| 3067 | doorbell_reg = readl(&ioc->chip->Doorbell); | ||
| 3068 | if (!(doorbell_reg & MPI2_DOORBELL_USED)) { | ||
| 3069 | dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " | ||
| 3070 | "successful count(%d), timeout(%d)\n", ioc->name, | ||
| 3071 | __func__, count, timeout)); | ||
| 3072 | return 0; | ||
| 3073 | } | ||
| 3074 | if (sleep_flag == CAN_SLEEP) | ||
| 3075 | msleep(1); | ||
| 3076 | else | ||
| 3077 | udelay(500); | ||
| 3078 | count++; | ||
| 3079 | } while (--cntdn); | ||
| 3080 | |||
| 3081 | printk(MPT2SAS_ERR_FMT "%s: failed due to timeout count(%d), " | ||
| 3082 | "doorbell_reg(%x)!\n", ioc->name, __func__, count, doorbell_reg); | ||
| 3083 | return -EFAULT; | ||
| 3084 | } | ||
| 3085 | |||
| 3086 | /** | ||
| 3087 | * _base_send_ioc_reset - send doorbell reset | ||
| 3088 | * @ioc: per adapter object | ||
| 3089 | * @reset_type: currently only supports: MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET | ||
| 3090 | * @timeout: timeout in second | ||
| 3091 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | ||
| 3092 | * | ||
| 3093 | * Returns 0 for success, non-zero for failure. | ||
| 3094 | */ | ||
| 3095 | static int | ||
| 3096 | _base_send_ioc_reset(struct MPT2SAS_ADAPTER *ioc, u8 reset_type, int timeout, | ||
| 3097 | int sleep_flag) | ||
| 3098 | { | ||
| 3099 | u32 ioc_state; | ||
| 3100 | int r = 0; | ||
| 3101 | |||
| 3102 | if (reset_type != MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET) { | ||
| 3103 | printk(MPT2SAS_ERR_FMT "%s: unknown reset_type\n", | ||
| 3104 | ioc->name, __func__); | ||
| 3105 | return -EFAULT; | ||
| 3106 | } | ||
| 3107 | |||
| 3108 | if (!(ioc->facts.IOCCapabilities & | ||
| 3109 | MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY)) | ||
| 3110 | return -EFAULT; | ||
| 3111 | |||
| 3112 | printk(MPT2SAS_INFO_FMT "sending message unit reset !!\n", ioc->name); | ||
| 3113 | |||
| 3114 | writel(reset_type << MPI2_DOORBELL_FUNCTION_SHIFT, | ||
| 3115 | &ioc->chip->Doorbell); | ||
| 3116 | if ((_base_wait_for_doorbell_ack(ioc, 15, sleep_flag))) { | ||
| 3117 | r = -EFAULT; | ||
| 3118 | goto out; | ||
| 3119 | } | ||
| 3120 | ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY, | ||
| 3121 | timeout, sleep_flag); | ||
| 3122 | if (ioc_state) { | ||
| 3123 | printk(MPT2SAS_ERR_FMT "%s: failed going to ready state " | ||
| 3124 | " (ioc_state=0x%x)\n", ioc->name, __func__, ioc_state); | ||
| 3125 | r = -EFAULT; | ||
| 3126 | goto out; | ||
| 3127 | } | ||
| 3128 | out: | ||
| 3129 | printk(MPT2SAS_INFO_FMT "message unit reset: %s\n", | ||
| 3130 | ioc->name, ((r == 0) ? "SUCCESS" : "FAILED")); | ||
| 3131 | return r; | ||
| 3132 | } | ||
| 3133 | |||
| 3134 | /** | ||
| 3135 | * _base_handshake_req_reply_wait - send request thru doorbell interface | ||
| 3136 | * @ioc: per adapter object | ||
| 3137 | * @request_bytes: request length | ||
| 3138 | * @request: pointer having request payload | ||
| 3139 | * @reply_bytes: reply length | ||
| 3140 | * @reply: pointer to reply payload | ||
| 3141 | * @timeout: timeout in second | ||
| 3142 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | ||
| 3143 | * | ||
| 3144 | * Returns 0 for success, non-zero for failure. | ||
| 3145 | */ | ||
| 3146 | static int | ||
| 3147 | _base_handshake_req_reply_wait(struct MPT2SAS_ADAPTER *ioc, int request_bytes, | ||
| 3148 | u32 *request, int reply_bytes, u16 *reply, int timeout, int sleep_flag) | ||
| 3149 | { | ||
| 3150 | MPI2DefaultReply_t *default_reply = (MPI2DefaultReply_t *)reply; | ||
| 3151 | int i; | ||
| 3152 | u8 failed; | ||
| 3153 | u16 dummy; | ||
| 3154 | __le32 *mfp; | ||
| 3155 | |||
| 3156 | /* make sure doorbell is not in use */ | ||
| 3157 | if ((readl(&ioc->chip->Doorbell) & MPI2_DOORBELL_USED)) { | ||
| 3158 | printk(MPT2SAS_ERR_FMT "doorbell is in use " | ||
| 3159 | " (line=%d)\n", ioc->name, __LINE__); | ||
| 3160 | return -EFAULT; | ||
| 3161 | } | ||
| 3162 | |||
| 3163 | /* clear pending doorbell interrupts from previous state changes */ | ||
| 3164 | if (readl(&ioc->chip->HostInterruptStatus) & | ||
| 3165 | MPI2_HIS_IOC2SYS_DB_STATUS) | ||
| 3166 | writel(0, &ioc->chip->HostInterruptStatus); | ||
| 3167 | |||
| 3168 | /* send message to ioc */ | ||
| 3169 | writel(((MPI2_FUNCTION_HANDSHAKE<<MPI2_DOORBELL_FUNCTION_SHIFT) | | ||
| 3170 | ((request_bytes/4)<<MPI2_DOORBELL_ADD_DWORDS_SHIFT)), | ||
| 3171 | &ioc->chip->Doorbell); | ||
| 3172 | |||
| 3173 | if ((_base_wait_for_doorbell_int(ioc, 5, NO_SLEEP))) { | ||
| 3174 | printk(MPT2SAS_ERR_FMT "doorbell handshake " | ||
| 3175 | "int failed (line=%d)\n", ioc->name, __LINE__); | ||
| 3176 | return -EFAULT; | ||
| 3177 | } | ||
| 3178 | writel(0, &ioc->chip->HostInterruptStatus); | ||
| 3179 | |||
| 3180 | if ((_base_wait_for_doorbell_ack(ioc, 5, sleep_flag))) { | ||
| 3181 | printk(MPT2SAS_ERR_FMT "doorbell handshake " | ||
| 3182 | "ack failed (line=%d)\n", ioc->name, __LINE__); | ||
| 3183 | return -EFAULT; | ||
| 3184 | } | ||
| 3185 | |||
| 3186 | /* send message 32-bits at a time */ | ||
| 3187 | for (i = 0, failed = 0; i < request_bytes/4 && !failed; i++) { | ||
| 3188 | writel(cpu_to_le32(request[i]), &ioc->chip->Doorbell); | ||
| 3189 | if ((_base_wait_for_doorbell_ack(ioc, 5, sleep_flag))) | ||
| 3190 | failed = 1; | ||
| 3191 | } | ||
| 3192 | |||
| 3193 | if (failed) { | ||
| 3194 | printk(MPT2SAS_ERR_FMT "doorbell handshake " | ||
| 3195 | "sending request failed (line=%d)\n", ioc->name, __LINE__); | ||
| 3196 | return -EFAULT; | ||
| 3197 | } | ||
| 3198 | |||
| 3199 | /* now wait for the reply */ | ||
| 3200 | if ((_base_wait_for_doorbell_int(ioc, timeout, sleep_flag))) { | ||
| 3201 | printk(MPT2SAS_ERR_FMT "doorbell handshake " | ||
| 3202 | "int failed (line=%d)\n", ioc->name, __LINE__); | ||
| 3203 | return -EFAULT; | ||
| 3204 | } | ||
| 3205 | |||
| 3206 | /* read the first two 16-bits, it gives the total length of the reply */ | ||
| 3207 | reply[0] = le16_to_cpu(readl(&ioc->chip->Doorbell) | ||
| 3208 | & MPI2_DOORBELL_DATA_MASK); | ||
| 3209 | writel(0, &ioc->chip->HostInterruptStatus); | ||
| 3210 | if ((_base_wait_for_doorbell_int(ioc, 5, sleep_flag))) { | ||
| 3211 | printk(MPT2SAS_ERR_FMT "doorbell handshake " | ||
| 3212 | "int failed (line=%d)\n", ioc->name, __LINE__); | ||
| 3213 | return -EFAULT; | ||
| 3214 | } | ||
| 3215 | reply[1] = le16_to_cpu(readl(&ioc->chip->Doorbell) | ||
| 3216 | & MPI2_DOORBELL_DATA_MASK); | ||
| 3217 | writel(0, &ioc->chip->HostInterruptStatus); | ||
| 3218 | |||
| 3219 | for (i = 2; i < default_reply->MsgLength * 2; i++) { | ||
| 3220 | if ((_base_wait_for_doorbell_int(ioc, 5, sleep_flag))) { | ||
| 3221 | printk(MPT2SAS_ERR_FMT "doorbell " | ||
| 3222 | "handshake int failed (line=%d)\n", ioc->name, | ||
| 3223 | __LINE__); | ||
| 3224 | return -EFAULT; | ||
| 3225 | } | ||
| 3226 | if (i >= reply_bytes/2) /* overflow case */ | ||
| 3227 | dummy = readl(&ioc->chip->Doorbell); | ||
| 3228 | else | ||
| 3229 | reply[i] = le16_to_cpu(readl(&ioc->chip->Doorbell) | ||
| 3230 | & MPI2_DOORBELL_DATA_MASK); | ||
| 3231 | writel(0, &ioc->chip->HostInterruptStatus); | ||
| 3232 | } | ||
| 3233 | |||
| 3234 | _base_wait_for_doorbell_int(ioc, 5, sleep_flag); | ||
| 3235 | if (_base_wait_for_doorbell_not_used(ioc, 5, sleep_flag) != 0) { | ||
| 3236 | dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "doorbell is in use " | ||
| 3237 | " (line=%d)\n", ioc->name, __LINE__)); | ||
| 3238 | } | ||
| 3239 | writel(0, &ioc->chip->HostInterruptStatus); | ||
| 3240 | |||
| 3241 | if (ioc->logging_level & MPT_DEBUG_INIT) { | ||
| 3242 | mfp = (__le32 *)reply; | ||
| 3243 | printk(KERN_INFO "\toffset:data\n"); | ||
| 3244 | for (i = 0; i < reply_bytes/4; i++) | ||
| 3245 | printk(KERN_INFO "\t[0x%02x]:%08x\n", i*4, | ||
| 3246 | le32_to_cpu(mfp[i])); | ||
| 3247 | } | ||
| 3248 | return 0; | ||
| 3249 | } | ||
| 3250 | |||
| 3251 | /** | ||
| 3252 | * mpt2sas_base_sas_iounit_control - send sas iounit control to FW | ||
| 3253 | * @ioc: per adapter object | ||
| 3254 | * @mpi_reply: the reply payload from FW | ||
| 3255 | * @mpi_request: the request payload sent to FW | ||
| 3256 | * | ||
| 3257 | * The SAS IO Unit Control Request message allows the host to perform low-level | ||
| 3258 | * operations, such as resets on the PHYs of the IO Unit, also allows the host | ||
| 3259 | * to obtain the IOC assigned device handles for a device if it has other | ||
| 3260 | * identifying information about the device, in addition allows the host to | ||
| 3261 | * remove IOC resources associated with the device. | ||
| 3262 | * | ||
| 3263 | * Returns 0 for success, non-zero for failure. | ||
| 3264 | */ | ||
| 3265 | int | ||
| 3266 | mpt2sas_base_sas_iounit_control(struct MPT2SAS_ADAPTER *ioc, | ||
| 3267 | Mpi2SasIoUnitControlReply_t *mpi_reply, | ||
| 3268 | Mpi2SasIoUnitControlRequest_t *mpi_request) | ||
| 3269 | { | ||
| 3270 | u16 smid; | ||
| 3271 | u32 ioc_state; | ||
| 3272 | unsigned long timeleft; | ||
| 3273 | bool issue_reset = false; | ||
| 3274 | int rc; | ||
| 3275 | void *request; | ||
| 3276 | u16 wait_state_count; | ||
| 3277 | |||
| 3278 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | ||
| 3279 | __func__)); | ||
| 3280 | |||
| 3281 | mutex_lock(&ioc->base_cmds.mutex); | ||
| 3282 | |||
| 3283 | if (ioc->base_cmds.status != MPT2_CMD_NOT_USED) { | ||
| 3284 | printk(MPT2SAS_ERR_FMT "%s: base_cmd in use\n", | ||
| 3285 | ioc->name, __func__); | ||
| 3286 | rc = -EAGAIN; | ||
| 3287 | goto out; | ||
| 3288 | } | ||
| 3289 | |||
| 3290 | wait_state_count = 0; | ||
| 3291 | ioc_state = mpt2sas_base_get_iocstate(ioc, 1); | ||
| 3292 | while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { | ||
| 3293 | if (wait_state_count++ == 10) { | ||
| 3294 | printk(MPT2SAS_ERR_FMT | ||
| 3295 | "%s: failed due to ioc not operational\n", | ||
| 3296 | ioc->name, __func__); | ||
| 3297 | rc = -EFAULT; | ||
| 3298 | goto out; | ||
| 3299 | } | ||
| 3300 | ssleep(1); | ||
| 3301 | ioc_state = mpt2sas_base_get_iocstate(ioc, 1); | ||
| 3302 | printk(MPT2SAS_INFO_FMT "%s: waiting for " | ||
| 3303 | "operational state(count=%d)\n", ioc->name, | ||
| 3304 | __func__, wait_state_count); | ||
| 3305 | } | ||
| 3306 | |||
| 3307 | smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx); | ||
| 3308 | if (!smid) { | ||
| 3309 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", | ||
| 3310 | ioc->name, __func__); | ||
| 3311 | rc = -EAGAIN; | ||
| 3312 | goto out; | ||
| 3313 | } | ||
| 3314 | |||
| 3315 | rc = 0; | ||
| 3316 | ioc->base_cmds.status = MPT2_CMD_PENDING; | ||
| 3317 | request = mpt2sas_base_get_msg_frame(ioc, smid); | ||
| 3318 | ioc->base_cmds.smid = smid; | ||
| 3319 | memcpy(request, mpi_request, sizeof(Mpi2SasIoUnitControlRequest_t)); | ||
| 3320 | if (mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET || | ||
| 3321 | mpi_request->Operation == MPI2_SAS_OP_PHY_LINK_RESET) | ||
| 3322 | ioc->ioc_link_reset_in_progress = 1; | ||
| 3323 | init_completion(&ioc->base_cmds.done); | ||
| 3324 | mpt2sas_base_put_smid_default(ioc, smid); | ||
| 3325 | timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, | ||
| 3326 | msecs_to_jiffies(10000)); | ||
| 3327 | if ((mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET || | ||
| 3328 | mpi_request->Operation == MPI2_SAS_OP_PHY_LINK_RESET) && | ||
| 3329 | ioc->ioc_link_reset_in_progress) | ||
| 3330 | ioc->ioc_link_reset_in_progress = 0; | ||
| 3331 | if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) { | ||
| 3332 | printk(MPT2SAS_ERR_FMT "%s: timeout\n", | ||
| 3333 | ioc->name, __func__); | ||
| 3334 | _debug_dump_mf(mpi_request, | ||
| 3335 | sizeof(Mpi2SasIoUnitControlRequest_t)/4); | ||
| 3336 | if (!(ioc->base_cmds.status & MPT2_CMD_RESET)) | ||
| 3337 | issue_reset = true; | ||
| 3338 | goto issue_host_reset; | ||
| 3339 | } | ||
| 3340 | if (ioc->base_cmds.status & MPT2_CMD_REPLY_VALID) | ||
| 3341 | memcpy(mpi_reply, ioc->base_cmds.reply, | ||
| 3342 | sizeof(Mpi2SasIoUnitControlReply_t)); | ||
| 3343 | else | ||
| 3344 | memset(mpi_reply, 0, sizeof(Mpi2SasIoUnitControlReply_t)); | ||
| 3345 | ioc->base_cmds.status = MPT2_CMD_NOT_USED; | ||
| 3346 | goto out; | ||
| 3347 | |||
| 3348 | issue_host_reset: | ||
| 3349 | if (issue_reset) | ||
| 3350 | mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, | ||
| 3351 | FORCE_BIG_HAMMER); | ||
| 3352 | ioc->base_cmds.status = MPT2_CMD_NOT_USED; | ||
| 3353 | rc = -EFAULT; | ||
| 3354 | out: | ||
| 3355 | mutex_unlock(&ioc->base_cmds.mutex); | ||
| 3356 | return rc; | ||
| 3357 | } | ||
| 3358 | |||
| 3359 | |||
| 3360 | /** | ||
| 3361 | * mpt2sas_base_scsi_enclosure_processor - sending request to sep device | ||
| 3362 | * @ioc: per adapter object | ||
| 3363 | * @mpi_reply: the reply payload from FW | ||
| 3364 | * @mpi_request: the request payload sent to FW | ||
| 3365 | * | ||
| 3366 | * The SCSI Enclosure Processor request message causes the IOC to | ||
| 3367 | * communicate with SES devices to control LED status signals. | ||
| 3368 | * | ||
| 3369 | * Returns 0 for success, non-zero for failure. | ||
| 3370 | */ | ||
| 3371 | int | ||
| 3372 | mpt2sas_base_scsi_enclosure_processor(struct MPT2SAS_ADAPTER *ioc, | ||
| 3373 | Mpi2SepReply_t *mpi_reply, Mpi2SepRequest_t *mpi_request) | ||
| 3374 | { | ||
| 3375 | u16 smid; | ||
| 3376 | u32 ioc_state; | ||
| 3377 | unsigned long timeleft; | ||
| 3378 | bool issue_reset = false; | ||
| 3379 | int rc; | ||
| 3380 | void *request; | ||
| 3381 | u16 wait_state_count; | ||
| 3382 | |||
| 3383 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | ||
| 3384 | __func__)); | ||
| 3385 | |||
| 3386 | mutex_lock(&ioc->base_cmds.mutex); | ||
| 3387 | |||
| 3388 | if (ioc->base_cmds.status != MPT2_CMD_NOT_USED) { | ||
| 3389 | printk(MPT2SAS_ERR_FMT "%s: base_cmd in use\n", | ||
| 3390 | ioc->name, __func__); | ||
| 3391 | rc = -EAGAIN; | ||
| 3392 | goto out; | ||
| 3393 | } | ||
| 3394 | |||
| 3395 | wait_state_count = 0; | ||
| 3396 | ioc_state = mpt2sas_base_get_iocstate(ioc, 1); | ||
| 3397 | while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { | ||
| 3398 | if (wait_state_count++ == 10) { | ||
| 3399 | printk(MPT2SAS_ERR_FMT | ||
| 3400 | "%s: failed due to ioc not operational\n", | ||
| 3401 | ioc->name, __func__); | ||
| 3402 | rc = -EFAULT; | ||
| 3403 | goto out; | ||
| 3404 | } | ||
| 3405 | ssleep(1); | ||
| 3406 | ioc_state = mpt2sas_base_get_iocstate(ioc, 1); | ||
| 3407 | printk(MPT2SAS_INFO_FMT "%s: waiting for " | ||
| 3408 | "operational state(count=%d)\n", ioc->name, | ||
| 3409 | __func__, wait_state_count); | ||
| 3410 | } | ||
| 3411 | |||
| 3412 | smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx); | ||
| 3413 | if (!smid) { | ||
| 3414 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", | ||
| 3415 | ioc->name, __func__); | ||
| 3416 | rc = -EAGAIN; | ||
| 3417 | goto out; | ||
| 3418 | } | ||
| 3419 | |||
| 3420 | rc = 0; | ||
| 3421 | ioc->base_cmds.status = MPT2_CMD_PENDING; | ||
| 3422 | request = mpt2sas_base_get_msg_frame(ioc, smid); | ||
| 3423 | ioc->base_cmds.smid = smid; | ||
| 3424 | memcpy(request, mpi_request, sizeof(Mpi2SepReply_t)); | ||
| 3425 | init_completion(&ioc->base_cmds.done); | ||
| 3426 | mpt2sas_base_put_smid_default(ioc, smid); | ||
| 3427 | timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, | ||
| 3428 | msecs_to_jiffies(10000)); | ||
| 3429 | if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) { | ||
| 3430 | printk(MPT2SAS_ERR_FMT "%s: timeout\n", | ||
| 3431 | ioc->name, __func__); | ||
| 3432 | _debug_dump_mf(mpi_request, | ||
| 3433 | sizeof(Mpi2SepRequest_t)/4); | ||
| 3434 | if (!(ioc->base_cmds.status & MPT2_CMD_RESET)) | ||
| 3435 | issue_reset = true; | ||
| 3436 | goto issue_host_reset; | ||
| 3437 | } | ||
| 3438 | if (ioc->base_cmds.status & MPT2_CMD_REPLY_VALID) | ||
| 3439 | memcpy(mpi_reply, ioc->base_cmds.reply, | ||
| 3440 | sizeof(Mpi2SepReply_t)); | ||
| 3441 | else | ||
| 3442 | memset(mpi_reply, 0, sizeof(Mpi2SepReply_t)); | ||
| 3443 | ioc->base_cmds.status = MPT2_CMD_NOT_USED; | ||
| 3444 | goto out; | ||
| 3445 | |||
| 3446 | issue_host_reset: | ||
| 3447 | if (issue_reset) | ||
| 3448 | mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, | ||
| 3449 | FORCE_BIG_HAMMER); | ||
| 3450 | ioc->base_cmds.status = MPT2_CMD_NOT_USED; | ||
| 3451 | rc = -EFAULT; | ||
| 3452 | out: | ||
| 3453 | mutex_unlock(&ioc->base_cmds.mutex); | ||
| 3454 | return rc; | ||
| 3455 | } | ||
| 3456 | |||
| 3457 | /** | ||
| 3458 | * _base_get_port_facts - obtain port facts reply and save in ioc | ||
| 3459 | * @ioc: per adapter object | ||
| 3460 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | ||
| 3461 | * | ||
| 3462 | * Returns 0 for success, non-zero for failure. | ||
| 3463 | */ | ||
| 3464 | static int | ||
| 3465 | _base_get_port_facts(struct MPT2SAS_ADAPTER *ioc, int port, int sleep_flag) | ||
| 3466 | { | ||
| 3467 | Mpi2PortFactsRequest_t mpi_request; | ||
| 3468 | Mpi2PortFactsReply_t mpi_reply; | ||
| 3469 | struct mpt2sas_port_facts *pfacts; | ||
| 3470 | int mpi_reply_sz, mpi_request_sz, r; | ||
| 3471 | |||
| 3472 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | ||
| 3473 | __func__)); | ||
| 3474 | |||
| 3475 | mpi_reply_sz = sizeof(Mpi2PortFactsReply_t); | ||
| 3476 | mpi_request_sz = sizeof(Mpi2PortFactsRequest_t); | ||
| 3477 | memset(&mpi_request, 0, mpi_request_sz); | ||
| 3478 | mpi_request.Function = MPI2_FUNCTION_PORT_FACTS; | ||
| 3479 | mpi_request.PortNumber = port; | ||
| 3480 | r = _base_handshake_req_reply_wait(ioc, mpi_request_sz, | ||
| 3481 | (u32 *)&mpi_request, mpi_reply_sz, (u16 *)&mpi_reply, 5, CAN_SLEEP); | ||
| 3482 | |||
| 3483 | if (r != 0) { | ||
| 3484 | printk(MPT2SAS_ERR_FMT "%s: handshake failed (r=%d)\n", | ||
| 3485 | ioc->name, __func__, r); | ||
| 3486 | return r; | ||
| 3487 | } | ||
| 3488 | |||
| 3489 | pfacts = &ioc->pfacts[port]; | ||
| 3490 | memset(pfacts, 0, sizeof(struct mpt2sas_port_facts)); | ||
| 3491 | pfacts->PortNumber = mpi_reply.PortNumber; | ||
| 3492 | pfacts->VP_ID = mpi_reply.VP_ID; | ||
| 3493 | pfacts->VF_ID = mpi_reply.VF_ID; | ||
| 3494 | pfacts->MaxPostedCmdBuffers = | ||
| 3495 | le16_to_cpu(mpi_reply.MaxPostedCmdBuffers); | ||
| 3496 | |||
| 3497 | return 0; | ||
| 3498 | } | ||
| 3499 | |||
| 3500 | /** | ||
| 3501 | * _base_wait_for_iocstate - Wait until the card is in READY or OPERATIONAL | ||
| 3502 | * @ioc: per adapter object | ||
| 3503 | * @timeout: | ||
| 3504 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | ||
| 3505 | * | ||
| 3506 | * Returns 0 for success, non-zero for failure. | ||
| 3507 | */ | ||
| 3508 | static int | ||
| 3509 | _base_wait_for_iocstate(struct MPT2SAS_ADAPTER *ioc, int timeout, | ||
| 3510 | int sleep_flag) | ||
| 3511 | { | ||
| 3512 | u32 ioc_state, doorbell; | ||
| 3513 | int rc; | ||
| 3514 | |||
| 3515 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | ||
| 3516 | __func__)); | ||
| 3517 | |||
| 3518 | if (ioc->pci_error_recovery) | ||
| 3519 | return 0; | ||
| 3520 | |||
| 3521 | doorbell = mpt2sas_base_get_iocstate(ioc, 0); | ||
| 3522 | ioc_state = doorbell & MPI2_IOC_STATE_MASK; | ||
| 3523 | dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: ioc_state(0x%08x)\n", | ||
| 3524 | ioc->name, __func__, ioc_state)); | ||
| 3525 | |||
| 3526 | switch (ioc_state) { | ||
| 3527 | case MPI2_IOC_STATE_READY: | ||
| 3528 | case MPI2_IOC_STATE_OPERATIONAL: | ||
| 3529 | return 0; | ||
| 3530 | } | ||
| 3531 | |||
| 3532 | if (doorbell & MPI2_DOORBELL_USED) { | ||
| 3533 | dhsprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 3534 | "unexpected doorbell activ!e\n", ioc->name)); | ||
| 3535 | goto issue_diag_reset; | ||
| 3536 | } | ||
| 3537 | |||
| 3538 | if (ioc_state == MPI2_IOC_STATE_FAULT) { | ||
| 3539 | mpt2sas_base_fault_info(ioc, doorbell & | ||
| 3540 | MPI2_DOORBELL_DATA_MASK); | ||
| 3541 | goto issue_diag_reset; | ||
| 3542 | } | ||
| 3543 | |||
| 3544 | ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY, | ||
| 3545 | timeout, sleep_flag); | ||
| 3546 | if (ioc_state) { | ||
| 3547 | printk(MPT2SAS_ERR_FMT | ||
| 3548 | "%s: failed going to ready state (ioc_state=0x%x)\n", | ||
| 3549 | ioc->name, __func__, ioc_state); | ||
| 3550 | return -EFAULT; | ||
| 3551 | } | ||
| 3552 | |||
| 3553 | issue_diag_reset: | ||
| 3554 | rc = _base_diag_reset(ioc, sleep_flag); | ||
| 3555 | return rc; | ||
| 3556 | } | ||
| 3557 | |||
| 3558 | /** | ||
| 3559 | * _base_get_ioc_facts - obtain ioc facts reply and save in ioc | ||
| 3560 | * @ioc: per adapter object | ||
| 3561 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | ||
| 3562 | * | ||
| 3563 | * Returns 0 for success, non-zero for failure. | ||
| 3564 | */ | ||
| 3565 | static int | ||
| 3566 | _base_get_ioc_facts(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | ||
| 3567 | { | ||
| 3568 | Mpi2IOCFactsRequest_t mpi_request; | ||
| 3569 | Mpi2IOCFactsReply_t mpi_reply; | ||
| 3570 | struct mpt2sas_facts *facts; | ||
| 3571 | int mpi_reply_sz, mpi_request_sz, r; | ||
| 3572 | |||
| 3573 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | ||
| 3574 | __func__)); | ||
| 3575 | |||
| 3576 | r = _base_wait_for_iocstate(ioc, 10, sleep_flag); | ||
| 3577 | if (r) { | ||
| 3578 | printk(MPT2SAS_ERR_FMT "%s: failed getting to correct state\n", | ||
| 3579 | ioc->name, __func__); | ||
| 3580 | return r; | ||
| 3581 | } | ||
| 3582 | |||
| 3583 | mpi_reply_sz = sizeof(Mpi2IOCFactsReply_t); | ||
| 3584 | mpi_request_sz = sizeof(Mpi2IOCFactsRequest_t); | ||
| 3585 | memset(&mpi_request, 0, mpi_request_sz); | ||
| 3586 | mpi_request.Function = MPI2_FUNCTION_IOC_FACTS; | ||
| 3587 | r = _base_handshake_req_reply_wait(ioc, mpi_request_sz, | ||
| 3588 | (u32 *)&mpi_request, mpi_reply_sz, (u16 *)&mpi_reply, 5, CAN_SLEEP); | ||
| 3589 | |||
| 3590 | if (r != 0) { | ||
| 3591 | printk(MPT2SAS_ERR_FMT "%s: handshake failed (r=%d)\n", | ||
| 3592 | ioc->name, __func__, r); | ||
| 3593 | return r; | ||
| 3594 | } | ||
| 3595 | |||
| 3596 | facts = &ioc->facts; | ||
| 3597 | memset(facts, 0, sizeof(struct mpt2sas_facts)); | ||
| 3598 | facts->MsgVersion = le16_to_cpu(mpi_reply.MsgVersion); | ||
| 3599 | facts->HeaderVersion = le16_to_cpu(mpi_reply.HeaderVersion); | ||
| 3600 | facts->VP_ID = mpi_reply.VP_ID; | ||
| 3601 | facts->VF_ID = mpi_reply.VF_ID; | ||
| 3602 | facts->IOCExceptions = le16_to_cpu(mpi_reply.IOCExceptions); | ||
| 3603 | facts->MaxChainDepth = mpi_reply.MaxChainDepth; | ||
| 3604 | facts->WhoInit = mpi_reply.WhoInit; | ||
| 3605 | facts->NumberOfPorts = mpi_reply.NumberOfPorts; | ||
| 3606 | facts->MaxMSIxVectors = mpi_reply.MaxMSIxVectors; | ||
| 3607 | facts->RequestCredit = le16_to_cpu(mpi_reply.RequestCredit); | ||
| 3608 | facts->MaxReplyDescriptorPostQueueDepth = | ||
| 3609 | le16_to_cpu(mpi_reply.MaxReplyDescriptorPostQueueDepth); | ||
| 3610 | facts->ProductID = le16_to_cpu(mpi_reply.ProductID); | ||
| 3611 | facts->IOCCapabilities = le32_to_cpu(mpi_reply.IOCCapabilities); | ||
| 3612 | if ((facts->IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID)) | ||
| 3613 | ioc->ir_firmware = 1; | ||
| 3614 | if ((facts->IOCCapabilities & | ||
| 3615 | MPI2_IOCFACTS_CAPABILITY_RDPQ_ARRAY_CAPABLE)) | ||
| 3616 | ioc->rdpq_array_capable = 1; | ||
| 3617 | facts->FWVersion.Word = le32_to_cpu(mpi_reply.FWVersion.Word); | ||
| 3618 | facts->IOCRequestFrameSize = | ||
| 3619 | le16_to_cpu(mpi_reply.IOCRequestFrameSize); | ||
| 3620 | facts->MaxInitiators = le16_to_cpu(mpi_reply.MaxInitiators); | ||
| 3621 | facts->MaxTargets = le16_to_cpu(mpi_reply.MaxTargets); | ||
| 3622 | ioc->shost->max_id = -1; | ||
| 3623 | facts->MaxSasExpanders = le16_to_cpu(mpi_reply.MaxSasExpanders); | ||
| 3624 | facts->MaxEnclosures = le16_to_cpu(mpi_reply.MaxEnclosures); | ||
| 3625 | facts->ProtocolFlags = le16_to_cpu(mpi_reply.ProtocolFlags); | ||
| 3626 | facts->HighPriorityCredit = | ||
| 3627 | le16_to_cpu(mpi_reply.HighPriorityCredit); | ||
| 3628 | facts->ReplyFrameSize = mpi_reply.ReplyFrameSize; | ||
| 3629 | facts->MaxDevHandle = le16_to_cpu(mpi_reply.MaxDevHandle); | ||
| 3630 | |||
| 3631 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "hba queue depth(%d), " | ||
| 3632 | "max chains per io(%d)\n", ioc->name, facts->RequestCredit, | ||
| 3633 | facts->MaxChainDepth)); | ||
| 3634 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request frame size(%d), " | ||
| 3635 | "reply frame size(%d)\n", ioc->name, | ||
| 3636 | facts->IOCRequestFrameSize * 4, facts->ReplyFrameSize * 4)); | ||
| 3637 | return 0; | ||
| 3638 | } | ||
| 3639 | |||
| 3640 | /** | ||
| 3641 | * _base_send_ioc_init - send ioc_init to firmware | ||
| 3642 | * @ioc: per adapter object | ||
| 3643 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | ||
| 3644 | * | ||
| 3645 | * Returns 0 for success, non-zero for failure. | ||
| 3646 | */ | ||
| 3647 | static int | ||
| 3648 | _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | ||
| 3649 | { | ||
| 3650 | Mpi2IOCInitRequest_t mpi_request; | ||
| 3651 | Mpi2IOCInitReply_t mpi_reply; | ||
| 3652 | int i, r = 0; | ||
| 3653 | struct timeval current_time; | ||
| 3654 | u16 ioc_status; | ||
| 3655 | u32 reply_post_free_array_sz = 0; | ||
| 3656 | Mpi2IOCInitRDPQArrayEntry *reply_post_free_array = NULL; | ||
| 3657 | dma_addr_t reply_post_free_array_dma; | ||
| 3658 | |||
| 3659 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | ||
| 3660 | __func__)); | ||
| 3661 | |||
| 3662 | memset(&mpi_request, 0, sizeof(Mpi2IOCInitRequest_t)); | ||
| 3663 | mpi_request.Function = MPI2_FUNCTION_IOC_INIT; | ||
| 3664 | mpi_request.WhoInit = MPI2_WHOINIT_HOST_DRIVER; | ||
| 3665 | mpi_request.VF_ID = 0; /* TODO */ | ||
| 3666 | mpi_request.VP_ID = 0; | ||
| 3667 | mpi_request.MsgVersion = cpu_to_le16(MPI2_VERSION); | ||
| 3668 | mpi_request.HeaderVersion = cpu_to_le16(MPI2_HEADER_VERSION); | ||
| 3669 | |||
| 3670 | if (_base_is_controller_msix_enabled(ioc)) | ||
| 3671 | mpi_request.HostMSIxVectors = ioc->reply_queue_count; | ||
| 3672 | mpi_request.SystemRequestFrameSize = cpu_to_le16(ioc->request_sz/4); | ||
| 3673 | mpi_request.ReplyDescriptorPostQueueDepth = | ||
| 3674 | cpu_to_le16(ioc->reply_post_queue_depth); | ||
| 3675 | mpi_request.ReplyFreeQueueDepth = | ||
| 3676 | cpu_to_le16(ioc->reply_free_queue_depth); | ||
| 3677 | |||
| 3678 | mpi_request.SenseBufferAddressHigh = | ||
| 3679 | cpu_to_le32((u64)ioc->sense_dma >> 32); | ||
| 3680 | mpi_request.SystemReplyAddressHigh = | ||
| 3681 | cpu_to_le32((u64)ioc->reply_dma >> 32); | ||
| 3682 | mpi_request.SystemRequestFrameBaseAddress = | ||
| 3683 | cpu_to_le64((u64)ioc->request_dma); | ||
| 3684 | mpi_request.ReplyFreeQueueAddress = | ||
| 3685 | cpu_to_le64((u64)ioc->reply_free_dma); | ||
| 3686 | |||
| 3687 | if (ioc->rdpq_array_enable) { | ||
| 3688 | reply_post_free_array_sz = ioc->reply_queue_count * | ||
| 3689 | sizeof(Mpi2IOCInitRDPQArrayEntry); | ||
| 3690 | reply_post_free_array = pci_alloc_consistent(ioc->pdev, | ||
| 3691 | reply_post_free_array_sz, &reply_post_free_array_dma); | ||
| 3692 | if (!reply_post_free_array) { | ||
| 3693 | printk(MPT2SAS_ERR_FMT | ||
| 3694 | "reply_post_free_array: pci_alloc_consistent failed\n", | ||
| 3695 | ioc->name); | ||
| 3696 | r = -ENOMEM; | ||
| 3697 | goto out; | ||
| 3698 | } | ||
| 3699 | memset(reply_post_free_array, 0, reply_post_free_array_sz); | ||
| 3700 | for (i = 0; i < ioc->reply_queue_count; i++) | ||
| 3701 | reply_post_free_array[i].RDPQBaseAddress = | ||
| 3702 | cpu_to_le64( | ||
| 3703 | (u64)ioc->reply_post[i].reply_post_free_dma); | ||
| 3704 | mpi_request.MsgFlags = MPI2_IOCINIT_MSGFLAG_RDPQ_ARRAY_MODE; | ||
| 3705 | mpi_request.ReplyDescriptorPostQueueAddress = | ||
| 3706 | cpu_to_le64((u64)reply_post_free_array_dma); | ||
| 3707 | } else { | ||
| 3708 | mpi_request.ReplyDescriptorPostQueueAddress = | ||
| 3709 | cpu_to_le64((u64)ioc->reply_post[0].reply_post_free_dma); | ||
| 3710 | } | ||
| 3711 | |||
| 3712 | /* This time stamp specifies number of milliseconds | ||
| 3713 | * since epoch ~ midnight January 1, 1970. | ||
| 3714 | */ | ||
| 3715 | do_gettimeofday(¤t_time); | ||
| 3716 | mpi_request.TimeStamp = cpu_to_le64((u64)current_time.tv_sec * 1000 + | ||
| 3717 | (current_time.tv_usec / 1000)); | ||
| 3718 | |||
| 3719 | if (ioc->logging_level & MPT_DEBUG_INIT) { | ||
| 3720 | __le32 *mfp; | ||
| 3721 | int i; | ||
| 3722 | |||
| 3723 | mfp = (__le32 *)&mpi_request; | ||
| 3724 | printk(KERN_INFO "\toffset:data\n"); | ||
| 3725 | for (i = 0; i < sizeof(Mpi2IOCInitRequest_t)/4; i++) | ||
| 3726 | printk(KERN_INFO "\t[0x%02x]:%08x\n", i*4, | ||
| 3727 | le32_to_cpu(mfp[i])); | ||
| 3728 | } | ||
| 3729 | |||
| 3730 | r = _base_handshake_req_reply_wait(ioc, | ||
| 3731 | sizeof(Mpi2IOCInitRequest_t), (u32 *)&mpi_request, | ||
| 3732 | sizeof(Mpi2IOCInitReply_t), (u16 *)&mpi_reply, 10, | ||
| 3733 | sleep_flag); | ||
| 3734 | |||
| 3735 | if (r != 0) { | ||
| 3736 | printk(MPT2SAS_ERR_FMT "%s: handshake failed (r=%d)\n", | ||
| 3737 | ioc->name, __func__, r); | ||
| 3738 | goto out; | ||
| 3739 | } | ||
| 3740 | |||
| 3741 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; | ||
| 3742 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS || | ||
| 3743 | mpi_reply.IOCLogInfo) { | ||
| 3744 | printk(MPT2SAS_ERR_FMT "%s: failed\n", ioc->name, __func__); | ||
| 3745 | r = -EIO; | ||
| 3746 | } | ||
| 3747 | |||
| 3748 | out: | ||
| 3749 | if (reply_post_free_array) | ||
| 3750 | pci_free_consistent(ioc->pdev, reply_post_free_array_sz, | ||
| 3751 | reply_post_free_array, | ||
| 3752 | reply_post_free_array_dma); | ||
| 3753 | return r; | ||
| 3754 | } | ||
| 3755 | |||
| 3756 | /** | ||
| 3757 | * mpt2sas_port_enable_done - command completion routine for port enable | ||
| 3758 | * @ioc: per adapter object | ||
| 3759 | * @smid: system request message index | ||
| 3760 | * @msix_index: MSIX table index supplied by the OS | ||
| 3761 | * @reply: reply message frame(lower 32bit addr) | ||
| 3762 | * | ||
| 3763 | * Return 1 meaning mf should be freed from _base_interrupt | ||
| 3764 | * 0 means the mf is freed from this function. | ||
| 3765 | */ | ||
| 3766 | u8 | ||
| 3767 | mpt2sas_port_enable_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | ||
| 3768 | u32 reply) | ||
| 3769 | { | ||
| 3770 | MPI2DefaultReply_t *mpi_reply; | ||
| 3771 | u16 ioc_status; | ||
| 3772 | |||
| 3773 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | ||
| 3774 | if (mpi_reply && mpi_reply->Function == MPI2_FUNCTION_EVENT_ACK) | ||
| 3775 | return 1; | ||
| 3776 | |||
| 3777 | if (ioc->port_enable_cmds.status == MPT2_CMD_NOT_USED) | ||
| 3778 | return 1; | ||
| 3779 | |||
| 3780 | ioc->port_enable_cmds.status |= MPT2_CMD_COMPLETE; | ||
| 3781 | if (mpi_reply) { | ||
| 3782 | ioc->port_enable_cmds.status |= MPT2_CMD_REPLY_VALID; | ||
| 3783 | memcpy(ioc->port_enable_cmds.reply, mpi_reply, | ||
| 3784 | mpi_reply->MsgLength*4); | ||
| 3785 | } | ||
| 3786 | ioc->port_enable_cmds.status &= ~MPT2_CMD_PENDING; | ||
| 3787 | |||
| 3788 | ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK; | ||
| 3789 | |||
| 3790 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) | ||
| 3791 | ioc->port_enable_failed = 1; | ||
| 3792 | |||
| 3793 | if (ioc->is_driver_loading) { | ||
| 3794 | if (ioc_status == MPI2_IOCSTATUS_SUCCESS) { | ||
| 3795 | mpt2sas_port_enable_complete(ioc); | ||
| 3796 | return 1; | ||
| 3797 | } else { | ||
| 3798 | ioc->start_scan_failed = ioc_status; | ||
| 3799 | ioc->start_scan = 0; | ||
| 3800 | return 1; | ||
| 3801 | } | ||
| 3802 | } | ||
| 3803 | complete(&ioc->port_enable_cmds.done); | ||
| 3804 | return 1; | ||
| 3805 | } | ||
| 3806 | |||
| 3807 | |||
| 3808 | /** | ||
| 3809 | * _base_send_port_enable - send port_enable(discovery stuff) to firmware | ||
| 3810 | * @ioc: per adapter object | ||
| 3811 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | ||
| 3812 | * | ||
| 3813 | * Returns 0 for success, non-zero for failure. | ||
| 3814 | */ | ||
| 3815 | static int | ||
| 3816 | _base_send_port_enable(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | ||
| 3817 | { | ||
| 3818 | Mpi2PortEnableRequest_t *mpi_request; | ||
| 3819 | Mpi2PortEnableReply_t *mpi_reply; | ||
| 3820 | unsigned long timeleft; | ||
| 3821 | int r = 0; | ||
| 3822 | u16 smid; | ||
| 3823 | u16 ioc_status; | ||
| 3824 | |||
| 3825 | printk(MPT2SAS_INFO_FMT "sending port enable !!\n", ioc->name); | ||
| 3826 | |||
| 3827 | if (ioc->port_enable_cmds.status & MPT2_CMD_PENDING) { | ||
| 3828 | printk(MPT2SAS_ERR_FMT "%s: internal command already in use\n", | ||
| 3829 | ioc->name, __func__); | ||
| 3830 | return -EAGAIN; | ||
| 3831 | } | ||
| 3832 | |||
| 3833 | smid = mpt2sas_base_get_smid(ioc, ioc->port_enable_cb_idx); | ||
| 3834 | if (!smid) { | ||
| 3835 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", | ||
| 3836 | ioc->name, __func__); | ||
| 3837 | return -EAGAIN; | ||
| 3838 | } | ||
| 3839 | |||
| 3840 | ioc->port_enable_cmds.status = MPT2_CMD_PENDING; | ||
| 3841 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); | ||
| 3842 | ioc->port_enable_cmds.smid = smid; | ||
| 3843 | memset(mpi_request, 0, sizeof(Mpi2PortEnableRequest_t)); | ||
| 3844 | mpi_request->Function = MPI2_FUNCTION_PORT_ENABLE; | ||
| 3845 | |||
| 3846 | init_completion(&ioc->port_enable_cmds.done); | ||
| 3847 | mpt2sas_base_put_smid_default(ioc, smid); | ||
| 3848 | timeleft = wait_for_completion_timeout(&ioc->port_enable_cmds.done, | ||
| 3849 | 300*HZ); | ||
| 3850 | if (!(ioc->port_enable_cmds.status & MPT2_CMD_COMPLETE)) { | ||
| 3851 | printk(MPT2SAS_ERR_FMT "%s: timeout\n", | ||
| 3852 | ioc->name, __func__); | ||
| 3853 | _debug_dump_mf(mpi_request, | ||
| 3854 | sizeof(Mpi2PortEnableRequest_t)/4); | ||
| 3855 | if (ioc->port_enable_cmds.status & MPT2_CMD_RESET) | ||
| 3856 | r = -EFAULT; | ||
| 3857 | else | ||
| 3858 | r = -ETIME; | ||
| 3859 | goto out; | ||
| 3860 | } | ||
| 3861 | mpi_reply = ioc->port_enable_cmds.reply; | ||
| 3862 | |||
| 3863 | ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK; | ||
| 3864 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { | ||
| 3865 | printk(MPT2SAS_ERR_FMT "%s: failed with (ioc_status=0x%08x)\n", | ||
| 3866 | ioc->name, __func__, ioc_status); | ||
| 3867 | r = -EFAULT; | ||
| 3868 | goto out; | ||
| 3869 | } | ||
| 3870 | out: | ||
| 3871 | ioc->port_enable_cmds.status = MPT2_CMD_NOT_USED; | ||
| 3872 | printk(MPT2SAS_INFO_FMT "port enable: %s\n", ioc->name, ((r == 0) ? | ||
| 3873 | "SUCCESS" : "FAILED")); | ||
| 3874 | return r; | ||
| 3875 | } | ||
| 3876 | |||
| 3877 | /** | ||
| 3878 | * mpt2sas_port_enable - initiate firmware discovery (don't wait for reply) | ||
| 3879 | * @ioc: per adapter object | ||
| 3880 | * | ||
| 3881 | * Returns 0 for success, non-zero for failure. | ||
| 3882 | */ | ||
| 3883 | int | ||
| 3884 | mpt2sas_port_enable(struct MPT2SAS_ADAPTER *ioc) | ||
| 3885 | { | ||
| 3886 | Mpi2PortEnableRequest_t *mpi_request; | ||
| 3887 | u16 smid; | ||
| 3888 | |||
| 3889 | printk(MPT2SAS_INFO_FMT "sending port enable !!\n", ioc->name); | ||
| 3890 | |||
| 3891 | if (ioc->port_enable_cmds.status & MPT2_CMD_PENDING) { | ||
| 3892 | printk(MPT2SAS_ERR_FMT "%s: internal command already in use\n", | ||
| 3893 | ioc->name, __func__); | ||
| 3894 | return -EAGAIN; | ||
| 3895 | } | ||
| 3896 | |||
| 3897 | smid = mpt2sas_base_get_smid(ioc, ioc->port_enable_cb_idx); | ||
| 3898 | if (!smid) { | ||
| 3899 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", | ||
| 3900 | ioc->name, __func__); | ||
| 3901 | return -EAGAIN; | ||
| 3902 | } | ||
| 3903 | |||
| 3904 | ioc->port_enable_cmds.status = MPT2_CMD_PENDING; | ||
| 3905 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); | ||
| 3906 | ioc->port_enable_cmds.smid = smid; | ||
| 3907 | memset(mpi_request, 0, sizeof(Mpi2PortEnableRequest_t)); | ||
| 3908 | mpi_request->Function = MPI2_FUNCTION_PORT_ENABLE; | ||
| 3909 | |||
| 3910 | mpt2sas_base_put_smid_default(ioc, smid); | ||
| 3911 | return 0; | ||
| 3912 | } | ||
| 3913 | |||
| 3914 | /** | ||
| 3915 | * _base_determine_wait_on_discovery - desposition | ||
| 3916 | * @ioc: per adapter object | ||
| 3917 | * | ||
| 3918 | * Decide whether to wait on discovery to complete. Used to either | ||
| 3919 | * locate boot device, or report volumes ahead of physical devices. | ||
| 3920 | * | ||
| 3921 | * Returns 1 for wait, 0 for don't wait | ||
| 3922 | */ | ||
| 3923 | static int | ||
| 3924 | _base_determine_wait_on_discovery(struct MPT2SAS_ADAPTER *ioc) | ||
| 3925 | { | ||
| 3926 | /* We wait for discovery to complete if IR firmware is loaded. | ||
| 3927 | * The sas topology events arrive before PD events, so we need time to | ||
| 3928 | * turn on the bit in ioc->pd_handles to indicate PD | ||
| 3929 | * Also, it maybe required to report Volumes ahead of physical | ||
| 3930 | * devices when MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING is set. | ||
| 3931 | */ | ||
| 3932 | if (ioc->ir_firmware) | ||
| 3933 | return 1; | ||
| 3934 | |||
| 3935 | /* if no Bios, then we don't need to wait */ | ||
| 3936 | if (!ioc->bios_pg3.BiosVersion) | ||
| 3937 | return 0; | ||
| 3938 | |||
| 3939 | /* Bios is present, then we drop down here. | ||
| 3940 | * | ||
| 3941 | * If there any entries in the Bios Page 2, then we wait | ||
| 3942 | * for discovery to complete. | ||
| 3943 | */ | ||
| 3944 | |||
| 3945 | /* Current Boot Device */ | ||
| 3946 | if ((ioc->bios_pg2.CurrentBootDeviceForm & | ||
| 3947 | MPI2_BIOSPAGE2_FORM_MASK) == | ||
| 3948 | MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED && | ||
| 3949 | /* Request Boot Device */ | ||
| 3950 | (ioc->bios_pg2.ReqBootDeviceForm & | ||
| 3951 | MPI2_BIOSPAGE2_FORM_MASK) == | ||
| 3952 | MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED && | ||
| 3953 | /* Alternate Request Boot Device */ | ||
| 3954 | (ioc->bios_pg2.ReqAltBootDeviceForm & | ||
| 3955 | MPI2_BIOSPAGE2_FORM_MASK) == | ||
| 3956 | MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED) | ||
| 3957 | return 0; | ||
| 3958 | |||
| 3959 | return 1; | ||
| 3960 | } | ||
| 3961 | |||
| 3962 | |||
| 3963 | /** | ||
| 3964 | * _base_unmask_events - turn on notification for this event | ||
| 3965 | * @ioc: per adapter object | ||
| 3966 | * @event: firmware event | ||
| 3967 | * | ||
| 3968 | * The mask is stored in ioc->event_masks. | ||
| 3969 | */ | ||
| 3970 | static void | ||
| 3971 | _base_unmask_events(struct MPT2SAS_ADAPTER *ioc, u16 event) | ||
| 3972 | { | ||
| 3973 | u32 desired_event; | ||
| 3974 | |||
| 3975 | if (event >= 128) | ||
| 3976 | return; | ||
| 3977 | |||
| 3978 | desired_event = (1 << (event % 32)); | ||
| 3979 | |||
| 3980 | if (event < 32) | ||
| 3981 | ioc->event_masks[0] &= ~desired_event; | ||
| 3982 | else if (event < 64) | ||
| 3983 | ioc->event_masks[1] &= ~desired_event; | ||
| 3984 | else if (event < 96) | ||
| 3985 | ioc->event_masks[2] &= ~desired_event; | ||
| 3986 | else if (event < 128) | ||
| 3987 | ioc->event_masks[3] &= ~desired_event; | ||
| 3988 | } | ||
| 3989 | |||
| 3990 | /** | ||
| 3991 | * _base_event_notification - send event notification | ||
| 3992 | * @ioc: per adapter object | ||
| 3993 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | ||
| 3994 | * | ||
| 3995 | * Returns 0 for success, non-zero for failure. | ||
| 3996 | */ | ||
| 3997 | static int | ||
| 3998 | _base_event_notification(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | ||
| 3999 | { | ||
| 4000 | Mpi2EventNotificationRequest_t *mpi_request; | ||
| 4001 | unsigned long timeleft; | ||
| 4002 | u16 smid; | ||
| 4003 | int r = 0; | ||
| 4004 | int i; | ||
| 4005 | |||
| 4006 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | ||
| 4007 | __func__)); | ||
| 4008 | |||
| 4009 | if (ioc->base_cmds.status & MPT2_CMD_PENDING) { | ||
| 4010 | printk(MPT2SAS_ERR_FMT "%s: internal command already in use\n", | ||
| 4011 | ioc->name, __func__); | ||
| 4012 | return -EAGAIN; | ||
| 4013 | } | ||
| 4014 | |||
| 4015 | smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx); | ||
| 4016 | if (!smid) { | ||
| 4017 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", | ||
| 4018 | ioc->name, __func__); | ||
| 4019 | return -EAGAIN; | ||
| 4020 | } | ||
| 4021 | ioc->base_cmds.status = MPT2_CMD_PENDING; | ||
| 4022 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); | ||
| 4023 | ioc->base_cmds.smid = smid; | ||
| 4024 | memset(mpi_request, 0, sizeof(Mpi2EventNotificationRequest_t)); | ||
| 4025 | mpi_request->Function = MPI2_FUNCTION_EVENT_NOTIFICATION; | ||
| 4026 | mpi_request->VF_ID = 0; /* TODO */ | ||
| 4027 | mpi_request->VP_ID = 0; | ||
| 4028 | for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) | ||
| 4029 | mpi_request->EventMasks[i] = | ||
| 4030 | cpu_to_le32(ioc->event_masks[i]); | ||
| 4031 | init_completion(&ioc->base_cmds.done); | ||
| 4032 | mpt2sas_base_put_smid_default(ioc, smid); | ||
| 4033 | timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, 30*HZ); | ||
| 4034 | if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) { | ||
| 4035 | printk(MPT2SAS_ERR_FMT "%s: timeout\n", | ||
| 4036 | ioc->name, __func__); | ||
| 4037 | _debug_dump_mf(mpi_request, | ||
| 4038 | sizeof(Mpi2EventNotificationRequest_t)/4); | ||
| 4039 | if (ioc->base_cmds.status & MPT2_CMD_RESET) | ||
| 4040 | r = -EFAULT; | ||
| 4041 | else | ||
| 4042 | r = -ETIME; | ||
| 4043 | } else | ||
| 4044 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: complete\n", | ||
| 4045 | ioc->name, __func__)); | ||
| 4046 | ioc->base_cmds.status = MPT2_CMD_NOT_USED; | ||
| 4047 | return r; | ||
| 4048 | } | ||
| 4049 | |||
| 4050 | /** | ||
| 4051 | * mpt2sas_base_validate_event_type - validating event types | ||
| 4052 | * @ioc: per adapter object | ||
| 4053 | * @event: firmware event | ||
| 4054 | * | ||
| 4055 | * This will turn on firmware event notification when application | ||
| 4056 | * ask for that event. We don't mask events that are already enabled. | ||
| 4057 | */ | ||
| 4058 | void | ||
| 4059 | mpt2sas_base_validate_event_type(struct MPT2SAS_ADAPTER *ioc, u32 *event_type) | ||
| 4060 | { | ||
| 4061 | int i, j; | ||
| 4062 | u32 event_mask, desired_event; | ||
| 4063 | u8 send_update_to_fw; | ||
| 4064 | |||
| 4065 | for (i = 0, send_update_to_fw = 0; i < | ||
| 4066 | MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) { | ||
| 4067 | event_mask = ~event_type[i]; | ||
| 4068 | desired_event = 1; | ||
| 4069 | for (j = 0; j < 32; j++) { | ||
| 4070 | if (!(event_mask & desired_event) && | ||
| 4071 | (ioc->event_masks[i] & desired_event)) { | ||
| 4072 | ioc->event_masks[i] &= ~desired_event; | ||
| 4073 | send_update_to_fw = 1; | ||
| 4074 | } | ||
| 4075 | desired_event = (desired_event << 1); | ||
| 4076 | } | ||
| 4077 | } | ||
| 4078 | |||
| 4079 | if (!send_update_to_fw) | ||
| 4080 | return; | ||
| 4081 | |||
| 4082 | mutex_lock(&ioc->base_cmds.mutex); | ||
| 4083 | _base_event_notification(ioc, CAN_SLEEP); | ||
| 4084 | mutex_unlock(&ioc->base_cmds.mutex); | ||
| 4085 | } | ||
| 4086 | |||
| 4087 | /** | ||
| 4088 | * _base_diag_reset - the "big hammer" start of day reset | ||
| 4089 | * @ioc: per adapter object | ||
| 4090 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | ||
| 4091 | * | ||
| 4092 | * Returns 0 for success, non-zero for failure. | ||
| 4093 | */ | ||
| 4094 | static int | ||
| 4095 | _base_diag_reset(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | ||
| 4096 | { | ||
| 4097 | u32 host_diagnostic; | ||
| 4098 | u32 ioc_state; | ||
| 4099 | u32 count; | ||
| 4100 | u32 hcb_size; | ||
| 4101 | |||
| 4102 | printk(MPT2SAS_INFO_FMT "sending diag reset !!\n", ioc->name); | ||
| 4103 | drsprintk(ioc, printk(MPT2SAS_INFO_FMT "clear interrupts\n", | ||
| 4104 | ioc->name)); | ||
| 4105 | |||
| 4106 | count = 0; | ||
| 4107 | do { | ||
| 4108 | /* Write magic sequence to WriteSequence register | ||
| 4109 | * Loop until in diagnostic mode | ||
| 4110 | */ | ||
| 4111 | drsprintk(ioc, printk(MPT2SAS_INFO_FMT "write magic " | ||
| 4112 | "sequence\n", ioc->name)); | ||
| 4113 | writel(MPI2_WRSEQ_FLUSH_KEY_VALUE, &ioc->chip->WriteSequence); | ||
| 4114 | writel(MPI2_WRSEQ_1ST_KEY_VALUE, &ioc->chip->WriteSequence); | ||
| 4115 | writel(MPI2_WRSEQ_2ND_KEY_VALUE, &ioc->chip->WriteSequence); | ||
| 4116 | writel(MPI2_WRSEQ_3RD_KEY_VALUE, &ioc->chip->WriteSequence); | ||
| 4117 | writel(MPI2_WRSEQ_4TH_KEY_VALUE, &ioc->chip->WriteSequence); | ||
| 4118 | writel(MPI2_WRSEQ_5TH_KEY_VALUE, &ioc->chip->WriteSequence); | ||
| 4119 | writel(MPI2_WRSEQ_6TH_KEY_VALUE, &ioc->chip->WriteSequence); | ||
| 4120 | |||
| 4121 | /* wait 100 msec */ | ||
| 4122 | if (sleep_flag == CAN_SLEEP) | ||
| 4123 | msleep(100); | ||
| 4124 | else | ||
| 4125 | mdelay(100); | ||
| 4126 | |||
| 4127 | if (count++ > 20) | ||
| 4128 | goto out; | ||
| 4129 | |||
| 4130 | host_diagnostic = readl(&ioc->chip->HostDiagnostic); | ||
| 4131 | drsprintk(ioc, printk(MPT2SAS_INFO_FMT "wrote magic " | ||
| 4132 | "sequence: count(%d), host_diagnostic(0x%08x)\n", | ||
| 4133 | ioc->name, count, host_diagnostic)); | ||
| 4134 | |||
| 4135 | } while ((host_diagnostic & MPI2_DIAG_DIAG_WRITE_ENABLE) == 0); | ||
| 4136 | |||
| 4137 | hcb_size = readl(&ioc->chip->HCBSize); | ||
| 4138 | |||
| 4139 | drsprintk(ioc, printk(MPT2SAS_INFO_FMT "diag reset: issued\n", | ||
| 4140 | ioc->name)); | ||
| 4141 | writel(host_diagnostic | MPI2_DIAG_RESET_ADAPTER, | ||
| 4142 | &ioc->chip->HostDiagnostic); | ||
| 4143 | |||
| 4144 | /* This delay allows the chip PCIe hardware time to finish reset tasks*/ | ||
| 4145 | if (sleep_flag == CAN_SLEEP) | ||
| 4146 | msleep(MPI2_HARD_RESET_PCIE_FIRST_READ_DELAY_MICRO_SEC/1000); | ||
| 4147 | else | ||
| 4148 | mdelay(MPI2_HARD_RESET_PCIE_FIRST_READ_DELAY_MICRO_SEC/1000); | ||
| 4149 | |||
| 4150 | /* Approximately 300 second max wait */ | ||
| 4151 | for (count = 0; count < (300000000 / | ||
| 4152 | MPI2_HARD_RESET_PCIE_SECOND_READ_DELAY_MICRO_SEC); count++) { | ||
| 4153 | |||
| 4154 | host_diagnostic = readl(&ioc->chip->HostDiagnostic); | ||
| 4155 | |||
| 4156 | if (host_diagnostic == 0xFFFFFFFF) | ||
| 4157 | goto out; | ||
| 4158 | if (!(host_diagnostic & MPI2_DIAG_RESET_ADAPTER)) | ||
| 4159 | break; | ||
| 4160 | |||
| 4161 | /* Wait to pass the second read delay window */ | ||
| 4162 | if (sleep_flag == CAN_SLEEP) | ||
| 4163 | msleep(MPI2_HARD_RESET_PCIE_SECOND_READ_DELAY_MICRO_SEC | ||
| 4164 | /1000); | ||
| 4165 | else | ||
| 4166 | mdelay(MPI2_HARD_RESET_PCIE_SECOND_READ_DELAY_MICRO_SEC | ||
| 4167 | /1000); | ||
| 4168 | } | ||
| 4169 | |||
| 4170 | if (host_diagnostic & MPI2_DIAG_HCB_MODE) { | ||
| 4171 | |||
| 4172 | drsprintk(ioc, printk(MPT2SAS_INFO_FMT "restart the adapter " | ||
| 4173 | "assuming the HCB Address points to good F/W\n", | ||
| 4174 | ioc->name)); | ||
| 4175 | host_diagnostic &= ~MPI2_DIAG_BOOT_DEVICE_SELECT_MASK; | ||
| 4176 | host_diagnostic |= MPI2_DIAG_BOOT_DEVICE_SELECT_HCDW; | ||
| 4177 | writel(host_diagnostic, &ioc->chip->HostDiagnostic); | ||
| 4178 | |||
| 4179 | drsprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 4180 | "re-enable the HCDW\n", ioc->name)); | ||
| 4181 | writel(hcb_size | MPI2_HCB_SIZE_HCB_ENABLE, | ||
| 4182 | &ioc->chip->HCBSize); | ||
| 4183 | } | ||
| 4184 | |||
| 4185 | drsprintk(ioc, printk(MPT2SAS_INFO_FMT "restart the adapter\n", | ||
| 4186 | ioc->name)); | ||
| 4187 | writel(host_diagnostic & ~MPI2_DIAG_HOLD_IOC_RESET, | ||
| 4188 | &ioc->chip->HostDiagnostic); | ||
| 4189 | |||
| 4190 | drsprintk(ioc, printk(MPT2SAS_INFO_FMT "disable writes to the " | ||
| 4191 | "diagnostic register\n", ioc->name)); | ||
| 4192 | writel(MPI2_WRSEQ_FLUSH_KEY_VALUE, &ioc->chip->WriteSequence); | ||
| 4193 | |||
| 4194 | drsprintk(ioc, printk(MPT2SAS_INFO_FMT "Wait for FW to go to the " | ||
| 4195 | "READY state\n", ioc->name)); | ||
| 4196 | ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY, 20, | ||
| 4197 | sleep_flag); | ||
| 4198 | if (ioc_state) { | ||
| 4199 | printk(MPT2SAS_ERR_FMT "%s: failed going to ready state " | ||
| 4200 | " (ioc_state=0x%x)\n", ioc->name, __func__, ioc_state); | ||
| 4201 | goto out; | ||
| 4202 | } | ||
| 4203 | |||
| 4204 | printk(MPT2SAS_INFO_FMT "diag reset: SUCCESS\n", ioc->name); | ||
| 4205 | return 0; | ||
| 4206 | |||
| 4207 | out: | ||
| 4208 | printk(MPT2SAS_ERR_FMT "diag reset: FAILED\n", ioc->name); | ||
| 4209 | return -EFAULT; | ||
| 4210 | } | ||
| 4211 | |||
| 4212 | /** | ||
| 4213 | * _base_make_ioc_ready - put controller in READY state | ||
| 4214 | * @ioc: per adapter object | ||
| 4215 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | ||
| 4216 | * @type: FORCE_BIG_HAMMER or SOFT_RESET | ||
| 4217 | * | ||
| 4218 | * Returns 0 for success, non-zero for failure. | ||
| 4219 | */ | ||
| 4220 | static int | ||
| 4221 | _base_make_ioc_ready(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, | ||
| 4222 | enum reset_type type) | ||
| 4223 | { | ||
| 4224 | u32 ioc_state; | ||
| 4225 | int rc; | ||
| 4226 | |||
| 4227 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | ||
| 4228 | __func__)); | ||
| 4229 | |||
| 4230 | if (ioc->pci_error_recovery) | ||
| 4231 | return 0; | ||
| 4232 | |||
| 4233 | ioc_state = mpt2sas_base_get_iocstate(ioc, 0); | ||
| 4234 | dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: ioc_state(0x%08x)\n", | ||
| 4235 | ioc->name, __func__, ioc_state)); | ||
| 4236 | |||
| 4237 | if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_READY) | ||
| 4238 | return 0; | ||
| 4239 | |||
| 4240 | if (ioc_state & MPI2_DOORBELL_USED) { | ||
| 4241 | dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "unexpected doorbell " | ||
| 4242 | "active!\n", ioc->name)); | ||
| 4243 | goto issue_diag_reset; | ||
| 4244 | } | ||
| 4245 | |||
| 4246 | if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) { | ||
| 4247 | mpt2sas_base_fault_info(ioc, ioc_state & | ||
| 4248 | MPI2_DOORBELL_DATA_MASK); | ||
| 4249 | goto issue_diag_reset; | ||
| 4250 | } | ||
| 4251 | |||
| 4252 | if (type == FORCE_BIG_HAMMER) | ||
| 4253 | goto issue_diag_reset; | ||
| 4254 | |||
| 4255 | if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_OPERATIONAL) | ||
| 4256 | if (!(_base_send_ioc_reset(ioc, | ||
| 4257 | MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET, 15, CAN_SLEEP))) { | ||
| 4258 | ioc->ioc_reset_count++; | ||
| 4259 | return 0; | ||
| 4260 | } | ||
| 4261 | |||
| 4262 | issue_diag_reset: | ||
| 4263 | rc = _base_diag_reset(ioc, CAN_SLEEP); | ||
| 4264 | ioc->ioc_reset_count++; | ||
| 4265 | return rc; | ||
| 4266 | } | ||
| 4267 | |||
| 4268 | /** | ||
| 4269 | * _base_make_ioc_operational - put controller in OPERATIONAL state | ||
| 4270 | * @ioc: per adapter object | ||
| 4271 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | ||
| 4272 | * | ||
| 4273 | * Returns 0 for success, non-zero for failure. | ||
| 4274 | */ | ||
| 4275 | static int | ||
| 4276 | _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | ||
| 4277 | { | ||
| 4278 | int r, i; | ||
| 4279 | unsigned long flags; | ||
| 4280 | u32 reply_address; | ||
| 4281 | u16 smid; | ||
| 4282 | struct _tr_list *delayed_tr, *delayed_tr_next; | ||
| 4283 | u8 hide_flag; | ||
| 4284 | struct adapter_reply_queue *reply_q; | ||
| 4285 | long reply_post_free; | ||
| 4286 | u32 reply_post_free_sz, index = 0; | ||
| 4287 | |||
| 4288 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | ||
| 4289 | __func__)); | ||
| 4290 | |||
| 4291 | /* clean the delayed target reset list */ | ||
| 4292 | list_for_each_entry_safe(delayed_tr, delayed_tr_next, | ||
| 4293 | &ioc->delayed_tr_list, list) { | ||
| 4294 | list_del(&delayed_tr->list); | ||
| 4295 | kfree(delayed_tr); | ||
| 4296 | } | ||
| 4297 | |||
| 4298 | list_for_each_entry_safe(delayed_tr, delayed_tr_next, | ||
| 4299 | &ioc->delayed_tr_volume_list, list) { | ||
| 4300 | list_del(&delayed_tr->list); | ||
| 4301 | kfree(delayed_tr); | ||
| 4302 | } | ||
| 4303 | |||
| 4304 | /* initialize the scsi lookup free list */ | ||
| 4305 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | ||
| 4306 | INIT_LIST_HEAD(&ioc->free_list); | ||
| 4307 | smid = 1; | ||
| 4308 | for (i = 0; i < ioc->scsiio_depth; i++, smid++) { | ||
| 4309 | INIT_LIST_HEAD(&ioc->scsi_lookup[i].chain_list); | ||
| 4310 | ioc->scsi_lookup[i].cb_idx = 0xFF; | ||
| 4311 | ioc->scsi_lookup[i].smid = smid; | ||
| 4312 | ioc->scsi_lookup[i].scmd = NULL; | ||
| 4313 | ioc->scsi_lookup[i].direct_io = 0; | ||
| 4314 | list_add_tail(&ioc->scsi_lookup[i].tracker_list, | ||
| 4315 | &ioc->free_list); | ||
| 4316 | } | ||
| 4317 | |||
| 4318 | /* hi-priority queue */ | ||
| 4319 | INIT_LIST_HEAD(&ioc->hpr_free_list); | ||
| 4320 | smid = ioc->hi_priority_smid; | ||
| 4321 | for (i = 0; i < ioc->hi_priority_depth; i++, smid++) { | ||
| 4322 | ioc->hpr_lookup[i].cb_idx = 0xFF; | ||
| 4323 | ioc->hpr_lookup[i].smid = smid; | ||
| 4324 | list_add_tail(&ioc->hpr_lookup[i].tracker_list, | ||
| 4325 | &ioc->hpr_free_list); | ||
| 4326 | } | ||
| 4327 | |||
| 4328 | /* internal queue */ | ||
| 4329 | INIT_LIST_HEAD(&ioc->internal_free_list); | ||
| 4330 | smid = ioc->internal_smid; | ||
| 4331 | for (i = 0; i < ioc->internal_depth; i++, smid++) { | ||
| 4332 | ioc->internal_lookup[i].cb_idx = 0xFF; | ||
| 4333 | ioc->internal_lookup[i].smid = smid; | ||
| 4334 | list_add_tail(&ioc->internal_lookup[i].tracker_list, | ||
| 4335 | &ioc->internal_free_list); | ||
| 4336 | } | ||
| 4337 | |||
| 4338 | /* chain pool */ | ||
| 4339 | INIT_LIST_HEAD(&ioc->free_chain_list); | ||
| 4340 | for (i = 0; i < ioc->chain_depth; i++) | ||
| 4341 | list_add_tail(&ioc->chain_lookup[i].tracker_list, | ||
| 4342 | &ioc->free_chain_list); | ||
| 4343 | |||
| 4344 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | ||
| 4345 | |||
| 4346 | /* initialize Reply Free Queue */ | ||
| 4347 | for (i = 0, reply_address = (u32)ioc->reply_dma ; | ||
| 4348 | i < ioc->reply_free_queue_depth ; i++, reply_address += | ||
| 4349 | ioc->reply_sz) | ||
| 4350 | ioc->reply_free[i] = cpu_to_le32(reply_address); | ||
| 4351 | |||
| 4352 | /* initialize reply queues */ | ||
| 4353 | if (ioc->is_driver_loading) | ||
| 4354 | _base_assign_reply_queues(ioc); | ||
| 4355 | |||
| 4356 | /* initialize Reply Post Free Queue */ | ||
| 4357 | reply_post_free_sz = ioc->reply_post_queue_depth * | ||
| 4358 | sizeof(Mpi2DefaultReplyDescriptor_t); | ||
| 4359 | reply_post_free = (long)ioc->reply_post[index].reply_post_free; | ||
| 4360 | list_for_each_entry(reply_q, &ioc->reply_queue_list, list) { | ||
| 4361 | reply_q->reply_post_host_index = 0; | ||
| 4362 | reply_q->reply_post_free = (Mpi2ReplyDescriptorsUnion_t *) | ||
| 4363 | reply_post_free; | ||
| 4364 | for (i = 0; i < ioc->reply_post_queue_depth; i++) | ||
| 4365 | reply_q->reply_post_free[i].Words = | ||
| 4366 | cpu_to_le64(ULLONG_MAX); | ||
| 4367 | if (!_base_is_controller_msix_enabled(ioc)) | ||
| 4368 | goto skip_init_reply_post_free_queue; | ||
| 4369 | /* | ||
| 4370 | * If RDPQ is enabled, switch to the next allocation. | ||
| 4371 | * Otherwise advance within the contiguous region. | ||
| 4372 | */ | ||
| 4373 | if (ioc->rdpq_array_enable) | ||
| 4374 | reply_post_free = (long) | ||
| 4375 | ioc->reply_post[++index].reply_post_free; | ||
| 4376 | else | ||
| 4377 | reply_post_free += reply_post_free_sz; | ||
| 4378 | } | ||
| 4379 | skip_init_reply_post_free_queue: | ||
| 4380 | |||
| 4381 | r = _base_send_ioc_init(ioc, sleep_flag); | ||
| 4382 | if (r) | ||
| 4383 | return r; | ||
| 4384 | |||
| 4385 | /* initialize reply free host index */ | ||
| 4386 | ioc->reply_free_host_index = ioc->reply_free_queue_depth - 1; | ||
| 4387 | writel(ioc->reply_free_host_index, &ioc->chip->ReplyFreeHostIndex); | ||
| 4388 | |||
| 4389 | /* initialize reply post host index */ | ||
| 4390 | list_for_each_entry(reply_q, &ioc->reply_queue_list, list) { | ||
| 4391 | writel(reply_q->msix_index << MPI2_RPHI_MSIX_INDEX_SHIFT, | ||
| 4392 | &ioc->chip->ReplyPostHostIndex); | ||
| 4393 | if (!_base_is_controller_msix_enabled(ioc)) | ||
| 4394 | goto skip_init_reply_post_host_index; | ||
| 4395 | } | ||
| 4396 | |||
| 4397 | skip_init_reply_post_host_index: | ||
| 4398 | |||
| 4399 | _base_unmask_interrupts(ioc); | ||
| 4400 | |||
| 4401 | r = _base_event_notification(ioc, sleep_flag); | ||
| 4402 | if (r) | ||
| 4403 | return r; | ||
| 4404 | |||
| 4405 | if (sleep_flag == CAN_SLEEP) | ||
| 4406 | _base_static_config_pages(ioc); | ||
| 4407 | |||
| 4408 | |||
| 4409 | if (ioc->is_driver_loading) { | ||
| 4410 | if (ioc->is_warpdrive && ioc->manu_pg10.OEMIdentifier | ||
| 4411 | == 0x80) { | ||
| 4412 | hide_flag = (u8) ( | ||
| 4413 | le32_to_cpu(ioc->manu_pg10.OEMSpecificFlags0) & | ||
| 4414 | MFG_PAGE10_HIDE_SSDS_MASK); | ||
| 4415 | if (hide_flag != MFG_PAGE10_HIDE_SSDS_MASK) | ||
| 4416 | ioc->mfg_pg10_hide_flag = hide_flag; | ||
| 4417 | } | ||
| 4418 | ioc->wait_for_discovery_to_complete = | ||
| 4419 | _base_determine_wait_on_discovery(ioc); | ||
| 4420 | return r; /* scan_start and scan_finished support */ | ||
| 4421 | } | ||
| 4422 | r = _base_send_port_enable(ioc, sleep_flag); | ||
| 4423 | if (r) | ||
| 4424 | return r; | ||
| 4425 | |||
| 4426 | return r; | ||
| 4427 | } | ||
| 4428 | |||
| 4429 | /** | ||
| 4430 | * mpt2sas_base_free_resources - free resources controller resources (io/irq/memap) | ||
| 4431 | * @ioc: per adapter object | ||
| 4432 | * | ||
| 4433 | * Return nothing. | ||
| 4434 | */ | ||
| 4435 | void | ||
| 4436 | mpt2sas_base_free_resources(struct MPT2SAS_ADAPTER *ioc) | ||
| 4437 | { | ||
| 4438 | struct pci_dev *pdev = ioc->pdev; | ||
| 4439 | |||
| 4440 | dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | ||
| 4441 | __func__)); | ||
| 4442 | |||
| 4443 | /* synchronizing freeing resource with pci_access_mutex lock */ | ||
| 4444 | mutex_lock(&ioc->pci_access_mutex); | ||
| 4445 | if (ioc->chip_phys && ioc->chip) { | ||
| 4446 | _base_mask_interrupts(ioc); | ||
| 4447 | ioc->shost_recovery = 1; | ||
| 4448 | _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET); | ||
| 4449 | ioc->shost_recovery = 0; | ||
| 4450 | } | ||
| 4451 | |||
| 4452 | _base_free_irq(ioc); | ||
| 4453 | _base_disable_msix(ioc); | ||
| 4454 | |||
| 4455 | if (ioc->chip_phys && ioc->chip) | ||
| 4456 | iounmap(ioc->chip); | ||
| 4457 | ioc->chip_phys = 0; | ||
| 4458 | |||
| 4459 | if (pci_is_enabled(pdev)) { | ||
| 4460 | pci_release_selected_regions(ioc->pdev, ioc->bars); | ||
| 4461 | pci_disable_pcie_error_reporting(pdev); | ||
| 4462 | pci_disable_device(pdev); | ||
| 4463 | } | ||
| 4464 | mutex_unlock(&ioc->pci_access_mutex); | ||
| 4465 | return; | ||
| 4466 | } | ||
| 4467 | |||
| 4468 | /** | ||
| 4469 | * mpt2sas_base_attach - attach controller instance | ||
| 4470 | * @ioc: per adapter object | ||
| 4471 | * | ||
| 4472 | * Returns 0 for success, non-zero for failure. | ||
| 4473 | */ | ||
| 4474 | int | ||
| 4475 | mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) | ||
| 4476 | { | ||
| 4477 | int r, i; | ||
| 4478 | int cpu_id, last_cpu_id = 0; | ||
| 4479 | |||
| 4480 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | ||
| 4481 | __func__)); | ||
| 4482 | |||
| 4483 | /* setup cpu_msix_table */ | ||
| 4484 | ioc->cpu_count = num_online_cpus(); | ||
| 4485 | for_each_online_cpu(cpu_id) | ||
| 4486 | last_cpu_id = cpu_id; | ||
| 4487 | ioc->cpu_msix_table_sz = last_cpu_id + 1; | ||
| 4488 | ioc->cpu_msix_table = kzalloc(ioc->cpu_msix_table_sz, GFP_KERNEL); | ||
| 4489 | ioc->reply_queue_count = 1; | ||
| 4490 | if (!ioc->cpu_msix_table) { | ||
| 4491 | dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "allocation for " | ||
| 4492 | "cpu_msix_table failed!!!\n", ioc->name)); | ||
| 4493 | r = -ENOMEM; | ||
| 4494 | goto out_free_resources; | ||
| 4495 | } | ||
| 4496 | |||
| 4497 | if (ioc->is_warpdrive) { | ||
| 4498 | ioc->reply_post_host_index = kcalloc(ioc->cpu_msix_table_sz, | ||
| 4499 | sizeof(resource_size_t *), GFP_KERNEL); | ||
| 4500 | if (!ioc->reply_post_host_index) { | ||
| 4501 | dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "allocation " | ||
| 4502 | "for cpu_msix_table failed!!!\n", ioc->name)); | ||
| 4503 | r = -ENOMEM; | ||
| 4504 | goto out_free_resources; | ||
| 4505 | } | ||
| 4506 | } | ||
| 4507 | |||
| 4508 | ioc->rdpq_array_enable_assigned = 0; | ||
| 4509 | ioc->dma_mask = 0; | ||
| 4510 | r = mpt2sas_base_map_resources(ioc); | ||
| 4511 | if (r) | ||
| 4512 | goto out_free_resources; | ||
| 4513 | |||
| 4514 | if (ioc->is_warpdrive) { | ||
| 4515 | ioc->reply_post_host_index[0] = (resource_size_t __iomem *) | ||
| 4516 | &ioc->chip->ReplyPostHostIndex; | ||
| 4517 | |||
| 4518 | for (i = 1; i < ioc->cpu_msix_table_sz; i++) | ||
| 4519 | ioc->reply_post_host_index[i] = | ||
| 4520 | (resource_size_t __iomem *) | ||
| 4521 | ((u8 __iomem *)&ioc->chip->Doorbell + (0x4000 + ((i - 1) | ||
| 4522 | * 4))); | ||
| 4523 | } | ||
| 4524 | |||
| 4525 | pci_set_drvdata(ioc->pdev, ioc->shost); | ||
| 4526 | r = _base_get_ioc_facts(ioc, CAN_SLEEP); | ||
| 4527 | if (r) | ||
| 4528 | goto out_free_resources; | ||
| 4529 | |||
| 4530 | r = _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET); | ||
| 4531 | if (r) | ||
| 4532 | goto out_free_resources; | ||
| 4533 | |||
| 4534 | ioc->pfacts = kcalloc(ioc->facts.NumberOfPorts, | ||
| 4535 | sizeof(struct mpt2sas_port_facts), GFP_KERNEL); | ||
| 4536 | if (!ioc->pfacts) { | ||
| 4537 | r = -ENOMEM; | ||
| 4538 | goto out_free_resources; | ||
| 4539 | } | ||
| 4540 | |||
| 4541 | for (i = 0 ; i < ioc->facts.NumberOfPorts; i++) { | ||
| 4542 | r = _base_get_port_facts(ioc, i, CAN_SLEEP); | ||
| 4543 | if (r) | ||
| 4544 | goto out_free_resources; | ||
| 4545 | } | ||
| 4546 | |||
| 4547 | r = _base_allocate_memory_pools(ioc, CAN_SLEEP); | ||
| 4548 | if (r) | ||
| 4549 | goto out_free_resources; | ||
| 4550 | |||
| 4551 | init_waitqueue_head(&ioc->reset_wq); | ||
| 4552 | /* allocate memory pd handle bitmask list */ | ||
| 4553 | ioc->pd_handles_sz = (ioc->facts.MaxDevHandle / 8); | ||
| 4554 | if (ioc->facts.MaxDevHandle % 8) | ||
| 4555 | ioc->pd_handles_sz++; | ||
| 4556 | ioc->pd_handles = kzalloc(ioc->pd_handles_sz, | ||
| 4557 | GFP_KERNEL); | ||
| 4558 | if (!ioc->pd_handles) { | ||
| 4559 | r = -ENOMEM; | ||
| 4560 | goto out_free_resources; | ||
| 4561 | } | ||
| 4562 | ioc->blocking_handles = kzalloc(ioc->pd_handles_sz, | ||
| 4563 | GFP_KERNEL); | ||
| 4564 | if (!ioc->blocking_handles) { | ||
| 4565 | r = -ENOMEM; | ||
| 4566 | goto out_free_resources; | ||
| 4567 | } | ||
| 4568 | ioc->fwfault_debug = mpt2sas_fwfault_debug; | ||
| 4569 | |||
| 4570 | /* base internal command bits */ | ||
| 4571 | mutex_init(&ioc->base_cmds.mutex); | ||
| 4572 | ioc->base_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); | ||
| 4573 | ioc->base_cmds.status = MPT2_CMD_NOT_USED; | ||
| 4574 | |||
| 4575 | /* port_enable command bits */ | ||
| 4576 | ioc->port_enable_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); | ||
| 4577 | ioc->port_enable_cmds.status = MPT2_CMD_NOT_USED; | ||
| 4578 | |||
| 4579 | /* transport internal command bits */ | ||
| 4580 | ioc->transport_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); | ||
| 4581 | ioc->transport_cmds.status = MPT2_CMD_NOT_USED; | ||
| 4582 | mutex_init(&ioc->transport_cmds.mutex); | ||
| 4583 | |||
| 4584 | /* scsih internal command bits */ | ||
| 4585 | ioc->scsih_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); | ||
| 4586 | ioc->scsih_cmds.status = MPT2_CMD_NOT_USED; | ||
| 4587 | mutex_init(&ioc->scsih_cmds.mutex); | ||
| 4588 | |||
| 4589 | /* task management internal command bits */ | ||
| 4590 | ioc->tm_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); | ||
| 4591 | ioc->tm_cmds.status = MPT2_CMD_NOT_USED; | ||
| 4592 | mutex_init(&ioc->tm_cmds.mutex); | ||
| 4593 | |||
| 4594 | /* config page internal command bits */ | ||
| 4595 | ioc->config_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); | ||
| 4596 | ioc->config_cmds.status = MPT2_CMD_NOT_USED; | ||
| 4597 | mutex_init(&ioc->config_cmds.mutex); | ||
| 4598 | |||
| 4599 | /* ctl module internal command bits */ | ||
| 4600 | ioc->ctl_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); | ||
| 4601 | ioc->ctl_cmds.sense = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL); | ||
| 4602 | ioc->ctl_cmds.status = MPT2_CMD_NOT_USED; | ||
| 4603 | mutex_init(&ioc->ctl_cmds.mutex); | ||
| 4604 | |||
| 4605 | if (!ioc->base_cmds.reply || !ioc->transport_cmds.reply || | ||
| 4606 | !ioc->scsih_cmds.reply || !ioc->tm_cmds.reply || | ||
| 4607 | !ioc->config_cmds.reply || !ioc->ctl_cmds.reply || | ||
| 4608 | !ioc->ctl_cmds.sense) { | ||
| 4609 | r = -ENOMEM; | ||
| 4610 | goto out_free_resources; | ||
| 4611 | } | ||
| 4612 | |||
| 4613 | if (!ioc->base_cmds.reply || !ioc->transport_cmds.reply || | ||
| 4614 | !ioc->scsih_cmds.reply || !ioc->tm_cmds.reply || | ||
| 4615 | !ioc->config_cmds.reply || !ioc->ctl_cmds.reply) { | ||
| 4616 | r = -ENOMEM; | ||
| 4617 | goto out_free_resources; | ||
| 4618 | } | ||
| 4619 | |||
| 4620 | for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) | ||
| 4621 | ioc->event_masks[i] = -1; | ||
| 4622 | |||
| 4623 | /* here we enable the events we care about */ | ||
| 4624 | _base_unmask_events(ioc, MPI2_EVENT_SAS_DISCOVERY); | ||
| 4625 | _base_unmask_events(ioc, MPI2_EVENT_SAS_BROADCAST_PRIMITIVE); | ||
| 4626 | _base_unmask_events(ioc, MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST); | ||
| 4627 | _base_unmask_events(ioc, MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE); | ||
| 4628 | _base_unmask_events(ioc, MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE); | ||
| 4629 | _base_unmask_events(ioc, MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST); | ||
| 4630 | _base_unmask_events(ioc, MPI2_EVENT_IR_VOLUME); | ||
| 4631 | _base_unmask_events(ioc, MPI2_EVENT_IR_PHYSICAL_DISK); | ||
| 4632 | _base_unmask_events(ioc, MPI2_EVENT_IR_OPERATION_STATUS); | ||
| 4633 | _base_unmask_events(ioc, MPI2_EVENT_LOG_ENTRY_ADDED); | ||
| 4634 | _base_unmask_events(ioc, MPI2_EVENT_TEMP_THRESHOLD); | ||
| 4635 | r = _base_make_ioc_operational(ioc, CAN_SLEEP); | ||
| 4636 | if (r) | ||
| 4637 | goto out_free_resources; | ||
| 4638 | |||
| 4639 | ioc->non_operational_loop = 0; | ||
| 4640 | |||
| 4641 | return 0; | ||
| 4642 | |||
| 4643 | out_free_resources: | ||
| 4644 | |||
| 4645 | ioc->remove_host = 1; | ||
| 4646 | mpt2sas_base_free_resources(ioc); | ||
| 4647 | _base_release_memory_pools(ioc); | ||
| 4648 | pci_set_drvdata(ioc->pdev, NULL); | ||
| 4649 | kfree(ioc->cpu_msix_table); | ||
| 4650 | if (ioc->is_warpdrive) | ||
| 4651 | kfree(ioc->reply_post_host_index); | ||
| 4652 | kfree(ioc->pd_handles); | ||
| 4653 | kfree(ioc->blocking_handles); | ||
| 4654 | kfree(ioc->tm_cmds.reply); | ||
| 4655 | kfree(ioc->transport_cmds.reply); | ||
| 4656 | kfree(ioc->scsih_cmds.reply); | ||
| 4657 | kfree(ioc->config_cmds.reply); | ||
| 4658 | kfree(ioc->base_cmds.reply); | ||
| 4659 | kfree(ioc->port_enable_cmds.reply); | ||
| 4660 | kfree(ioc->ctl_cmds.reply); | ||
| 4661 | kfree(ioc->ctl_cmds.sense); | ||
| 4662 | kfree(ioc->pfacts); | ||
| 4663 | ioc->ctl_cmds.reply = NULL; | ||
| 4664 | ioc->base_cmds.reply = NULL; | ||
| 4665 | ioc->tm_cmds.reply = NULL; | ||
| 4666 | ioc->scsih_cmds.reply = NULL; | ||
| 4667 | ioc->transport_cmds.reply = NULL; | ||
| 4668 | ioc->config_cmds.reply = NULL; | ||
| 4669 | ioc->pfacts = NULL; | ||
| 4670 | return r; | ||
| 4671 | } | ||
| 4672 | |||
| 4673 | |||
| 4674 | /** | ||
| 4675 | * mpt2sas_base_detach - remove controller instance | ||
| 4676 | * @ioc: per adapter object | ||
| 4677 | * | ||
| 4678 | * Return nothing. | ||
| 4679 | */ | ||
| 4680 | void | ||
| 4681 | mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc) | ||
| 4682 | { | ||
| 4683 | |||
| 4684 | dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | ||
| 4685 | __func__)); | ||
| 4686 | |||
| 4687 | mpt2sas_base_stop_watchdog(ioc); | ||
| 4688 | mpt2sas_base_free_resources(ioc); | ||
| 4689 | _base_release_memory_pools(ioc); | ||
| 4690 | pci_set_drvdata(ioc->pdev, NULL); | ||
| 4691 | kfree(ioc->cpu_msix_table); | ||
| 4692 | if (ioc->is_warpdrive) | ||
| 4693 | kfree(ioc->reply_post_host_index); | ||
| 4694 | kfree(ioc->pd_handles); | ||
| 4695 | kfree(ioc->blocking_handles); | ||
| 4696 | kfree(ioc->pfacts); | ||
| 4697 | kfree(ioc->ctl_cmds.reply); | ||
| 4698 | kfree(ioc->ctl_cmds.sense); | ||
| 4699 | kfree(ioc->base_cmds.reply); | ||
| 4700 | kfree(ioc->port_enable_cmds.reply); | ||
| 4701 | kfree(ioc->tm_cmds.reply); | ||
| 4702 | kfree(ioc->transport_cmds.reply); | ||
| 4703 | kfree(ioc->scsih_cmds.reply); | ||
| 4704 | kfree(ioc->config_cmds.reply); | ||
| 4705 | } | ||
| 4706 | |||
| 4707 | /** | ||
| 4708 | * _base_reset_handler - reset callback handler (for base) | ||
| 4709 | * @ioc: per adapter object | ||
| 4710 | * @reset_phase: phase | ||
| 4711 | * | ||
| 4712 | * The handler for doing any required cleanup or initialization. | ||
| 4713 | * | ||
| 4714 | * The reset phase can be MPT2_IOC_PRE_RESET, MPT2_IOC_AFTER_RESET, | ||
| 4715 | * MPT2_IOC_DONE_RESET | ||
| 4716 | * | ||
| 4717 | * Return nothing. | ||
| 4718 | */ | ||
| 4719 | static void | ||
| 4720 | _base_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase) | ||
| 4721 | { | ||
| 4722 | mpt2sas_scsih_reset_handler(ioc, reset_phase); | ||
| 4723 | mpt2sas_ctl_reset_handler(ioc, reset_phase); | ||
| 4724 | switch (reset_phase) { | ||
| 4725 | case MPT2_IOC_PRE_RESET: | ||
| 4726 | dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " | ||
| 4727 | "MPT2_IOC_PRE_RESET\n", ioc->name, __func__)); | ||
| 4728 | break; | ||
| 4729 | case MPT2_IOC_AFTER_RESET: | ||
| 4730 | dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " | ||
| 4731 | "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__)); | ||
| 4732 | if (ioc->transport_cmds.status & MPT2_CMD_PENDING) { | ||
| 4733 | ioc->transport_cmds.status |= MPT2_CMD_RESET; | ||
| 4734 | mpt2sas_base_free_smid(ioc, ioc->transport_cmds.smid); | ||
| 4735 | complete(&ioc->transport_cmds.done); | ||
| 4736 | } | ||
| 4737 | if (ioc->base_cmds.status & MPT2_CMD_PENDING) { | ||
| 4738 | ioc->base_cmds.status |= MPT2_CMD_RESET; | ||
| 4739 | mpt2sas_base_free_smid(ioc, ioc->base_cmds.smid); | ||
| 4740 | complete(&ioc->base_cmds.done); | ||
| 4741 | } | ||
| 4742 | if (ioc->port_enable_cmds.status & MPT2_CMD_PENDING) { | ||
| 4743 | ioc->port_enable_failed = 1; | ||
| 4744 | ioc->port_enable_cmds.status |= MPT2_CMD_RESET; | ||
| 4745 | mpt2sas_base_free_smid(ioc, ioc->port_enable_cmds.smid); | ||
| 4746 | if (ioc->is_driver_loading) { | ||
| 4747 | ioc->start_scan_failed = | ||
| 4748 | MPI2_IOCSTATUS_INTERNAL_ERROR; | ||
| 4749 | ioc->start_scan = 0; | ||
| 4750 | ioc->port_enable_cmds.status = | ||
| 4751 | MPT2_CMD_NOT_USED; | ||
| 4752 | } else | ||
| 4753 | complete(&ioc->port_enable_cmds.done); | ||
| 4754 | |||
| 4755 | } | ||
| 4756 | if (ioc->config_cmds.status & MPT2_CMD_PENDING) { | ||
| 4757 | ioc->config_cmds.status |= MPT2_CMD_RESET; | ||
| 4758 | mpt2sas_base_free_smid(ioc, ioc->config_cmds.smid); | ||
| 4759 | ioc->config_cmds.smid = USHRT_MAX; | ||
| 4760 | complete(&ioc->config_cmds.done); | ||
| 4761 | } | ||
| 4762 | break; | ||
| 4763 | case MPT2_IOC_DONE_RESET: | ||
| 4764 | dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " | ||
| 4765 | "MPT2_IOC_DONE_RESET\n", ioc->name, __func__)); | ||
| 4766 | break; | ||
| 4767 | } | ||
| 4768 | } | ||
| 4769 | |||
| 4770 | /** | ||
| 4771 | * _wait_for_commands_to_complete - reset controller | ||
| 4772 | * @ioc: Pointer to MPT_ADAPTER structure | ||
| 4773 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | ||
| 4774 | * | ||
| 4775 | * This function waiting(3s) for all pending commands to complete | ||
| 4776 | * prior to putting controller in reset. | ||
| 4777 | */ | ||
| 4778 | static void | ||
| 4779 | _wait_for_commands_to_complete(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | ||
| 4780 | { | ||
| 4781 | u32 ioc_state; | ||
| 4782 | unsigned long flags; | ||
| 4783 | u16 i; | ||
| 4784 | |||
| 4785 | ioc->pending_io_count = 0; | ||
| 4786 | if (sleep_flag != CAN_SLEEP) | ||
| 4787 | return; | ||
| 4788 | |||
| 4789 | ioc_state = mpt2sas_base_get_iocstate(ioc, 0); | ||
| 4790 | if ((ioc_state & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_OPERATIONAL) | ||
| 4791 | return; | ||
| 4792 | |||
| 4793 | /* pending command count */ | ||
| 4794 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | ||
| 4795 | for (i = 0; i < ioc->scsiio_depth; i++) | ||
| 4796 | if (ioc->scsi_lookup[i].cb_idx != 0xFF) | ||
| 4797 | ioc->pending_io_count++; | ||
| 4798 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | ||
| 4799 | |||
| 4800 | if (!ioc->pending_io_count) | ||
| 4801 | return; | ||
| 4802 | |||
| 4803 | /* wait for pending commands to complete */ | ||
| 4804 | wait_event_timeout(ioc->reset_wq, ioc->pending_io_count == 0, 10 * HZ); | ||
| 4805 | } | ||
| 4806 | |||
| 4807 | /** | ||
| 4808 | * mpt2sas_base_hard_reset_handler - reset controller | ||
| 4809 | * @ioc: Pointer to MPT_ADAPTER structure | ||
| 4810 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | ||
| 4811 | * @type: FORCE_BIG_HAMMER or SOFT_RESET | ||
| 4812 | * | ||
| 4813 | * Returns 0 for success, non-zero for failure. | ||
| 4814 | */ | ||
| 4815 | int | ||
| 4816 | mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, | ||
| 4817 | enum reset_type type) | ||
| 4818 | { | ||
| 4819 | int r; | ||
| 4820 | unsigned long flags; | ||
| 4821 | |||
| 4822 | dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name, | ||
| 4823 | __func__)); | ||
| 4824 | |||
| 4825 | if (ioc->pci_error_recovery) { | ||
| 4826 | printk(MPT2SAS_ERR_FMT "%s: pci error recovery reset\n", | ||
| 4827 | ioc->name, __func__); | ||
| 4828 | r = 0; | ||
| 4829 | goto out_unlocked; | ||
| 4830 | } | ||
| 4831 | |||
| 4832 | if (mpt2sas_fwfault_debug) | ||
| 4833 | mpt2sas_halt_firmware(ioc); | ||
| 4834 | |||
| 4835 | /* TODO - What we really should be doing is pulling | ||
| 4836 | * out all the code associated with NO_SLEEP; its never used. | ||
| 4837 | * That is legacy code from mpt fusion driver, ported over. | ||
| 4838 | * I will leave this BUG_ON here for now till its been resolved. | ||
| 4839 | */ | ||
| 4840 | BUG_ON(sleep_flag == NO_SLEEP); | ||
| 4841 | |||
| 4842 | /* wait for an active reset in progress to complete */ | ||
| 4843 | if (!mutex_trylock(&ioc->reset_in_progress_mutex)) { | ||
| 4844 | do { | ||
| 4845 | ssleep(1); | ||
| 4846 | } while (ioc->shost_recovery == 1); | ||
| 4847 | dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: exit\n", ioc->name, | ||
| 4848 | __func__)); | ||
| 4849 | return ioc->ioc_reset_in_progress_status; | ||
| 4850 | } | ||
| 4851 | |||
| 4852 | spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); | ||
| 4853 | ioc->shost_recovery = 1; | ||
| 4854 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); | ||
| 4855 | |||
| 4856 | _base_reset_handler(ioc, MPT2_IOC_PRE_RESET); | ||
| 4857 | _wait_for_commands_to_complete(ioc, sleep_flag); | ||
| 4858 | _base_mask_interrupts(ioc); | ||
| 4859 | r = _base_make_ioc_ready(ioc, sleep_flag, type); | ||
| 4860 | if (r) | ||
| 4861 | goto out; | ||
| 4862 | _base_reset_handler(ioc, MPT2_IOC_AFTER_RESET); | ||
| 4863 | |||
| 4864 | /* If this hard reset is called while port enable is active, then | ||
| 4865 | * there is no reason to call make_ioc_operational | ||
| 4866 | */ | ||
| 4867 | if (ioc->is_driver_loading && ioc->port_enable_failed) { | ||
| 4868 | ioc->remove_host = 1; | ||
| 4869 | r = -EFAULT; | ||
| 4870 | goto out; | ||
| 4871 | } | ||
| 4872 | |||
| 4873 | r = _base_get_ioc_facts(ioc, CAN_SLEEP); | ||
| 4874 | if (r) | ||
| 4875 | goto out; | ||
| 4876 | |||
| 4877 | if (ioc->rdpq_array_enable && !ioc->rdpq_array_capable) | ||
| 4878 | panic("%s: Issue occurred with flashing controller firmware." | ||
| 4879 | "Please reboot the system and ensure that the correct" | ||
| 4880 | " firmware version is running\n", ioc->name); | ||
| 4881 | |||
| 4882 | r = _base_make_ioc_operational(ioc, sleep_flag); | ||
| 4883 | if (!r) | ||
| 4884 | _base_reset_handler(ioc, MPT2_IOC_DONE_RESET); | ||
| 4885 | out: | ||
| 4886 | dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: %s\n", | ||
| 4887 | ioc->name, __func__, ((r == 0) ? "SUCCESS" : "FAILED"))); | ||
| 4888 | |||
| 4889 | spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); | ||
| 4890 | ioc->ioc_reset_in_progress_status = r; | ||
| 4891 | ioc->shost_recovery = 0; | ||
| 4892 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); | ||
| 4893 | mutex_unlock(&ioc->reset_in_progress_mutex); | ||
| 4894 | |||
| 4895 | out_unlocked: | ||
| 4896 | dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: exit\n", ioc->name, | ||
| 4897 | __func__)); | ||
| 4898 | return r; | ||
| 4899 | } | ||
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h deleted file mode 100644 index 97ea360c6920..000000000000 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ /dev/null | |||
| @@ -1,1235 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * This is the Fusion MPT base driver providing common API layer interface | ||
| 3 | * for access to MPT (Message Passing Technology) firmware. | ||
| 4 | * | ||
| 5 | * This code is based on drivers/scsi/mpt2sas/mpt2_base.h | ||
| 6 | * Copyright (C) 2007-2014 LSI Corporation | ||
| 7 | * Copyright (C) 20013-2014 Avago Technologies | ||
| 8 | * (mailto: MPT-FusionLinux.pdl@avagotech.com) | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or | ||
| 11 | * modify it under the terms of the GNU General Public License | ||
| 12 | * as published by the Free Software Foundation; either version 2 | ||
| 13 | * of the License, or (at your option) any later version. | ||
| 14 | * | ||
| 15 | * This program is distributed in the hope that it will be useful, | ||
| 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | * GNU General Public License for more details. | ||
| 19 | * | ||
| 20 | * NO WARRANTY | ||
| 21 | * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR | ||
| 22 | * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT | ||
| 23 | * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, | ||
| 24 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is | ||
| 25 | * solely responsible for determining the appropriateness of using and | ||
| 26 | * distributing the Program and assumes all risks associated with its | ||
| 27 | * exercise of rights under this Agreement, including but not limited to | ||
| 28 | * the risks and costs of program errors, damage to or loss of data, | ||
| 29 | * programs or equipment, and unavailability or interruption of operations. | ||
| 30 | |||
| 31 | * DISCLAIMER OF LIABILITY | ||
| 32 | * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY | ||
| 33 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 34 | * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND | ||
| 35 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR | ||
| 36 | * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | ||
| 37 | * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED | ||
| 38 | * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES | ||
| 39 | |||
| 40 | * You should have received a copy of the GNU General Public License | ||
| 41 | * along with this program; if not, write to the Free Software | ||
| 42 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
| 43 | * USA. | ||
| 44 | */ | ||
| 45 | |||
| 46 | #ifndef MPT2SAS_BASE_H_INCLUDED | ||
| 47 | #define MPT2SAS_BASE_H_INCLUDED | ||
| 48 | |||
| 49 | #include "mpi/mpi2_type.h" | ||
| 50 | #include "mpi/mpi2.h" | ||
| 51 | #include "mpi/mpi2_ioc.h" | ||
| 52 | #include "mpi/mpi2_cnfg.h" | ||
| 53 | #include "mpi/mpi2_init.h" | ||
| 54 | #include "mpi/mpi2_raid.h" | ||
| 55 | #include "mpi/mpi2_tool.h" | ||
| 56 | #include "mpi/mpi2_sas.h" | ||
| 57 | |||
| 58 | #include <scsi/scsi.h> | ||
| 59 | #include <scsi/scsi_cmnd.h> | ||
| 60 | #include <scsi/scsi_device.h> | ||
| 61 | #include <scsi/scsi_host.h> | ||
| 62 | #include <scsi/scsi_tcq.h> | ||
| 63 | #include <scsi/scsi_transport_sas.h> | ||
| 64 | #include <scsi/scsi_dbg.h> | ||
| 65 | #include <scsi/scsi_eh.h> | ||
| 66 | |||
| 67 | #include "mpt2sas_debug.h" | ||
| 68 | |||
| 69 | /* driver versioning info */ | ||
| 70 | #define MPT2SAS_DRIVER_NAME "mpt2sas" | ||
| 71 | #define MPT2SAS_AUTHOR "Avago Technologies <MPT-FusionLinux.pdl@avagotech.com>" | ||
| 72 | #define MPT2SAS_DESCRIPTION "LSI MPT Fusion SAS 2.0 Device Driver" | ||
| 73 | #define MPT2SAS_DRIVER_VERSION "20.100.00.00" | ||
| 74 | #define MPT2SAS_MAJOR_VERSION 20 | ||
| 75 | #define MPT2SAS_MINOR_VERSION 100 | ||
| 76 | #define MPT2SAS_BUILD_VERSION 00 | ||
| 77 | #define MPT2SAS_RELEASE_VERSION 00 | ||
| 78 | |||
| 79 | /* | ||
| 80 | * Set MPT2SAS_SG_DEPTH value based on user input. | ||
| 81 | */ | ||
| 82 | #ifdef CONFIG_SCSI_MPT2SAS_MAX_SGE | ||
| 83 | #if CONFIG_SCSI_MPT2SAS_MAX_SGE < 16 | ||
| 84 | #define MPT2SAS_SG_DEPTH 16 | ||
| 85 | #elif CONFIG_SCSI_MPT2SAS_MAX_SGE > 128 | ||
| 86 | #define MPT2SAS_SG_DEPTH 128 | ||
| 87 | #else | ||
| 88 | #define MPT2SAS_SG_DEPTH CONFIG_SCSI_MPT2SAS_MAX_SGE | ||
| 89 | #endif | ||
| 90 | #else | ||
| 91 | #define MPT2SAS_SG_DEPTH 128 /* MAX_HW_SEGMENTS */ | ||
| 92 | #endif | ||
| 93 | |||
| 94 | |||
| 95 | /* | ||
| 96 | * Generic Defines | ||
| 97 | */ | ||
| 98 | #define MPT2SAS_SATA_QUEUE_DEPTH 32 | ||
| 99 | #define MPT2SAS_SAS_QUEUE_DEPTH 254 | ||
| 100 | #define MPT2SAS_RAID_QUEUE_DEPTH 128 | ||
| 101 | |||
| 102 | #define MPT_NAME_LENGTH 32 /* generic length of strings */ | ||
| 103 | #define MPT_STRING_LENGTH 64 | ||
| 104 | |||
| 105 | #define MPT_MAX_CALLBACKS 16 | ||
| 106 | |||
| 107 | |||
| 108 | #define CAN_SLEEP 1 | ||
| 109 | #define NO_SLEEP 0 | ||
| 110 | |||
| 111 | #define INTERNAL_CMDS_COUNT 10 /* reserved cmds */ | ||
| 112 | |||
| 113 | #define MPI2_HIM_MASK 0xFFFFFFFF /* mask every bit*/ | ||
| 114 | |||
| 115 | #define MPT2SAS_INVALID_DEVICE_HANDLE 0xFFFF | ||
| 116 | |||
| 117 | |||
| 118 | /* | ||
| 119 | * reset phases | ||
| 120 | */ | ||
| 121 | #define MPT2_IOC_PRE_RESET 1 /* prior to host reset */ | ||
| 122 | #define MPT2_IOC_AFTER_RESET 2 /* just after host reset */ | ||
| 123 | #define MPT2_IOC_DONE_RESET 3 /* links re-initialized */ | ||
| 124 | |||
| 125 | /* | ||
| 126 | * logging format | ||
| 127 | */ | ||
| 128 | #define MPT2SAS_FMT "%s: " | ||
| 129 | #define MPT2SAS_INFO_FMT KERN_INFO MPT2SAS_FMT | ||
| 130 | #define MPT2SAS_NOTE_FMT KERN_NOTICE MPT2SAS_FMT | ||
| 131 | #define MPT2SAS_WARN_FMT KERN_WARNING MPT2SAS_FMT | ||
| 132 | #define MPT2SAS_ERR_FMT KERN_ERR MPT2SAS_FMT | ||
| 133 | |||
| 134 | /* | ||
| 135 | * Dell HBA branding | ||
| 136 | */ | ||
| 137 | #define MPT2SAS_DELL_BRANDING_SIZE 32 | ||
| 138 | |||
| 139 | #define MPT2SAS_DELL_6GBPS_SAS_HBA_BRANDING "Dell 6Gbps SAS HBA" | ||
| 140 | #define MPT2SAS_DELL_PERC_H200_ADAPTER_BRANDING "Dell PERC H200 Adapter" | ||
| 141 | #define MPT2SAS_DELL_PERC_H200_INTEGRATED_BRANDING "Dell PERC H200 Integrated" | ||
| 142 | #define MPT2SAS_DELL_PERC_H200_MODULAR_BRANDING "Dell PERC H200 Modular" | ||
| 143 | #define MPT2SAS_DELL_PERC_H200_EMBEDDED_BRANDING "Dell PERC H200 Embedded" | ||
| 144 | #define MPT2SAS_DELL_PERC_H200_BRANDING "Dell PERC H200" | ||
| 145 | #define MPT2SAS_DELL_6GBPS_SAS_BRANDING "Dell 6Gbps SAS" | ||
| 146 | |||
| 147 | /* | ||
| 148 | * Dell HBA SSDIDs | ||
| 149 | */ | ||
| 150 | #define MPT2SAS_DELL_6GBPS_SAS_HBA_SSDID 0x1F1C | ||
| 151 | #define MPT2SAS_DELL_PERC_H200_ADAPTER_SSDID 0x1F1D | ||
| 152 | #define MPT2SAS_DELL_PERC_H200_INTEGRATED_SSDID 0x1F1E | ||
| 153 | #define MPT2SAS_DELL_PERC_H200_MODULAR_SSDID 0x1F1F | ||
| 154 | #define MPT2SAS_DELL_PERC_H200_EMBEDDED_SSDID 0x1F20 | ||
| 155 | #define MPT2SAS_DELL_PERC_H200_SSDID 0x1F21 | ||
| 156 | #define MPT2SAS_DELL_6GBPS_SAS_SSDID 0x1F22 | ||
| 157 | |||
| 158 | /* | ||
| 159 | * Intel HBA branding | ||
| 160 | */ | ||
| 161 | #define MPT2SAS_INTEL_RMS25JB080_BRANDING \ | ||
| 162 | "Intel(R) Integrated RAID Module RMS25JB080" | ||
| 163 | #define MPT2SAS_INTEL_RMS25JB040_BRANDING \ | ||
| 164 | "Intel(R) Integrated RAID Module RMS25JB040" | ||
| 165 | #define MPT2SAS_INTEL_RMS25KB080_BRANDING \ | ||
| 166 | "Intel(R) Integrated RAID Module RMS25KB080" | ||
| 167 | #define MPT2SAS_INTEL_RMS25KB040_BRANDING \ | ||
| 168 | "Intel(R) Integrated RAID Module RMS25KB040" | ||
| 169 | #define MPT2SAS_INTEL_RMS25LB040_BRANDING \ | ||
| 170 | "Intel(R) Integrated RAID Module RMS25LB040" | ||
| 171 | #define MPT2SAS_INTEL_RMS25LB080_BRANDING \ | ||
| 172 | "Intel(R) Integrated RAID Module RMS25LB080" | ||
| 173 | #define MPT2SAS_INTEL_RMS2LL080_BRANDING \ | ||
| 174 | "Intel Integrated RAID Module RMS2LL080" | ||
| 175 | #define MPT2SAS_INTEL_RMS2LL040_BRANDING \ | ||
| 176 | "Intel Integrated RAID Module RMS2LL040" | ||
| 177 | #define MPT2SAS_INTEL_RS25GB008_BRANDING \ | ||
| 178 | "Intel(R) RAID Controller RS25GB008" | ||
| 179 | #define MPT2SAS_INTEL_SSD910_BRANDING \ | ||
| 180 | "Intel(R) SSD 910 Series" | ||
| 181 | /* | ||
| 182 | * Intel HBA SSDIDs | ||
| 183 | */ | ||
| 184 | #define MPT2SAS_INTEL_RMS25JB080_SSDID 0x3516 | ||
| 185 | #define MPT2SAS_INTEL_RMS25JB040_SSDID 0x3517 | ||
| 186 | #define MPT2SAS_INTEL_RMS25KB080_SSDID 0x3518 | ||
| 187 | #define MPT2SAS_INTEL_RMS25KB040_SSDID 0x3519 | ||
| 188 | #define MPT2SAS_INTEL_RMS25LB040_SSDID 0x351A | ||
| 189 | #define MPT2SAS_INTEL_RMS25LB080_SSDID 0x351B | ||
| 190 | #define MPT2SAS_INTEL_RMS2LL080_SSDID 0x350E | ||
| 191 | #define MPT2SAS_INTEL_RMS2LL040_SSDID 0x350F | ||
| 192 | #define MPT2SAS_INTEL_RS25GB008_SSDID 0x3000 | ||
| 193 | #define MPT2SAS_INTEL_SSD910_SSDID 0x3700 | ||
| 194 | |||
| 195 | /* | ||
| 196 | * HP HBA branding | ||
| 197 | */ | ||
| 198 | #define MPT2SAS_HP_3PAR_SSVID 0x1590 | ||
| 199 | #define MPT2SAS_HP_2_4_INTERNAL_BRANDING "HP H220 Host Bus Adapter" | ||
| 200 | #define MPT2SAS_HP_2_4_EXTERNAL_BRANDING "HP H221 Host Bus Adapter" | ||
| 201 | #define MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_BRANDING "HP H222 Host Bus Adapter" | ||
| 202 | #define MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_BRANDING "HP H220i Host Bus Adapter" | ||
| 203 | #define MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_BRANDING "HP H210i Host Bus Adapter" | ||
| 204 | |||
| 205 | /* | ||
| 206 | * HO HBA SSDIDs | ||
| 207 | */ | ||
| 208 | #define MPT2SAS_HP_2_4_INTERNAL_SSDID 0x0041 | ||
| 209 | #define MPT2SAS_HP_2_4_EXTERNAL_SSDID 0x0042 | ||
| 210 | #define MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_SSDID 0x0043 | ||
| 211 | #define MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_SSDID 0x0044 | ||
| 212 | #define MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_SSDID 0x0046 | ||
| 213 | |||
| 214 | /* | ||
| 215 | * WarpDrive Specific Log codes | ||
| 216 | */ | ||
| 217 | |||
| 218 | #define MPT2_WARPDRIVE_LOGENTRY (0x8002) | ||
| 219 | #define MPT2_WARPDRIVE_LC_SSDT (0x41) | ||
| 220 | #define MPT2_WARPDRIVE_LC_SSDLW (0x43) | ||
| 221 | #define MPT2_WARPDRIVE_LC_SSDLF (0x44) | ||
| 222 | #define MPT2_WARPDRIVE_LC_BRMF (0x4D) | ||
| 223 | |||
| 224 | /* | ||
| 225 | * per target private data | ||
| 226 | */ | ||
| 227 | #define MPT_TARGET_FLAGS_RAID_COMPONENT 0x01 | ||
| 228 | #define MPT_TARGET_FLAGS_VOLUME 0x02 | ||
| 229 | #define MPT_TARGET_FLAGS_DELETED 0x04 | ||
| 230 | |||
| 231 | /** | ||
| 232 | * struct MPT2SAS_TARGET - starget private hostdata | ||
| 233 | * @starget: starget object | ||
| 234 | * @sas_address: target sas address | ||
| 235 | * @raid_device: raid_device pointer to access volume data | ||
| 236 | * @handle: device handle | ||
| 237 | * @num_luns: number luns | ||
| 238 | * @flags: MPT_TARGET_FLAGS_XXX flags | ||
| 239 | * @deleted: target flaged for deletion | ||
| 240 | * @tm_busy: target is busy with TM request. | ||
| 241 | * @sdev: The sas_device associated with this target | ||
| 242 | */ | ||
| 243 | struct MPT2SAS_TARGET { | ||
| 244 | struct scsi_target *starget; | ||
| 245 | u64 sas_address; | ||
| 246 | struct _raid_device *raid_device; | ||
| 247 | u16 handle; | ||
| 248 | int num_luns; | ||
| 249 | u32 flags; | ||
| 250 | u8 deleted; | ||
| 251 | u8 tm_busy; | ||
| 252 | struct _sas_device *sdev; | ||
| 253 | }; | ||
| 254 | |||
| 255 | |||
| 256 | /* | ||
| 257 | * per device private data | ||
| 258 | */ | ||
| 259 | #define MPT_DEVICE_FLAGS_INIT 0x01 | ||
| 260 | #define MPT_DEVICE_TLR_ON 0x02 | ||
| 261 | |||
| 262 | /** | ||
| 263 | * struct MPT2SAS_DEVICE - sdev private hostdata | ||
| 264 | * @sas_target: starget private hostdata | ||
| 265 | * @lun: lun number | ||
| 266 | * @flags: MPT_DEVICE_XXX flags | ||
| 267 | * @configured_lun: lun is configured | ||
| 268 | * @block: device is in SDEV_BLOCK state | ||
| 269 | * @tlr_snoop_check: flag used in determining whether to disable TLR | ||
| 270 | */ | ||
| 271 | |||
| 272 | /* OEM Identifiers */ | ||
| 273 | #define MFG10_OEM_ID_INVALID (0x00000000) | ||
| 274 | #define MFG10_OEM_ID_DELL (0x00000001) | ||
| 275 | #define MFG10_OEM_ID_FSC (0x00000002) | ||
| 276 | #define MFG10_OEM_ID_SUN (0x00000003) | ||
| 277 | #define MFG10_OEM_ID_IBM (0x00000004) | ||
| 278 | |||
| 279 | /* GENERIC Flags 0*/ | ||
| 280 | #define MFG10_GF0_OCE_DISABLED (0x00000001) | ||
| 281 | #define MFG10_GF0_R1E_DRIVE_COUNT (0x00000002) | ||
| 282 | #define MFG10_GF0_R10_DISPLAY (0x00000004) | ||
| 283 | #define MFG10_GF0_SSD_DATA_SCRUB_DISABLE (0x00000008) | ||
| 284 | #define MFG10_GF0_SINGLE_DRIVE_R0 (0x00000010) | ||
| 285 | |||
| 286 | /* OEM Specific Flags will come from OEM specific header files */ | ||
| 287 | typedef struct _MPI2_CONFIG_PAGE_MAN_10 { | ||
| 288 | MPI2_CONFIG_PAGE_HEADER Header; /* 00h */ | ||
| 289 | U8 OEMIdentifier; /* 04h */ | ||
| 290 | U8 Reserved1; /* 05h */ | ||
| 291 | U16 Reserved2; /* 08h */ | ||
| 292 | U32 Reserved3; /* 0Ch */ | ||
| 293 | U32 GenericFlags0; /* 10h */ | ||
| 294 | U32 GenericFlags1; /* 14h */ | ||
| 295 | U32 Reserved4; /* 18h */ | ||
| 296 | U32 OEMSpecificFlags0; /* 1Ch */ | ||
| 297 | U32 OEMSpecificFlags1; /* 20h */ | ||
| 298 | U32 Reserved5[18]; /* 24h-60h*/ | ||
| 299 | } MPI2_CONFIG_PAGE_MAN_10, | ||
| 300 | MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_10, | ||
| 301 | Mpi2ManufacturingPage10_t, MPI2_POINTER pMpi2ManufacturingPage10_t; | ||
| 302 | |||
| 303 | #define MFG_PAGE10_HIDE_SSDS_MASK (0x00000003) | ||
| 304 | #define MFG_PAGE10_HIDE_ALL_DISKS (0x00) | ||
| 305 | #define MFG_PAGE10_EXPOSE_ALL_DISKS (0x01) | ||
| 306 | #define MFG_PAGE10_HIDE_IF_VOL_PRESENT (0x02) | ||
| 307 | |||
| 308 | |||
| 309 | struct MPT2SAS_DEVICE { | ||
| 310 | struct MPT2SAS_TARGET *sas_target; | ||
| 311 | unsigned int lun; | ||
| 312 | u32 flags; | ||
| 313 | u8 configured_lun; | ||
| 314 | u8 block; | ||
| 315 | u8 tlr_snoop_check; | ||
| 316 | }; | ||
| 317 | |||
| 318 | #define MPT2_CMD_NOT_USED 0x8000 /* free */ | ||
| 319 | #define MPT2_CMD_COMPLETE 0x0001 /* completed */ | ||
| 320 | #define MPT2_CMD_PENDING 0x0002 /* pending */ | ||
| 321 | #define MPT2_CMD_REPLY_VALID 0x0004 /* reply is valid */ | ||
| 322 | #define MPT2_CMD_RESET 0x0008 /* host reset dropped the command */ | ||
| 323 | |||
| 324 | /** | ||
| 325 | * struct _internal_cmd - internal commands struct | ||
| 326 | * @mutex: mutex | ||
| 327 | * @done: completion | ||
| 328 | * @reply: reply message pointer | ||
| 329 | * @sense: sense data | ||
| 330 | * @status: MPT2_CMD_XXX status | ||
| 331 | * @smid: system message id | ||
| 332 | */ | ||
| 333 | struct _internal_cmd { | ||
| 334 | struct mutex mutex; | ||
| 335 | struct completion done; | ||
| 336 | void *reply; | ||
| 337 | void *sense; | ||
| 338 | u16 status; | ||
| 339 | u16 smid; | ||
| 340 | }; | ||
| 341 | |||
| 342 | |||
| 343 | /** | ||
| 344 | * struct _sas_device - attached device information | ||
| 345 | * @list: sas device list | ||
| 346 | * @starget: starget object | ||
| 347 | * @sas_address: device sas address | ||
| 348 | * @device_name: retrieved from the SAS IDENTIFY frame. | ||
| 349 | * @handle: device handle | ||
| 350 | * @sas_address_parent: sas address of parent expander or sas host | ||
| 351 | * @enclosure_handle: enclosure handle | ||
| 352 | * @enclosure_logical_id: enclosure logical identifier | ||
| 353 | * @volume_handle: volume handle (valid when hidden raid member) | ||
| 354 | * @volume_wwid: volume unique identifier | ||
| 355 | * @device_info: bitfield provides detailed info about the device | ||
| 356 | * @id: target id | ||
| 357 | * @channel: target channel | ||
| 358 | * @slot: number number | ||
| 359 | * @phy: phy identifier provided in sas device page 0 | ||
| 360 | * @responding: used in _scsih_sas_device_mark_responding | ||
| 361 | * @pfa_led_on: flag for PFA LED status | ||
| 362 | */ | ||
| 363 | struct _sas_device { | ||
| 364 | struct list_head list; | ||
| 365 | struct scsi_target *starget; | ||
| 366 | u64 sas_address; | ||
| 367 | u64 device_name; | ||
| 368 | u16 handle; | ||
| 369 | u64 sas_address_parent; | ||
| 370 | u16 enclosure_handle; | ||
| 371 | u64 enclosure_logical_id; | ||
| 372 | u16 volume_handle; | ||
| 373 | u64 volume_wwid; | ||
| 374 | u32 device_info; | ||
| 375 | int id; | ||
| 376 | int channel; | ||
| 377 | u16 slot; | ||
| 378 | u8 phy; | ||
| 379 | u8 responding; | ||
| 380 | u8 pfa_led_on; | ||
| 381 | struct kref refcount; | ||
| 382 | }; | ||
| 383 | |||
| 384 | static inline void sas_device_get(struct _sas_device *s) | ||
| 385 | { | ||
| 386 | kref_get(&s->refcount); | ||
| 387 | } | ||
| 388 | |||
| 389 | static inline void sas_device_free(struct kref *r) | ||
| 390 | { | ||
| 391 | kfree(container_of(r, struct _sas_device, refcount)); | ||
| 392 | } | ||
| 393 | |||
| 394 | static inline void sas_device_put(struct _sas_device *s) | ||
| 395 | { | ||
| 396 | kref_put(&s->refcount, sas_device_free); | ||
| 397 | } | ||
| 398 | |||
| 399 | /** | ||
| 400 | * struct _raid_device - raid volume link list | ||
| 401 | * @list: sas device list | ||
| 402 | * @starget: starget object | ||
| 403 | * @sdev: scsi device struct (volumes are single lun) | ||
| 404 | * @wwid: unique identifier for the volume | ||
| 405 | * @handle: device handle | ||
| 406 | * @block_size: Block size of the volume | ||
| 407 | * @id: target id | ||
| 408 | * @channel: target channel | ||
| 409 | * @volume_type: the raid level | ||
| 410 | * @device_info: bitfield provides detailed info about the hidden components | ||
| 411 | * @num_pds: number of hidden raid components | ||
| 412 | * @responding: used in _scsih_raid_device_mark_responding | ||
| 413 | * @percent_complete: resync percent complete | ||
| 414 | * @direct_io_enabled: Whether direct io to PDs are allowed or not | ||
| 415 | * @stripe_exponent: X where 2powX is the stripe sz in blocks | ||
| 416 | * @block_exponent: X where 2powX is the block sz in bytes | ||
| 417 | * @max_lba: Maximum number of LBA in the volume | ||
| 418 | * @stripe_sz: Stripe Size of the volume | ||
| 419 | * @device_info: Device info of the volume member disk | ||
| 420 | * @pd_handle: Array of handles of the physical drives for direct I/O in le16 | ||
| 421 | */ | ||
| 422 | #define MPT_MAX_WARPDRIVE_PDS 8 | ||
| 423 | struct _raid_device { | ||
| 424 | struct list_head list; | ||
| 425 | struct scsi_target *starget; | ||
| 426 | struct scsi_device *sdev; | ||
| 427 | u64 wwid; | ||
| 428 | u16 handle; | ||
| 429 | u16 block_sz; | ||
| 430 | int id; | ||
| 431 | int channel; | ||
| 432 | u8 volume_type; | ||
| 433 | u8 num_pds; | ||
| 434 | u8 responding; | ||
| 435 | u8 percent_complete; | ||
| 436 | u8 direct_io_enabled; | ||
| 437 | u8 stripe_exponent; | ||
| 438 | u8 block_exponent; | ||
| 439 | u64 max_lba; | ||
| 440 | u32 stripe_sz; | ||
| 441 | u32 device_info; | ||
| 442 | u16 pd_handle[MPT_MAX_WARPDRIVE_PDS]; | ||
| 443 | }; | ||
| 444 | |||
| 445 | /** | ||
| 446 | * struct _boot_device - boot device info | ||
| 447 | * @is_raid: flag to indicate whether this is volume | ||
| 448 | * @device: holds pointer for either struct _sas_device or | ||
| 449 | * struct _raid_device | ||
| 450 | */ | ||
| 451 | struct _boot_device { | ||
| 452 | u8 is_raid; | ||
| 453 | void *device; | ||
| 454 | }; | ||
| 455 | |||
| 456 | /** | ||
| 457 | * struct _sas_port - wide/narrow sas port information | ||
| 458 | * @port_list: list of ports belonging to expander | ||
| 459 | * @num_phys: number of phys belonging to this port | ||
| 460 | * @remote_identify: attached device identification | ||
| 461 | * @rphy: sas transport rphy object | ||
| 462 | * @port: sas transport wide/narrow port object | ||
| 463 | * @phy_list: _sas_phy list objects belonging to this port | ||
| 464 | */ | ||
| 465 | struct _sas_port { | ||
| 466 | struct list_head port_list; | ||
| 467 | u8 num_phys; | ||
| 468 | struct sas_identify remote_identify; | ||
| 469 | struct sas_rphy *rphy; | ||
| 470 | struct sas_port *port; | ||
| 471 | struct list_head phy_list; | ||
| 472 | }; | ||
| 473 | |||
| 474 | /** | ||
| 475 | * struct _sas_phy - phy information | ||
| 476 | * @port_siblings: list of phys belonging to a port | ||
| 477 | * @identify: phy identification | ||
| 478 | * @remote_identify: attached device identification | ||
| 479 | * @phy: sas transport phy object | ||
| 480 | * @phy_id: unique phy id | ||
| 481 | * @handle: device handle for this phy | ||
| 482 | * @attached_handle: device handle for attached device | ||
| 483 | * @phy_belongs_to_port: port has been created for this phy | ||
| 484 | */ | ||
| 485 | struct _sas_phy { | ||
| 486 | struct list_head port_siblings; | ||
| 487 | struct sas_identify identify; | ||
| 488 | struct sas_identify remote_identify; | ||
| 489 | struct sas_phy *phy; | ||
| 490 | u8 phy_id; | ||
| 491 | u16 handle; | ||
| 492 | u16 attached_handle; | ||
| 493 | u8 phy_belongs_to_port; | ||
| 494 | }; | ||
| 495 | |||
| 496 | /** | ||
| 497 | * struct _sas_node - sas_host/expander information | ||
| 498 | * @list: list of expanders | ||
| 499 | * @parent_dev: parent device class | ||
| 500 | * @num_phys: number phys belonging to this sas_host/expander | ||
| 501 | * @sas_address: sas address of this sas_host/expander | ||
| 502 | * @handle: handle for this sas_host/expander | ||
| 503 | * @sas_address_parent: sas address of parent expander or sas host | ||
| 504 | * @enclosure_handle: handle for this a member of an enclosure | ||
| 505 | * @device_info: bitwise defining capabilities of this sas_host/expander | ||
| 506 | * @responding: used in _scsih_expander_device_mark_responding | ||
| 507 | * @phy: a list of phys that make up this sas_host/expander | ||
| 508 | * @sas_port_list: list of ports attached to this sas_host/expander | ||
| 509 | */ | ||
| 510 | struct _sas_node { | ||
| 511 | struct list_head list; | ||
| 512 | struct device *parent_dev; | ||
| 513 | u8 num_phys; | ||
| 514 | u64 sas_address; | ||
| 515 | u16 handle; | ||
| 516 | u64 sas_address_parent; | ||
| 517 | u16 enclosure_handle; | ||
| 518 | u64 enclosure_logical_id; | ||
| 519 | u8 responding; | ||
| 520 | struct _sas_phy *phy; | ||
| 521 | struct list_head sas_port_list; | ||
| 522 | }; | ||
| 523 | |||
| 524 | /** | ||
| 525 | * enum reset_type - reset state | ||
| 526 | * @FORCE_BIG_HAMMER: issue diagnostic reset | ||
| 527 | * @SOFT_RESET: issue message_unit_reset, if fails to to big hammer | ||
| 528 | */ | ||
| 529 | enum reset_type { | ||
| 530 | FORCE_BIG_HAMMER, | ||
| 531 | SOFT_RESET, | ||
| 532 | }; | ||
| 533 | |||
| 534 | /** | ||
| 535 | * struct chain_tracker - firmware chain tracker | ||
| 536 | * @chain_buffer: chain buffer | ||
| 537 | * @chain_buffer_dma: physical address | ||
| 538 | * @tracker_list: list of free request (ioc->free_chain_list) | ||
| 539 | */ | ||
| 540 | struct chain_tracker { | ||
| 541 | void *chain_buffer; | ||
| 542 | dma_addr_t chain_buffer_dma; | ||
| 543 | struct list_head tracker_list; | ||
| 544 | }; | ||
| 545 | |||
| 546 | /** | ||
| 547 | * struct scsiio_tracker - scsi mf request tracker | ||
| 548 | * @smid: system message id | ||
| 549 | * @scmd: scsi request pointer | ||
| 550 | * @cb_idx: callback index | ||
| 551 | * @direct_io: To indicate whether I/O is direct (WARPDRIVE) | ||
| 552 | * @chain_list: list of chains associated to this IO | ||
| 553 | * @tracker_list: list of free request (ioc->free_list) | ||
| 554 | */ | ||
| 555 | struct scsiio_tracker { | ||
| 556 | u16 smid; | ||
| 557 | struct scsi_cmnd *scmd; | ||
| 558 | u8 cb_idx; | ||
| 559 | u8 direct_io; | ||
| 560 | struct list_head chain_list; | ||
| 561 | struct list_head tracker_list; | ||
| 562 | }; | ||
| 563 | |||
| 564 | /** | ||
| 565 | * struct request_tracker - firmware request tracker | ||
| 566 | * @smid: system message id | ||
| 567 | * @cb_idx: callback index | ||
| 568 | * @tracker_list: list of free request (ioc->free_list) | ||
| 569 | */ | ||
| 570 | struct request_tracker { | ||
| 571 | u16 smid; | ||
| 572 | u8 cb_idx; | ||
| 573 | struct list_head tracker_list; | ||
| 574 | }; | ||
| 575 | |||
| 576 | /** | ||
| 577 | * struct _tr_list - target reset list | ||
| 578 | * @handle: device handle | ||
| 579 | * @state: state machine | ||
| 580 | */ | ||
| 581 | struct _tr_list { | ||
| 582 | struct list_head list; | ||
| 583 | u16 handle; | ||
| 584 | u16 state; | ||
| 585 | }; | ||
| 586 | |||
| 587 | typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr); | ||
| 588 | |||
| 589 | /** | ||
| 590 | * struct adapter_reply_queue - the reply queue struct | ||
| 591 | * @ioc: per adapter object | ||
| 592 | * @msix_index: msix index into vector table | ||
| 593 | * @vector: irq vector | ||
| 594 | * @reply_post_host_index: head index in the pool where FW completes IO | ||
| 595 | * @reply_post_free: reply post base virt address | ||
| 596 | * @name: the name registered to request_irq() | ||
| 597 | * @busy: isr is actively processing replies on another cpu | ||
| 598 | * @list: this list | ||
| 599 | */ | ||
| 600 | struct adapter_reply_queue { | ||
| 601 | struct MPT2SAS_ADAPTER *ioc; | ||
| 602 | u8 msix_index; | ||
| 603 | unsigned int vector; | ||
| 604 | u32 reply_post_host_index; | ||
| 605 | Mpi2ReplyDescriptorsUnion_t *reply_post_free; | ||
| 606 | char name[MPT_NAME_LENGTH]; | ||
| 607 | atomic_t busy; | ||
| 608 | cpumask_var_t affinity_hint; | ||
| 609 | struct list_head list; | ||
| 610 | }; | ||
| 611 | |||
| 612 | /* IOC Facts and Port Facts converted from little endian to cpu */ | ||
| 613 | union mpi2_version_union { | ||
| 614 | MPI2_VERSION_STRUCT Struct; | ||
| 615 | u32 Word; | ||
| 616 | }; | ||
| 617 | |||
| 618 | struct mpt2sas_facts { | ||
| 619 | u16 MsgVersion; | ||
| 620 | u16 HeaderVersion; | ||
| 621 | u8 IOCNumber; | ||
| 622 | u8 VP_ID; | ||
| 623 | u8 VF_ID; | ||
| 624 | u16 IOCExceptions; | ||
| 625 | u16 IOCStatus; | ||
| 626 | u32 IOCLogInfo; | ||
| 627 | u8 MaxChainDepth; | ||
| 628 | u8 WhoInit; | ||
| 629 | u8 NumberOfPorts; | ||
| 630 | u8 MaxMSIxVectors; | ||
| 631 | u16 RequestCredit; | ||
| 632 | u16 ProductID; | ||
| 633 | u32 IOCCapabilities; | ||
| 634 | union mpi2_version_union FWVersion; | ||
| 635 | u16 IOCRequestFrameSize; | ||
| 636 | u16 Reserved3; | ||
| 637 | u16 MaxInitiators; | ||
| 638 | u16 MaxTargets; | ||
| 639 | u16 MaxSasExpanders; | ||
| 640 | u16 MaxEnclosures; | ||
| 641 | u16 ProtocolFlags; | ||
| 642 | u16 HighPriorityCredit; | ||
| 643 | u16 MaxReplyDescriptorPostQueueDepth; | ||
| 644 | u8 ReplyFrameSize; | ||
| 645 | u8 MaxVolumes; | ||
| 646 | u16 MaxDevHandle; | ||
| 647 | u16 MaxPersistentEntries; | ||
| 648 | u16 MinDevHandle; | ||
| 649 | }; | ||
| 650 | |||
| 651 | struct mpt2sas_port_facts { | ||
| 652 | u8 PortNumber; | ||
| 653 | u8 VP_ID; | ||
| 654 | u8 VF_ID; | ||
| 655 | u8 PortType; | ||
| 656 | u16 MaxPostedCmdBuffers; | ||
| 657 | }; | ||
| 658 | |||
| 659 | struct reply_post_struct { | ||
| 660 | Mpi2ReplyDescriptorsUnion_t *reply_post_free; | ||
| 661 | dma_addr_t reply_post_free_dma; | ||
| 662 | }; | ||
| 663 | |||
| 664 | /** | ||
| 665 | * enum mutex_type - task management mutex type | ||
| 666 | * @TM_MUTEX_OFF: mutex is not required becuase calling function is acquiring it | ||
| 667 | * @TM_MUTEX_ON: mutex is required | ||
| 668 | */ | ||
| 669 | enum mutex_type { | ||
| 670 | TM_MUTEX_OFF = 0, | ||
| 671 | TM_MUTEX_ON = 1, | ||
| 672 | }; | ||
| 673 | |||
| 674 | typedef void (*MPT2SAS_FLUSH_RUNNING_CMDS)(struct MPT2SAS_ADAPTER *ioc); | ||
| 675 | /** | ||
| 676 | * struct MPT2SAS_ADAPTER - per adapter struct | ||
| 677 | * @list: ioc_list | ||
| 678 | * @shost: shost object | ||
| 679 | * @id: unique adapter id | ||
| 680 | * @cpu_count: number online cpus | ||
| 681 | * @name: generic ioc string | ||
| 682 | * @tmp_string: tmp string used for logging | ||
| 683 | * @pdev: pci pdev object | ||
| 684 | * @chip: memory mapped register space | ||
| 685 | * @chip_phys: physical addrss prior to mapping | ||
| 686 | * @logging_level: see mpt2sas_debug.h | ||
| 687 | * @fwfault_debug: debuging FW timeouts | ||
| 688 | * @ir_firmware: IR firmware present | ||
| 689 | * @bars: bitmask of BAR's that must be configured | ||
| 690 | * @mask_interrupts: ignore interrupt | ||
| 691 | * @dma_mask: used to set the consistent dma mask | ||
| 692 | * @fault_reset_work_q_name: fw fault work queue | ||
| 693 | * @fault_reset_work_q: "" | ||
| 694 | * @fault_reset_work: "" | ||
| 695 | * @firmware_event_name: fw event work queue | ||
| 696 | * @firmware_event_thread: "" | ||
| 697 | * @fw_events_off: flag to turn off fw event handling | ||
| 698 | * @fw_event_lock: | ||
| 699 | * @fw_event_list: list of fw events | ||
| 700 | * @aen_event_read_flag: event log was read | ||
| 701 | * @broadcast_aen_busy: broadcast aen waiting to be serviced | ||
| 702 | * @shost_recovery: host reset in progress | ||
| 703 | * @ioc_reset_in_progress_lock: | ||
| 704 | * @ioc_link_reset_in_progress: phy/hard reset in progress | ||
| 705 | * @ignore_loginfos: ignore loginfos during task management | ||
| 706 | * @remove_host: flag for when driver unloads, to avoid sending dev resets | ||
| 707 | * @pci_error_recovery: flag to prevent ioc access until slot reset completes | ||
| 708 | * @wait_for_discovery_to_complete: flag set at driver load time when | ||
| 709 | * waiting on reporting devices | ||
| 710 | * @is_driver_loading: flag set at driver load time | ||
| 711 | * @port_enable_failed: flag set when port enable has failed | ||
| 712 | * @start_scan: flag set from scan_start callback, cleared from _mpt2sas_fw_work | ||
| 713 | * @start_scan_failed: means port enable failed, return's the ioc_status | ||
| 714 | * @msix_enable: flag indicating msix is enabled | ||
| 715 | * @msix_vector_count: number msix vectors | ||
| 716 | * @cpu_msix_table: table for mapping cpus to msix index | ||
| 717 | * @cpu_msix_table_sz: table size | ||
| 718 | * @schedule_dead_ioc_flush_running_cmds: callback to flush pending commands | ||
| 719 | * @scsi_io_cb_idx: shost generated commands | ||
| 720 | * @tm_cb_idx: task management commands | ||
| 721 | * @scsih_cb_idx: scsih internal commands | ||
| 722 | * @transport_cb_idx: transport internal commands | ||
| 723 | * @ctl_cb_idx: clt internal commands | ||
| 724 | * @base_cb_idx: base internal commands | ||
| 725 | * @config_cb_idx: base internal commands | ||
| 726 | * @tm_tr_cb_idx : device removal target reset handshake | ||
| 727 | * @tm_tr_volume_cb_idx : volume removal target reset | ||
| 728 | * @base_cmds: | ||
| 729 | * @transport_cmds: | ||
| 730 | * @scsih_cmds: | ||
| 731 | * @tm_cmds: | ||
| 732 | * @ctl_cmds: | ||
| 733 | * @config_cmds: | ||
| 734 | * @base_add_sg_single: handler for either 32/64 bit sgl's | ||
| 735 | * @event_type: bits indicating which events to log | ||
| 736 | * @event_context: unique id for each logged event | ||
| 737 | * @event_log: event log pointer | ||
| 738 | * @event_masks: events that are masked | ||
| 739 | * @facts: static facts data | ||
| 740 | * @pfacts: static port facts data | ||
| 741 | * @manu_pg0: static manufacturing page 0 | ||
| 742 | * @manu_pg10: static manufacturing page 10 | ||
| 743 | * @bios_pg2: static bios page 2 | ||
| 744 | * @bios_pg3: static bios page 3 | ||
| 745 | * @ioc_pg8: static ioc page 8 | ||
| 746 | * @iounit_pg0: static iounit page 0 | ||
| 747 | * @iounit_pg1: static iounit page 1 | ||
| 748 | * @iounit_pg8: static iounit page 8 | ||
| 749 | * @sas_hba: sas host object | ||
| 750 | * @sas_expander_list: expander object list | ||
| 751 | * @sas_node_lock: | ||
| 752 | * @sas_device_list: sas device object list | ||
| 753 | * @sas_device_init_list: sas device object list (used only at init time) | ||
| 754 | * @sas_device_lock: | ||
| 755 | * @io_missing_delay: time for IO completed by fw when PDR enabled | ||
| 756 | * @device_missing_delay: time for device missing by fw when PDR enabled | ||
| 757 | * @sas_id : used for setting volume target IDs | ||
| 758 | * @blocking_handles: bitmask used to identify which devices need blocking | ||
| 759 | * @pd_handles : bitmask for PD handles | ||
| 760 | * @pd_handles_sz : size of pd_handle bitmask | ||
| 761 | * @config_page_sz: config page size | ||
| 762 | * @config_page: reserve memory for config page payload | ||
| 763 | * @config_page_dma: | ||
| 764 | * @hba_queue_depth: hba request queue depth | ||
| 765 | * @sge_size: sg element size for either 32/64 bit | ||
| 766 | * @scsiio_depth: SCSI_IO queue depth | ||
| 767 | * @request_sz: per request frame size | ||
| 768 | * @request: pool of request frames | ||
| 769 | * @request_dma: | ||
| 770 | * @request_dma_sz: | ||
| 771 | * @scsi_lookup: firmware request tracker list | ||
| 772 | * @scsi_lookup_lock: | ||
| 773 | * @free_list: free list of request | ||
| 774 | * @chain: pool of chains | ||
| 775 | * @pending_io_count: | ||
| 776 | * @reset_wq: | ||
| 777 | * @chain_dma: | ||
| 778 | * @max_sges_in_main_message: number sg elements in main message | ||
| 779 | * @max_sges_in_chain_message: number sg elements per chain | ||
| 780 | * @chains_needed_per_io: max chains per io | ||
| 781 | * @chain_offset_value_for_main_message: location 1st sg in main | ||
| 782 | * @chain_depth: total chains allocated | ||
| 783 | * @hi_priority_smid: | ||
| 784 | * @hi_priority: | ||
| 785 | * @hi_priority_dma: | ||
| 786 | * @hi_priority_depth: | ||
| 787 | * @hpr_lookup: | ||
| 788 | * @hpr_free_list: | ||
| 789 | * @internal_smid: | ||
| 790 | * @internal: | ||
| 791 | * @internal_dma: | ||
| 792 | * @internal_depth: | ||
| 793 | * @internal_lookup: | ||
| 794 | * @internal_free_list: | ||
| 795 | * @sense: pool of sense | ||
| 796 | * @sense_dma: | ||
| 797 | * @sense_dma_pool: | ||
| 798 | * @reply_depth: hba reply queue depth: | ||
| 799 | * @reply_sz: per reply frame size: | ||
| 800 | * @reply: pool of replys: | ||
| 801 | * @reply_dma: | ||
| 802 | * @reply_dma_pool: | ||
| 803 | * @reply_free_queue_depth: reply free depth | ||
| 804 | * @reply_free: pool for reply free queue (32 bit addr) | ||
| 805 | * @reply_free_dma: | ||
| 806 | * @reply_free_dma_pool: | ||
| 807 | * @reply_free_host_index: tail index in pool to insert free replys | ||
| 808 | * @reply_post_queue_depth: reply post queue depth | ||
| 809 | * @reply_post_struct: struct for reply_post_free physical & virt address | ||
| 810 | * @rdpq_array_capable: FW supports multiple reply queue addresses in ioc_init | ||
| 811 | * @rdpq_array_enable: rdpq_array support is enabled in the driver | ||
| 812 | * @rdpq_array_enable_assigned: this ensures that rdpq_array_enable flag | ||
| 813 | * is assigned only ones | ||
| 814 | * @reply_queue_count: number of reply queue's | ||
| 815 | * @reply_queue_list: link list contaning the reply queue info | ||
| 816 | * @reply_post_host_index: head index in the pool where FW completes IO | ||
| 817 | * @delayed_tr_list: target reset link list | ||
| 818 | * @delayed_tr_volume_list: volume target reset link list | ||
| 819 | * @@temp_sensors_count: flag to carry the number of temperature sensors | ||
| 820 | * @pci_access_mutex: Mutex to synchronize ioctl,sysfs show path and | ||
| 821 | * pci resource handling. PCI resource freeing will lead to free | ||
| 822 | * vital hardware/memory resource, which might be in use by cli/sysfs | ||
| 823 | * path functions resulting in Null pointer reference followed by kernel | ||
| 824 | * crash. To avoid the above race condition we use mutex syncrhonization | ||
| 825 | * which ensures the syncrhonization between cli/sysfs_show path | ||
| 826 | */ | ||
| 827 | struct MPT2SAS_ADAPTER { | ||
| 828 | struct list_head list; | ||
| 829 | struct Scsi_Host *shost; | ||
| 830 | u8 id; | ||
| 831 | int cpu_count; | ||
| 832 | char name[MPT_NAME_LENGTH]; | ||
| 833 | char tmp_string[MPT_STRING_LENGTH]; | ||
| 834 | struct pci_dev *pdev; | ||
| 835 | Mpi2SystemInterfaceRegs_t __iomem *chip; | ||
| 836 | resource_size_t chip_phys; | ||
| 837 | int logging_level; | ||
| 838 | int fwfault_debug; | ||
| 839 | u8 ir_firmware; | ||
| 840 | int bars; | ||
| 841 | u8 mask_interrupts; | ||
| 842 | int dma_mask; | ||
| 843 | |||
| 844 | /* fw fault handler */ | ||
| 845 | char fault_reset_work_q_name[20]; | ||
| 846 | struct workqueue_struct *fault_reset_work_q; | ||
| 847 | struct delayed_work fault_reset_work; | ||
| 848 | |||
| 849 | /* fw event handler */ | ||
| 850 | char firmware_event_name[20]; | ||
| 851 | struct workqueue_struct *firmware_event_thread; | ||
| 852 | spinlock_t fw_event_lock; | ||
| 853 | struct list_head fw_event_list; | ||
| 854 | |||
| 855 | /* misc flags */ | ||
| 856 | int aen_event_read_flag; | ||
| 857 | u8 broadcast_aen_busy; | ||
| 858 | u16 broadcast_aen_pending; | ||
| 859 | u8 shost_recovery; | ||
| 860 | |||
| 861 | struct mutex reset_in_progress_mutex; | ||
| 862 | spinlock_t ioc_reset_in_progress_lock; | ||
| 863 | u8 ioc_link_reset_in_progress; | ||
| 864 | u8 ioc_reset_in_progress_status; | ||
| 865 | |||
| 866 | u8 ignore_loginfos; | ||
| 867 | u8 remove_host; | ||
| 868 | u8 pci_error_recovery; | ||
| 869 | u8 wait_for_discovery_to_complete; | ||
| 870 | struct completion port_enable_done; | ||
| 871 | u8 is_driver_loading; | ||
| 872 | u8 port_enable_failed; | ||
| 873 | |||
| 874 | u8 start_scan; | ||
| 875 | u16 start_scan_failed; | ||
| 876 | |||
| 877 | u8 msix_enable; | ||
| 878 | u16 msix_vector_count; | ||
| 879 | u8 *cpu_msix_table; | ||
| 880 | resource_size_t __iomem **reply_post_host_index; | ||
| 881 | u16 cpu_msix_table_sz; | ||
| 882 | u32 ioc_reset_count; | ||
| 883 | MPT2SAS_FLUSH_RUNNING_CMDS schedule_dead_ioc_flush_running_cmds; | ||
| 884 | u32 non_operational_loop; | ||
| 885 | |||
| 886 | /* internal commands, callback index */ | ||
| 887 | u8 scsi_io_cb_idx; | ||
| 888 | u8 tm_cb_idx; | ||
| 889 | u8 transport_cb_idx; | ||
| 890 | u8 scsih_cb_idx; | ||
| 891 | u8 ctl_cb_idx; | ||
| 892 | u8 base_cb_idx; | ||
| 893 | u8 port_enable_cb_idx; | ||
| 894 | u8 config_cb_idx; | ||
| 895 | u8 tm_tr_cb_idx; | ||
| 896 | u8 tm_tr_volume_cb_idx; | ||
| 897 | u8 tm_sas_control_cb_idx; | ||
| 898 | struct _internal_cmd base_cmds; | ||
| 899 | struct _internal_cmd port_enable_cmds; | ||
| 900 | struct _internal_cmd transport_cmds; | ||
| 901 | struct _internal_cmd scsih_cmds; | ||
| 902 | struct _internal_cmd tm_cmds; | ||
| 903 | struct _internal_cmd ctl_cmds; | ||
| 904 | struct _internal_cmd config_cmds; | ||
| 905 | |||
| 906 | MPT_ADD_SGE base_add_sg_single; | ||
| 907 | |||
| 908 | /* event log */ | ||
| 909 | u32 event_type[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS]; | ||
| 910 | u32 event_context; | ||
| 911 | void *event_log; | ||
| 912 | u32 event_masks[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS]; | ||
| 913 | |||
| 914 | /* static config pages */ | ||
| 915 | struct mpt2sas_facts facts; | ||
| 916 | struct mpt2sas_port_facts *pfacts; | ||
| 917 | Mpi2ManufacturingPage0_t manu_pg0; | ||
| 918 | Mpi2BiosPage2_t bios_pg2; | ||
| 919 | Mpi2BiosPage3_t bios_pg3; | ||
| 920 | Mpi2IOCPage8_t ioc_pg8; | ||
| 921 | Mpi2IOUnitPage0_t iounit_pg0; | ||
| 922 | Mpi2IOUnitPage1_t iounit_pg1; | ||
| 923 | Mpi2IOUnitPage8_t iounit_pg8; | ||
| 924 | |||
| 925 | struct _boot_device req_boot_device; | ||
| 926 | struct _boot_device req_alt_boot_device; | ||
| 927 | struct _boot_device current_boot_device; | ||
| 928 | |||
| 929 | /* sas hba, expander, and device list */ | ||
| 930 | struct _sas_node sas_hba; | ||
| 931 | struct list_head sas_expander_list; | ||
| 932 | spinlock_t sas_node_lock; | ||
| 933 | struct list_head sas_device_list; | ||
| 934 | struct list_head sas_device_init_list; | ||
| 935 | spinlock_t sas_device_lock; | ||
| 936 | struct list_head raid_device_list; | ||
| 937 | spinlock_t raid_device_lock; | ||
| 938 | u8 io_missing_delay; | ||
| 939 | u16 device_missing_delay; | ||
| 940 | int sas_id; | ||
| 941 | void *blocking_handles; | ||
| 942 | void *pd_handles; | ||
| 943 | u16 pd_handles_sz; | ||
| 944 | |||
| 945 | /* config page */ | ||
| 946 | u16 config_page_sz; | ||
| 947 | void *config_page; | ||
| 948 | dma_addr_t config_page_dma; | ||
| 949 | |||
| 950 | /* scsiio request */ | ||
| 951 | u16 hba_queue_depth; | ||
| 952 | u16 sge_size; | ||
| 953 | u16 scsiio_depth; | ||
| 954 | u16 request_sz; | ||
| 955 | u8 *request; | ||
| 956 | dma_addr_t request_dma; | ||
| 957 | u32 request_dma_sz; | ||
| 958 | struct scsiio_tracker *scsi_lookup; | ||
| 959 | ulong scsi_lookup_pages; | ||
| 960 | spinlock_t scsi_lookup_lock; | ||
| 961 | struct list_head free_list; | ||
| 962 | int pending_io_count; | ||
| 963 | wait_queue_head_t reset_wq; | ||
| 964 | |||
| 965 | /* chain */ | ||
| 966 | struct chain_tracker *chain_lookup; | ||
| 967 | struct list_head free_chain_list; | ||
| 968 | struct dma_pool *chain_dma_pool; | ||
| 969 | ulong chain_pages; | ||
| 970 | u16 max_sges_in_main_message; | ||
| 971 | u16 max_sges_in_chain_message; | ||
| 972 | u16 chains_needed_per_io; | ||
| 973 | u16 chain_offset_value_for_main_message; | ||
| 974 | u32 chain_depth; | ||
| 975 | |||
| 976 | /* hi-priority queue */ | ||
| 977 | u16 hi_priority_smid; | ||
| 978 | u8 *hi_priority; | ||
| 979 | dma_addr_t hi_priority_dma; | ||
| 980 | u16 hi_priority_depth; | ||
| 981 | struct request_tracker *hpr_lookup; | ||
| 982 | struct list_head hpr_free_list; | ||
| 983 | |||
| 984 | /* internal queue */ | ||
| 985 | u16 internal_smid; | ||
| 986 | u8 *internal; | ||
| 987 | dma_addr_t internal_dma; | ||
| 988 | u16 internal_depth; | ||
| 989 | struct request_tracker *internal_lookup; | ||
| 990 | struct list_head internal_free_list; | ||
| 991 | |||
| 992 | /* sense */ | ||
| 993 | u8 *sense; | ||
| 994 | dma_addr_t sense_dma; | ||
| 995 | struct dma_pool *sense_dma_pool; | ||
| 996 | |||
| 997 | /* reply */ | ||
| 998 | u16 reply_sz; | ||
| 999 | u8 *reply; | ||
| 1000 | dma_addr_t reply_dma; | ||
| 1001 | u32 reply_dma_max_address; | ||
| 1002 | u32 reply_dma_min_address; | ||
| 1003 | struct dma_pool *reply_dma_pool; | ||
| 1004 | |||
| 1005 | /* reply free queue */ | ||
| 1006 | u16 reply_free_queue_depth; | ||
| 1007 | __le32 *reply_free; | ||
| 1008 | dma_addr_t reply_free_dma; | ||
| 1009 | struct dma_pool *reply_free_dma_pool; | ||
| 1010 | u32 reply_free_host_index; | ||
| 1011 | |||
| 1012 | /* reply post queue */ | ||
| 1013 | u16 reply_post_queue_depth; | ||
| 1014 | struct reply_post_struct *reply_post; | ||
| 1015 | u8 rdpq_array_capable; | ||
| 1016 | u8 rdpq_array_enable; | ||
| 1017 | u8 rdpq_array_enable_assigned; | ||
| 1018 | struct dma_pool *reply_post_free_dma_pool; | ||
| 1019 | u8 reply_queue_count; | ||
| 1020 | struct list_head reply_queue_list; | ||
| 1021 | |||
| 1022 | struct list_head delayed_tr_list; | ||
| 1023 | struct list_head delayed_tr_volume_list; | ||
| 1024 | u8 temp_sensors_count; | ||
| 1025 | |||
| 1026 | /* diag buffer support */ | ||
| 1027 | u8 *diag_buffer[MPI2_DIAG_BUF_TYPE_COUNT]; | ||
| 1028 | u32 diag_buffer_sz[MPI2_DIAG_BUF_TYPE_COUNT]; | ||
| 1029 | dma_addr_t diag_buffer_dma[MPI2_DIAG_BUF_TYPE_COUNT]; | ||
| 1030 | u8 diag_buffer_status[MPI2_DIAG_BUF_TYPE_COUNT]; | ||
| 1031 | u32 unique_id[MPI2_DIAG_BUF_TYPE_COUNT]; | ||
| 1032 | Mpi2ManufacturingPage10_t manu_pg10; | ||
| 1033 | u32 product_specific[MPI2_DIAG_BUF_TYPE_COUNT][23]; | ||
| 1034 | u32 diagnostic_flags[MPI2_DIAG_BUF_TYPE_COUNT]; | ||
| 1035 | u32 ring_buffer_offset; | ||
| 1036 | u32 ring_buffer_sz; | ||
| 1037 | u8 is_warpdrive; | ||
| 1038 | u8 hide_ir_msg; | ||
| 1039 | u8 mfg_pg10_hide_flag; | ||
| 1040 | u8 hide_drives; | ||
| 1041 | |||
| 1042 | struct mutex pci_access_mutex; | ||
| 1043 | }; | ||
| 1044 | |||
| 1045 | typedef u8 (*MPT_CALLBACK)(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | ||
| 1046 | u32 reply); | ||
| 1047 | |||
| 1048 | |||
| 1049 | /* base shared API */ | ||
| 1050 | extern struct list_head mpt2sas_ioc_list; | ||
| 1051 | /* spinlock on list operations over IOCs | ||
| 1052 | * Case: when multiple warpdrive cards(IOCs) are in use | ||
| 1053 | * Each IOC will added to the ioc list stucture on initialization. | ||
| 1054 | * Watchdog threads run at regular intervals to check IOC for any | ||
| 1055 | * fault conditions which will trigger the dead_ioc thread to | ||
| 1056 | * deallocate pci resource, resulting deleting the IOC netry from list, | ||
| 1057 | * this deletion need to protected by spinlock to enusre that | ||
| 1058 | * ioc removal is syncrhonized, if not synchronized it might lead to | ||
| 1059 | * list_del corruption as the ioc list is traversed in cli path | ||
| 1060 | */ | ||
| 1061 | extern spinlock_t gioc_lock; | ||
| 1062 | void mpt2sas_base_start_watchdog(struct MPT2SAS_ADAPTER *ioc); | ||
| 1063 | void mpt2sas_base_stop_watchdog(struct MPT2SAS_ADAPTER *ioc); | ||
| 1064 | |||
| 1065 | int mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc); | ||
| 1066 | void mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc); | ||
| 1067 | int mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc); | ||
| 1068 | void mpt2sas_base_free_resources(struct MPT2SAS_ADAPTER *ioc); | ||
| 1069 | int mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, | ||
| 1070 | enum reset_type type); | ||
| 1071 | |||
| 1072 | void *mpt2sas_base_get_msg_frame(struct MPT2SAS_ADAPTER *ioc, u16 smid); | ||
| 1073 | void *mpt2sas_base_get_sense_buffer(struct MPT2SAS_ADAPTER *ioc, u16 smid); | ||
| 1074 | void mpt2sas_base_build_zero_len_sge(struct MPT2SAS_ADAPTER *ioc, void *paddr); | ||
| 1075 | __le32 mpt2sas_base_get_sense_buffer_dma(struct MPT2SAS_ADAPTER *ioc, | ||
| 1076 | u16 smid); | ||
| 1077 | void mpt2sas_base_flush_reply_queues(struct MPT2SAS_ADAPTER *ioc); | ||
| 1078 | |||
| 1079 | /* hi-priority queue */ | ||
| 1080 | u16 mpt2sas_base_get_smid_hpr(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx); | ||
| 1081 | u16 mpt2sas_base_get_smid_scsiio(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx, | ||
| 1082 | struct scsi_cmnd *scmd); | ||
| 1083 | |||
| 1084 | u16 mpt2sas_base_get_smid(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx); | ||
| 1085 | void mpt2sas_base_free_smid(struct MPT2SAS_ADAPTER *ioc, u16 smid); | ||
| 1086 | void mpt2sas_base_put_smid_scsi_io(struct MPT2SAS_ADAPTER *ioc, u16 smid, | ||
| 1087 | u16 handle); | ||
| 1088 | void mpt2sas_base_put_smid_hi_priority(struct MPT2SAS_ADAPTER *ioc, u16 smid); | ||
| 1089 | void mpt2sas_base_put_smid_target_assist(struct MPT2SAS_ADAPTER *ioc, u16 smid, | ||
| 1090 | u16 io_index); | ||
| 1091 | void mpt2sas_base_put_smid_default(struct MPT2SAS_ADAPTER *ioc, u16 smid); | ||
| 1092 | void mpt2sas_base_initialize_callback_handler(void); | ||
| 1093 | u8 mpt2sas_base_register_callback_handler(MPT_CALLBACK cb_func); | ||
| 1094 | void mpt2sas_base_release_callback_handler(u8 cb_idx); | ||
| 1095 | |||
| 1096 | u8 mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | ||
| 1097 | u32 reply); | ||
| 1098 | u8 mpt2sas_port_enable_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, | ||
| 1099 | u8 msix_index, u32 reply); | ||
| 1100 | void *mpt2sas_base_get_reply_virt_addr(struct MPT2SAS_ADAPTER *ioc, u32 phys_addr); | ||
| 1101 | |||
| 1102 | u32 mpt2sas_base_get_iocstate(struct MPT2SAS_ADAPTER *ioc, int cooked); | ||
| 1103 | |||
| 1104 | void mpt2sas_base_fault_info(struct MPT2SAS_ADAPTER *ioc , u16 fault_code); | ||
| 1105 | int mpt2sas_base_sas_iounit_control(struct MPT2SAS_ADAPTER *ioc, | ||
| 1106 | Mpi2SasIoUnitControlReply_t *mpi_reply, Mpi2SasIoUnitControlRequest_t | ||
| 1107 | *mpi_request); | ||
| 1108 | int mpt2sas_base_scsi_enclosure_processor(struct MPT2SAS_ADAPTER *ioc, | ||
| 1109 | Mpi2SepReply_t *mpi_reply, Mpi2SepRequest_t *mpi_request); | ||
| 1110 | void mpt2sas_base_validate_event_type(struct MPT2SAS_ADAPTER *ioc, u32 *event_type); | ||
| 1111 | |||
| 1112 | void mpt2sas_halt_firmware(struct MPT2SAS_ADAPTER *ioc); | ||
| 1113 | |||
| 1114 | void mpt2sas_base_update_missing_delay(struct MPT2SAS_ADAPTER *ioc, | ||
| 1115 | u16 device_missing_delay, u8 io_missing_delay); | ||
| 1116 | |||
| 1117 | int mpt2sas_port_enable(struct MPT2SAS_ADAPTER *ioc); | ||
| 1118 | |||
| 1119 | /* scsih shared API */ | ||
| 1120 | void mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, | ||
| 1121 | u32 reply); | ||
| 1122 | int mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, | ||
| 1123 | uint channel, uint id, uint lun, u8 type, u16 smid_task, | ||
| 1124 | ulong timeout, enum mutex_type m_type); | ||
| 1125 | void mpt2sas_scsih_set_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle); | ||
| 1126 | void mpt2sas_scsih_clear_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle); | ||
| 1127 | void mpt2sas_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address); | ||
| 1128 | void mpt2sas_device_remove_by_sas_address(struct MPT2SAS_ADAPTER *ioc, | ||
| 1129 | u64 sas_address); | ||
| 1130 | struct _sas_node *mpt2sas_scsih_expander_find_by_handle(struct MPT2SAS_ADAPTER *ioc, | ||
| 1131 | u16 handle); | ||
| 1132 | struct _sas_node *mpt2sas_scsih_expander_find_by_sas_address(struct MPT2SAS_ADAPTER | ||
| 1133 | *ioc, u64 sas_address); | ||
| 1134 | struct _sas_device *mpt2sas_get_sdev_by_addr( | ||
| 1135 | struct MPT2SAS_ADAPTER *ioc, u64 sas_address); | ||
| 1136 | struct _sas_device *__mpt2sas_get_sdev_by_addr( | ||
| 1137 | struct MPT2SAS_ADAPTER *ioc, u64 sas_address); | ||
| 1138 | |||
| 1139 | void mpt2sas_port_enable_complete(struct MPT2SAS_ADAPTER *ioc); | ||
| 1140 | void mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase); | ||
| 1141 | |||
| 1142 | /* config shared API */ | ||
| 1143 | u8 mpt2sas_config_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | ||
| 1144 | u32 reply); | ||
| 1145 | int mpt2sas_config_get_number_hba_phys(struct MPT2SAS_ADAPTER *ioc, u8 *num_phys); | ||
| 1146 | int mpt2sas_config_get_manufacturing_pg0(struct MPT2SAS_ADAPTER *ioc, | ||
| 1147 | Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page); | ||
| 1148 | int mpt2sas_config_get_manufacturing_pg10(struct MPT2SAS_ADAPTER *ioc, | ||
| 1149 | Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage10_t *config_page); | ||
| 1150 | int mpt2sas_config_get_bios_pg2(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
| 1151 | *mpi_reply, Mpi2BiosPage2_t *config_page); | ||
| 1152 | int mpt2sas_config_get_bios_pg3(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
| 1153 | *mpi_reply, Mpi2BiosPage3_t *config_page); | ||
| 1154 | int mpt2sas_config_get_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
| 1155 | *mpi_reply, Mpi2IOUnitPage0_t *config_page); | ||
| 1156 | int mpt2sas_config_get_sas_device_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
| 1157 | *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u32 handle); | ||
| 1158 | int mpt2sas_config_get_sas_device_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
| 1159 | *mpi_reply, Mpi2SasDevicePage1_t *config_page, u32 form, u32 handle); | ||
| 1160 | int mpt2sas_config_get_sas_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
| 1161 | *mpi_reply, Mpi2SasIOUnitPage0_t *config_page, u16 sz); | ||
| 1162 | int mpt2sas_config_get_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
| 1163 | *mpi_reply, Mpi2IOUnitPage1_t *config_page); | ||
| 1164 | int mpt2sas_config_set_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
| 1165 | *mpi_reply, Mpi2IOUnitPage1_t *config_page); | ||
| 1166 | int mpt2sas_config_get_iounit_pg8(struct MPT2SAS_ADAPTER *ioc, | ||
| 1167 | Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage8_t *config_page); | ||
| 1168 | int mpt2sas_config_get_iounit_pg3(struct MPT2SAS_ADAPTER *ioc, | ||
| 1169 | Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage3_t *config_page, u16 sz); | ||
| 1170 | int mpt2sas_config_get_sas_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
| 1171 | *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, u16 sz); | ||
| 1172 | int mpt2sas_config_set_sas_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, | ||
| 1173 | Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, u16 sz); | ||
| 1174 | int mpt2sas_config_get_ioc_pg8(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
| 1175 | *mpi_reply, Mpi2IOCPage8_t *config_page); | ||
| 1176 | int mpt2sas_config_get_expander_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
| 1177 | *mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle); | ||
| 1178 | int mpt2sas_config_get_expander_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
| 1179 | *mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number, u16 handle); | ||
| 1180 | int mpt2sas_config_get_enclosure_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
| 1181 | *mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle); | ||
| 1182 | int mpt2sas_config_get_phy_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
| 1183 | *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number); | ||
| 1184 | int mpt2sas_config_get_phy_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
| 1185 | *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number); | ||
| 1186 | int mpt2sas_config_get_raid_volume_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
| 1187 | *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u32 handle); | ||
| 1188 | int mpt2sas_config_get_number_pds(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 *num_pds); | ||
| 1189 | int mpt2sas_config_get_raid_volume_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
| 1190 | *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form, u32 handle, u16 sz); | ||
| 1191 | int mpt2sas_config_get_phys_disk_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
| 1192 | *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form, | ||
| 1193 | u32 form_specific); | ||
| 1194 | int mpt2sas_config_get_volume_handle(struct MPT2SAS_ADAPTER *ioc, u16 pd_handle, | ||
| 1195 | u16 *volume_handle); | ||
| 1196 | int mpt2sas_config_get_volume_wwid(struct MPT2SAS_ADAPTER *ioc, u16 volume_handle, | ||
| 1197 | u64 *wwid); | ||
| 1198 | /* ctl shared API */ | ||
| 1199 | extern struct device_attribute *mpt2sas_host_attrs[]; | ||
| 1200 | extern struct device_attribute *mpt2sas_dev_attrs[]; | ||
| 1201 | void mpt2sas_ctl_init(void); | ||
| 1202 | void mpt2sas_ctl_exit(void); | ||
| 1203 | u8 mpt2sas_ctl_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | ||
| 1204 | u32 reply); | ||
| 1205 | void mpt2sas_ctl_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase); | ||
| 1206 | void mpt2sas_ctl_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, | ||
| 1207 | u32 reply); | ||
| 1208 | void mpt2sas_ctl_add_to_event_log(struct MPT2SAS_ADAPTER *ioc, | ||
| 1209 | Mpi2EventNotificationReply_t *mpi_reply); | ||
| 1210 | |||
| 1211 | void mpt2sas_enable_diag_buffer(struct MPT2SAS_ADAPTER *ioc, | ||
| 1212 | u8 bits_to_regsiter); | ||
| 1213 | |||
| 1214 | /* transport shared API */ | ||
| 1215 | u8 mpt2sas_transport_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | ||
| 1216 | u32 reply); | ||
| 1217 | struct _sas_port *mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER *ioc, | ||
| 1218 | u16 handle, u64 sas_address); | ||
| 1219 | void mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address, | ||
| 1220 | u64 sas_address_parent); | ||
| 1221 | int mpt2sas_transport_add_host_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy | ||
| 1222 | *mpt2sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev); | ||
| 1223 | int mpt2sas_transport_add_expander_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy | ||
| 1224 | *mpt2sas_phy, Mpi2ExpanderPage1_t expander_pg1, struct device *parent_dev); | ||
| 1225 | void mpt2sas_transport_update_links(struct MPT2SAS_ADAPTER *ioc, | ||
| 1226 | u64 sas_address, u16 handle, u8 phy_number, u8 link_rate); | ||
| 1227 | extern struct sas_function_template mpt2sas_transport_functions; | ||
| 1228 | extern struct scsi_transport_template *mpt2sas_transport_template; | ||
| 1229 | extern int scsi_internal_device_block(struct scsi_device *sdev); | ||
| 1230 | extern u8 mpt2sas_stm_zero_smid_handler(struct MPT2SAS_ADAPTER *ioc, | ||
| 1231 | u8 msix_index, u32 reply); | ||
| 1232 | extern int scsi_internal_device_unblock(struct scsi_device *sdev, | ||
| 1233 | enum scsi_device_state new_state); | ||
| 1234 | |||
| 1235 | #endif /* MPT2SAS_BASE_H_INCLUDED */ | ||
diff --git a/drivers/scsi/mpt2sas/mpt2sas_config.c b/drivers/scsi/mpt2sas/mpt2sas_config.c deleted file mode 100644 index c43815b1a485..000000000000 --- a/drivers/scsi/mpt2sas/mpt2sas_config.c +++ /dev/null | |||
| @@ -1,1527 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * This module provides common API for accessing firmware configuration pages | ||
| 3 | * | ||
| 4 | * This code is based on drivers/scsi/mpt2sas/mpt2_base.c | ||
| 5 | * Copyright (C) 2007-2014 LSI Corporation | ||
| 6 | * Copyright (C) 20013-2014 Avago Technologies | ||
| 7 | * (mailto: MPT-FusionLinux.pdl@avagotech.com) | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or | ||
| 10 | * modify it under the terms of the GNU General Public License | ||
| 11 | * as published by the Free Software Foundation; either version 2 | ||
| 12 | * of the License, or (at your option) any later version. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | * NO WARRANTY | ||
| 20 | * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR | ||
| 21 | * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT | ||
| 22 | * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, | ||
| 23 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is | ||
| 24 | * solely responsible for determining the appropriateness of using and | ||
| 25 | * distributing the Program and assumes all risks associated with its | ||
| 26 | * exercise of rights under this Agreement, including but not limited to | ||
| 27 | * the risks and costs of program errors, damage to or loss of data, | ||
| 28 | * programs or equipment, and unavailability or interruption of operations. | ||
| 29 | |||
| 30 | * DISCLAIMER OF LIABILITY | ||
| 31 | * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY | ||
| 32 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 33 | * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND | ||
| 34 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR | ||
| 35 | * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | ||
| 36 | * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED | ||
| 37 | * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES | ||
| 38 | |||
| 39 | * You should have received a copy of the GNU General Public License | ||
| 40 | * along with this program; if not, write to the Free Software | ||
| 41 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
| 42 | * USA. | ||
| 43 | */ | ||
| 44 | |||
| 45 | #include <linux/module.h> | ||
| 46 | #include <linux/kernel.h> | ||
| 47 | #include <linux/init.h> | ||
| 48 | #include <linux/errno.h> | ||
| 49 | #include <linux/blkdev.h> | ||
| 50 | #include <linux/sched.h> | ||
| 51 | #include <linux/workqueue.h> | ||
| 52 | #include <linux/delay.h> | ||
| 53 | #include <linux/pci.h> | ||
| 54 | #include <linux/slab.h> | ||
| 55 | |||
| 56 | #include "mpt2sas_base.h" | ||
| 57 | |||
| 58 | /* local definitions */ | ||
| 59 | |||
| 60 | /* Timeout for config page request (in seconds) */ | ||
| 61 | #define MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT 15 | ||
| 62 | |||
| 63 | /* Common sgl flags for READING a config page. */ | ||
| 64 | #define MPT2_CONFIG_COMMON_SGLFLAGS ((MPI2_SGE_FLAGS_SIMPLE_ELEMENT | \ | ||
| 65 | MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER \ | ||
| 66 | | MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT) | ||
| 67 | |||
| 68 | /* Common sgl flags for WRITING a config page. */ | ||
| 69 | #define MPT2_CONFIG_COMMON_WRITE_SGLFLAGS ((MPI2_SGE_FLAGS_SIMPLE_ELEMENT | \ | ||
| 70 | MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER \ | ||
| 71 | | MPI2_SGE_FLAGS_END_OF_LIST | MPI2_SGE_FLAGS_HOST_TO_IOC) \ | ||
| 72 | << MPI2_SGE_FLAGS_SHIFT) | ||
| 73 | |||
| 74 | /** | ||
| 75 | * struct config_request - obtain dma memory via routine | ||
| 76 | * @sz: size | ||
| 77 | * @page: virt pointer | ||
| 78 | * @page_dma: phys pointer | ||
| 79 | * | ||
| 80 | */ | ||
| 81 | struct config_request{ | ||
| 82 | u16 sz; | ||
| 83 | void *page; | ||
| 84 | dma_addr_t page_dma; | ||
| 85 | }; | ||
| 86 | |||
| 87 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | ||
| 88 | /** | ||
| 89 | * _config_display_some_debug - debug routine | ||
| 90 | * @ioc: per adapter object | ||
| 91 | * @smid: system request message index | ||
| 92 | * @calling_function_name: string pass from calling function | ||
| 93 | * @mpi_reply: reply message frame | ||
| 94 | * Context: none. | ||
| 95 | * | ||
| 96 | * Function for displaying debug info helpful when debugging issues | ||
| 97 | * in this module. | ||
| 98 | */ | ||
| 99 | static void | ||
| 100 | _config_display_some_debug(struct MPT2SAS_ADAPTER *ioc, u16 smid, | ||
| 101 | char *calling_function_name, MPI2DefaultReply_t *mpi_reply) | ||
| 102 | { | ||
| 103 | Mpi2ConfigRequest_t *mpi_request; | ||
| 104 | char *desc = NULL; | ||
| 105 | |||
| 106 | if (!(ioc->logging_level & MPT_DEBUG_CONFIG)) | ||
| 107 | return; | ||
| 108 | |||
| 109 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); | ||
| 110 | switch (mpi_request->Header.PageType & MPI2_CONFIG_PAGETYPE_MASK) { | ||
| 111 | case MPI2_CONFIG_PAGETYPE_IO_UNIT: | ||
| 112 | desc = "io_unit"; | ||
| 113 | break; | ||
| 114 | case MPI2_CONFIG_PAGETYPE_IOC: | ||
| 115 | desc = "ioc"; | ||
| 116 | break; | ||
| 117 | case MPI2_CONFIG_PAGETYPE_BIOS: | ||
| 118 | desc = "bios"; | ||
| 119 | break; | ||
| 120 | case MPI2_CONFIG_PAGETYPE_RAID_VOLUME: | ||
| 121 | desc = "raid_volume"; | ||
| 122 | break; | ||
| 123 | case MPI2_CONFIG_PAGETYPE_MANUFACTURING: | ||
| 124 | desc = "manufaucturing"; | ||
| 125 | break; | ||
| 126 | case MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK: | ||
| 127 | desc = "physdisk"; | ||
| 128 | break; | ||
| 129 | case MPI2_CONFIG_PAGETYPE_EXTENDED: | ||
| 130 | switch (mpi_request->ExtPageType) { | ||
| 131 | case MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT: | ||
| 132 | desc = "sas_io_unit"; | ||
| 133 | break; | ||
| 134 | case MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER: | ||
| 135 | desc = "sas_expander"; | ||
| 136 | break; | ||
| 137 | case MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE: | ||
| 138 | desc = "sas_device"; | ||
| 139 | break; | ||
| 140 | case MPI2_CONFIG_EXTPAGETYPE_SAS_PHY: | ||
| 141 | desc = "sas_phy"; | ||
| 142 | break; | ||
| 143 | case MPI2_CONFIG_EXTPAGETYPE_LOG: | ||
| 144 | desc = "log"; | ||
| 145 | break; | ||
| 146 | case MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE: | ||
| 147 | desc = "enclosure"; | ||
| 148 | break; | ||
| 149 | case MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG: | ||
| 150 | desc = "raid_config"; | ||
| 151 | break; | ||
| 152 | case MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING: | ||
| 153 | desc = "driver_mapping"; | ||
| 154 | break; | ||
| 155 | } | ||
| 156 | break; | ||
| 157 | } | ||
| 158 | |||
| 159 | if (!desc) | ||
| 160 | return; | ||
| 161 | |||
| 162 | printk(MPT2SAS_INFO_FMT "%s: %s(%d), action(%d), form(0x%08x), " | ||
| 163 | "smid(%d)\n", ioc->name, calling_function_name, desc, | ||
| 164 | mpi_request->Header.PageNumber, mpi_request->Action, | ||
| 165 | le32_to_cpu(mpi_request->PageAddress), smid); | ||
| 166 | |||
| 167 | if (!mpi_reply) | ||
| 168 | return; | ||
| 169 | |||
| 170 | if (mpi_reply->IOCStatus || mpi_reply->IOCLogInfo) | ||
| 171 | printk(MPT2SAS_INFO_FMT | ||
| 172 | "\tiocstatus(0x%04x), loginfo(0x%08x)\n", | ||
| 173 | ioc->name, le16_to_cpu(mpi_reply->IOCStatus), | ||
| 174 | le32_to_cpu(mpi_reply->IOCLogInfo)); | ||
| 175 | } | ||
| 176 | #endif | ||
| 177 | |||
| 178 | /** | ||
| 179 | * _config_alloc_config_dma_memory - obtain physical memory | ||
| 180 | * @ioc: per adapter object | ||
| 181 | * @mem: struct config_request | ||
| 182 | * | ||
| 183 | * A wrapper for obtaining dma-able memory for config page request. | ||
| 184 | * | ||
| 185 | * Returns 0 for success, non-zero for failure. | ||
| 186 | */ | ||
| 187 | static int | ||
| 188 | _config_alloc_config_dma_memory(struct MPT2SAS_ADAPTER *ioc, | ||
| 189 | struct config_request *mem) | ||
| 190 | { | ||
| 191 | int r = 0; | ||
| 192 | |||
| 193 | if (mem->sz > ioc->config_page_sz) { | ||
| 194 | mem->page = dma_alloc_coherent(&ioc->pdev->dev, mem->sz, | ||
| 195 | &mem->page_dma, GFP_KERNEL); | ||
| 196 | if (!mem->page) { | ||
| 197 | printk(MPT2SAS_ERR_FMT "%s: dma_alloc_coherent" | ||
| 198 | " failed asking for (%d) bytes!!\n", | ||
| 199 | ioc->name, __func__, mem->sz); | ||
| 200 | r = -ENOMEM; | ||
| 201 | } | ||
| 202 | } else { /* use tmp buffer if less than 512 bytes */ | ||
| 203 | mem->page = ioc->config_page; | ||
| 204 | mem->page_dma = ioc->config_page_dma; | ||
| 205 | } | ||
| 206 | return r; | ||
| 207 | } | ||
| 208 | |||
| 209 | /** | ||
| 210 | * _config_free_config_dma_memory - wrapper to free the memory | ||
| 211 | * @ioc: per adapter object | ||
| 212 | * @mem: struct config_request | ||
| 213 | * | ||
| 214 | * A wrapper to free dma-able memory when using _config_alloc_config_dma_memory. | ||
| 215 | * | ||
| 216 | * Returns 0 for success, non-zero for failure. | ||
| 217 | */ | ||
| 218 | static void | ||
| 219 | _config_free_config_dma_memory(struct MPT2SAS_ADAPTER *ioc, | ||
| 220 | struct config_request *mem) | ||
| 221 | { | ||
| 222 | if (mem->sz > ioc->config_page_sz) | ||
| 223 | dma_free_coherent(&ioc->pdev->dev, mem->sz, mem->page, | ||
| 224 | mem->page_dma); | ||
| 225 | } | ||
| 226 | |||
| 227 | /** | ||
| 228 | * mpt2sas_config_done - config page completion routine | ||
| 229 | * @ioc: per adapter object | ||
| 230 | * @smid: system request message index | ||
| 231 | * @msix_index: MSIX table index supplied by the OS | ||
| 232 | * @reply: reply message frame(lower 32bit addr) | ||
| 233 | * Context: none. | ||
| 234 | * | ||
| 235 | * The callback handler when using _config_request. | ||
| 236 | * | ||
| 237 | * Return 1 meaning mf should be freed from _base_interrupt | ||
| 238 | * 0 means the mf is freed from this function. | ||
| 239 | */ | ||
| 240 | u8 | ||
| 241 | mpt2sas_config_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | ||
| 242 | u32 reply) | ||
| 243 | { | ||
| 244 | MPI2DefaultReply_t *mpi_reply; | ||
| 245 | |||
| 246 | if (ioc->config_cmds.status == MPT2_CMD_NOT_USED) | ||
| 247 | return 1; | ||
| 248 | if (ioc->config_cmds.smid != smid) | ||
| 249 | return 1; | ||
| 250 | ioc->config_cmds.status |= MPT2_CMD_COMPLETE; | ||
| 251 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | ||
| 252 | if (mpi_reply) { | ||
| 253 | ioc->config_cmds.status |= MPT2_CMD_REPLY_VALID; | ||
| 254 | memcpy(ioc->config_cmds.reply, mpi_reply, | ||
| 255 | mpi_reply->MsgLength*4); | ||
| 256 | } | ||
| 257 | ioc->config_cmds.status &= ~MPT2_CMD_PENDING; | ||
| 258 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | ||
| 259 | _config_display_some_debug(ioc, smid, "config_done", mpi_reply); | ||
| 260 | #endif | ||
| 261 | ioc->config_cmds.smid = USHRT_MAX; | ||
| 262 | complete(&ioc->config_cmds.done); | ||
| 263 | return 1; | ||
| 264 | } | ||
| 265 | |||
| 266 | /** | ||
| 267 | * _config_request - main routine for sending config page requests | ||
| 268 | * @ioc: per adapter object | ||
| 269 | * @mpi_request: request message frame | ||
| 270 | * @mpi_reply: reply mf payload returned from firmware | ||
| 271 | * @timeout: timeout in seconds | ||
| 272 | * @config_page: contents of the config page | ||
| 273 | * @config_page_sz: size of config page | ||
| 274 | * Context: sleep | ||
| 275 | * | ||
| 276 | * A generic API for config page requests to firmware. | ||
| 277 | * | ||
| 278 | * The ioc->config_cmds.status flag should be MPT2_CMD_NOT_USED before calling | ||
| 279 | * this API. | ||
| 280 | * | ||
| 281 | * The callback index is set inside `ioc->config_cb_idx. | ||
| 282 | * | ||
| 283 | * Returns 0 for success, non-zero for failure. | ||
| 284 | */ | ||
| 285 | static int | ||
| 286 | _config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t | ||
| 287 | *mpi_request, Mpi2ConfigReply_t *mpi_reply, int timeout, | ||
| 288 | void *config_page, u16 config_page_sz) | ||
| 289 | { | ||
| 290 | u16 smid; | ||
| 291 | u32 ioc_state; | ||
| 292 | unsigned long timeleft; | ||
| 293 | Mpi2ConfigRequest_t *config_request; | ||
| 294 | int r; | ||
| 295 | u8 retry_count, issue_host_reset = 0; | ||
| 296 | u16 wait_state_count; | ||
| 297 | struct config_request mem; | ||
| 298 | |||
| 299 | mutex_lock(&ioc->config_cmds.mutex); | ||
| 300 | if (ioc->config_cmds.status != MPT2_CMD_NOT_USED) { | ||
| 301 | printk(MPT2SAS_ERR_FMT "%s: config_cmd in use\n", | ||
| 302 | ioc->name, __func__); | ||
| 303 | mutex_unlock(&ioc->config_cmds.mutex); | ||
| 304 | return -EAGAIN; | ||
| 305 | } | ||
| 306 | |||
| 307 | retry_count = 0; | ||
| 308 | memset(&mem, 0, sizeof(struct config_request)); | ||
| 309 | |||
| 310 | mpi_request->VF_ID = 0; /* TODO */ | ||
| 311 | mpi_request->VP_ID = 0; | ||
| 312 | |||
| 313 | if (config_page) { | ||
| 314 | mpi_request->Header.PageVersion = mpi_reply->Header.PageVersion; | ||
| 315 | mpi_request->Header.PageNumber = mpi_reply->Header.PageNumber; | ||
| 316 | mpi_request->Header.PageType = mpi_reply->Header.PageType; | ||
| 317 | mpi_request->Header.PageLength = mpi_reply->Header.PageLength; | ||
| 318 | mpi_request->ExtPageLength = mpi_reply->ExtPageLength; | ||
| 319 | mpi_request->ExtPageType = mpi_reply->ExtPageType; | ||
| 320 | if (mpi_request->Header.PageLength) | ||
| 321 | mem.sz = mpi_request->Header.PageLength * 4; | ||
| 322 | else | ||
| 323 | mem.sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4; | ||
| 324 | r = _config_alloc_config_dma_memory(ioc, &mem); | ||
| 325 | if (r != 0) | ||
| 326 | goto out; | ||
| 327 | if (mpi_request->Action == | ||
| 328 | MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT || | ||
| 329 | mpi_request->Action == | ||
| 330 | MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM) { | ||
| 331 | ioc->base_add_sg_single(&mpi_request->PageBufferSGE, | ||
| 332 | MPT2_CONFIG_COMMON_WRITE_SGLFLAGS | mem.sz, | ||
| 333 | mem.page_dma); | ||
| 334 | memcpy(mem.page, config_page, min_t(u16, mem.sz, | ||
| 335 | config_page_sz)); | ||
| 336 | } else { | ||
| 337 | memset(config_page, 0, config_page_sz); | ||
| 338 | ioc->base_add_sg_single(&mpi_request->PageBufferSGE, | ||
| 339 | MPT2_CONFIG_COMMON_SGLFLAGS | mem.sz, mem.page_dma); | ||
| 340 | } | ||
| 341 | } | ||
| 342 | |||
| 343 | retry_config: | ||
| 344 | if (retry_count) { | ||
| 345 | if (retry_count > 2) { /* attempt only 2 retries */ | ||
| 346 | r = -EFAULT; | ||
| 347 | goto free_mem; | ||
| 348 | } | ||
| 349 | printk(MPT2SAS_INFO_FMT "%s: attempting retry (%d)\n", | ||
| 350 | ioc->name, __func__, retry_count); | ||
| 351 | } | ||
| 352 | wait_state_count = 0; | ||
| 353 | ioc_state = mpt2sas_base_get_iocstate(ioc, 1); | ||
| 354 | while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { | ||
| 355 | if (wait_state_count++ == MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT) { | ||
| 356 | printk(MPT2SAS_ERR_FMT | ||
| 357 | "%s: failed due to ioc not operational\n", | ||
| 358 | ioc->name, __func__); | ||
| 359 | ioc->config_cmds.status = MPT2_CMD_NOT_USED; | ||
| 360 | r = -EFAULT; | ||
| 361 | goto free_mem; | ||
| 362 | } | ||
| 363 | ssleep(1); | ||
| 364 | ioc_state = mpt2sas_base_get_iocstate(ioc, 1); | ||
| 365 | printk(MPT2SAS_INFO_FMT "%s: waiting for " | ||
| 366 | "operational state(count=%d)\n", ioc->name, | ||
| 367 | __func__, wait_state_count); | ||
| 368 | } | ||
| 369 | if (wait_state_count) | ||
| 370 | printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n", | ||
| 371 | ioc->name, __func__); | ||
| 372 | |||
| 373 | smid = mpt2sas_base_get_smid(ioc, ioc->config_cb_idx); | ||
| 374 | if (!smid) { | ||
| 375 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", | ||
| 376 | ioc->name, __func__); | ||
| 377 | ioc->config_cmds.status = MPT2_CMD_NOT_USED; | ||
| 378 | r = -EAGAIN; | ||
| 379 | goto free_mem; | ||
| 380 | } | ||
| 381 | |||
| 382 | r = 0; | ||
| 383 | memset(mpi_reply, 0, sizeof(Mpi2ConfigReply_t)); | ||
| 384 | ioc->config_cmds.status = MPT2_CMD_PENDING; | ||
| 385 | config_request = mpt2sas_base_get_msg_frame(ioc, smid); | ||
| 386 | ioc->config_cmds.smid = smid; | ||
| 387 | memcpy(config_request, mpi_request, sizeof(Mpi2ConfigRequest_t)); | ||
| 388 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | ||
| 389 | _config_display_some_debug(ioc, smid, "config_request", NULL); | ||
| 390 | #endif | ||
| 391 | init_completion(&ioc->config_cmds.done); | ||
| 392 | mpt2sas_base_put_smid_default(ioc, smid); | ||
| 393 | timeleft = wait_for_completion_timeout(&ioc->config_cmds.done, | ||
| 394 | timeout*HZ); | ||
| 395 | if (!(ioc->config_cmds.status & MPT2_CMD_COMPLETE)) { | ||
| 396 | printk(MPT2SAS_ERR_FMT "%s: timeout\n", | ||
| 397 | ioc->name, __func__); | ||
| 398 | _debug_dump_mf(mpi_request, | ||
| 399 | sizeof(Mpi2ConfigRequest_t)/4); | ||
| 400 | retry_count++; | ||
| 401 | if (ioc->config_cmds.smid == smid) | ||
| 402 | mpt2sas_base_free_smid(ioc, smid); | ||
| 403 | if ((ioc->shost_recovery) || (ioc->config_cmds.status & | ||
| 404 | MPT2_CMD_RESET) || ioc->pci_error_recovery) | ||
| 405 | goto retry_config; | ||
| 406 | issue_host_reset = 1; | ||
| 407 | r = -EFAULT; | ||
| 408 | goto free_mem; | ||
| 409 | } | ||
| 410 | |||
| 411 | if (ioc->config_cmds.status & MPT2_CMD_REPLY_VALID) | ||
| 412 | memcpy(mpi_reply, ioc->config_cmds.reply, | ||
| 413 | sizeof(Mpi2ConfigReply_t)); | ||
| 414 | if (retry_count) | ||
| 415 | printk(MPT2SAS_INFO_FMT "%s: retry (%d) completed!!\n", | ||
| 416 | ioc->name, __func__, retry_count); | ||
| 417 | if (config_page && mpi_request->Action == | ||
| 418 | MPI2_CONFIG_ACTION_PAGE_READ_CURRENT) | ||
| 419 | memcpy(config_page, mem.page, min_t(u16, mem.sz, | ||
| 420 | config_page_sz)); | ||
| 421 | free_mem: | ||
| 422 | if (config_page) | ||
| 423 | _config_free_config_dma_memory(ioc, &mem); | ||
| 424 | out: | ||
| 425 | ioc->config_cmds.status = MPT2_CMD_NOT_USED; | ||
| 426 | mutex_unlock(&ioc->config_cmds.mutex); | ||
| 427 | |||
| 428 | if (issue_host_reset) | ||
| 429 | mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, | ||
| 430 | FORCE_BIG_HAMMER); | ||
| 431 | return r; | ||
| 432 | } | ||
| 433 | |||
| 434 | /** | ||
| 435 | * mpt2sas_config_get_manufacturing_pg0 - obtain manufacturing page 0 | ||
| 436 | * @ioc: per adapter object | ||
| 437 | * @mpi_reply: reply mf payload returned from firmware | ||
| 438 | * @config_page: contents of the config page | ||
| 439 | * Context: sleep. | ||
| 440 | * | ||
| 441 | * Returns 0 for success, non-zero for failure. | ||
| 442 | */ | ||
| 443 | int | ||
| 444 | mpt2sas_config_get_manufacturing_pg0(struct MPT2SAS_ADAPTER *ioc, | ||
| 445 | Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page) | ||
| 446 | { | ||
| 447 | Mpi2ConfigRequest_t mpi_request; | ||
| 448 | int r; | ||
| 449 | |||
| 450 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
| 451 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
| 452 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
| 453 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING; | ||
| 454 | mpi_request.Header.PageNumber = 0; | ||
| 455 | mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION; | ||
| 456 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
| 457 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 458 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | ||
| 459 | if (r) | ||
| 460 | goto out; | ||
| 461 | |||
| 462 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
| 463 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 464 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | ||
| 465 | sizeof(*config_page)); | ||
| 466 | out: | ||
| 467 | return r; | ||
| 468 | } | ||
| 469 | |||
| 470 | /** | ||
| 471 | * mpt2sas_config_get_manufacturing_pg10 - obtain manufacturing page 10 | ||
| 472 | * @ioc: per adapter object | ||
| 473 | * @mpi_reply: reply mf payload returned from firmware | ||
| 474 | * @config_page: contents of the config page | ||
| 475 | * Context: sleep. | ||
| 476 | * | ||
| 477 | * Returns 0 for success, non-zero for failure. | ||
| 478 | */ | ||
| 479 | int | ||
| 480 | mpt2sas_config_get_manufacturing_pg10(struct MPT2SAS_ADAPTER *ioc, | ||
| 481 | Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage10_t *config_page) | ||
| 482 | { | ||
| 483 | Mpi2ConfigRequest_t mpi_request; | ||
| 484 | int r; | ||
| 485 | |||
| 486 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
| 487 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
| 488 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
| 489 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING; | ||
| 490 | mpi_request.Header.PageNumber = 10; | ||
| 491 | mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION; | ||
| 492 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
| 493 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 494 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | ||
| 495 | if (r) | ||
| 496 | goto out; | ||
| 497 | |||
| 498 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
| 499 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 500 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | ||
| 501 | sizeof(*config_page)); | ||
| 502 | out: | ||
| 503 | return r; | ||
| 504 | } | ||
| 505 | |||
| 506 | /** | ||
| 507 | * mpt2sas_config_get_bios_pg2 - obtain bios page 2 | ||
| 508 | * @ioc: per adapter object | ||
| 509 | * @mpi_reply: reply mf payload returned from firmware | ||
| 510 | * @config_page: contents of the config page | ||
| 511 | * Context: sleep. | ||
| 512 | * | ||
| 513 | * Returns 0 for success, non-zero for failure. | ||
| 514 | */ | ||
| 515 | int | ||
| 516 | mpt2sas_config_get_bios_pg2(struct MPT2SAS_ADAPTER *ioc, | ||
| 517 | Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage2_t *config_page) | ||
| 518 | { | ||
| 519 | Mpi2ConfigRequest_t mpi_request; | ||
| 520 | int r; | ||
| 521 | |||
| 522 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
| 523 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
| 524 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
| 525 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS; | ||
| 526 | mpi_request.Header.PageNumber = 2; | ||
| 527 | mpi_request.Header.PageVersion = MPI2_BIOSPAGE2_PAGEVERSION; | ||
| 528 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
| 529 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 530 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | ||
| 531 | if (r) | ||
| 532 | goto out; | ||
| 533 | |||
| 534 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
| 535 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 536 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | ||
| 537 | sizeof(*config_page)); | ||
| 538 | out: | ||
| 539 | return r; | ||
| 540 | } | ||
| 541 | |||
| 542 | /** | ||
| 543 | * mpt2sas_config_get_bios_pg3 - obtain bios page 3 | ||
| 544 | * @ioc: per adapter object | ||
| 545 | * @mpi_reply: reply mf payload returned from firmware | ||
| 546 | * @config_page: contents of the config page | ||
| 547 | * Context: sleep. | ||
| 548 | * | ||
| 549 | * Returns 0 for success, non-zero for failure. | ||
| 550 | */ | ||
| 551 | int | ||
| 552 | mpt2sas_config_get_bios_pg3(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
| 553 | *mpi_reply, Mpi2BiosPage3_t *config_page) | ||
| 554 | { | ||
| 555 | Mpi2ConfigRequest_t mpi_request; | ||
| 556 | int r; | ||
| 557 | |||
| 558 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
| 559 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
| 560 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
| 561 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS; | ||
| 562 | mpi_request.Header.PageNumber = 3; | ||
| 563 | mpi_request.Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION; | ||
| 564 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
| 565 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 566 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | ||
| 567 | if (r) | ||
| 568 | goto out; | ||
| 569 | |||
| 570 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
| 571 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 572 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | ||
| 573 | sizeof(*config_page)); | ||
| 574 | out: | ||
| 575 | return r; | ||
| 576 | } | ||
| 577 | |||
| 578 | /** | ||
| 579 | * mpt2sas_config_get_iounit_pg0 - obtain iounit page 0 | ||
| 580 | * @ioc: per adapter object | ||
| 581 | * @mpi_reply: reply mf payload returned from firmware | ||
| 582 | * @config_page: contents of the config page | ||
| 583 | * Context: sleep. | ||
| 584 | * | ||
| 585 | * Returns 0 for success, non-zero for failure. | ||
| 586 | */ | ||
| 587 | int | ||
| 588 | mpt2sas_config_get_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, | ||
| 589 | Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage0_t *config_page) | ||
| 590 | { | ||
| 591 | Mpi2ConfigRequest_t mpi_request; | ||
| 592 | int r; | ||
| 593 | |||
| 594 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
| 595 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
| 596 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
| 597 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; | ||
| 598 | mpi_request.Header.PageNumber = 0; | ||
| 599 | mpi_request.Header.PageVersion = MPI2_IOUNITPAGE0_PAGEVERSION; | ||
| 600 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
| 601 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 602 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | ||
| 603 | if (r) | ||
| 604 | goto out; | ||
| 605 | |||
| 606 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
| 607 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 608 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | ||
| 609 | sizeof(*config_page)); | ||
| 610 | out: | ||
| 611 | return r; | ||
| 612 | } | ||
| 613 | |||
| 614 | /** | ||
| 615 | * mpt2sas_config_get_iounit_pg1 - obtain iounit page 1 | ||
| 616 | * @ioc: per adapter object | ||
| 617 | * @mpi_reply: reply mf payload returned from firmware | ||
| 618 | * @config_page: contents of the config page | ||
| 619 | * Context: sleep. | ||
| 620 | * | ||
| 621 | * Returns 0 for success, non-zero for failure. | ||
| 622 | */ | ||
| 623 | int | ||
| 624 | mpt2sas_config_get_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, | ||
| 625 | Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page) | ||
| 626 | { | ||
| 627 | Mpi2ConfigRequest_t mpi_request; | ||
| 628 | int r; | ||
| 629 | |||
| 630 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
| 631 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
| 632 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
| 633 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; | ||
| 634 | mpi_request.Header.PageNumber = 1; | ||
| 635 | mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION; | ||
| 636 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
| 637 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 638 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | ||
| 639 | if (r) | ||
| 640 | goto out; | ||
| 641 | |||
| 642 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
| 643 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 644 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | ||
| 645 | sizeof(*config_page)); | ||
| 646 | out: | ||
| 647 | return r; | ||
| 648 | } | ||
| 649 | |||
| 650 | /** | ||
| 651 | * mpt2sas_config_set_iounit_pg1 - set iounit page 1 | ||
| 652 | * @ioc: per adapter object | ||
| 653 | * @mpi_reply: reply mf payload returned from firmware | ||
| 654 | * @config_page: contents of the config page | ||
| 655 | * Context: sleep. | ||
| 656 | * | ||
| 657 | * Returns 0 for success, non-zero for failure. | ||
| 658 | */ | ||
| 659 | int | ||
| 660 | mpt2sas_config_set_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, | ||
| 661 | Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page) | ||
| 662 | { | ||
| 663 | Mpi2ConfigRequest_t mpi_request; | ||
| 664 | int r; | ||
| 665 | |||
| 666 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
| 667 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
| 668 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
| 669 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; | ||
| 670 | mpi_request.Header.PageNumber = 1; | ||
| 671 | mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION; | ||
| 672 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
| 673 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 674 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | ||
| 675 | if (r) | ||
| 676 | goto out; | ||
| 677 | |||
| 678 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT; | ||
| 679 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 680 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | ||
| 681 | sizeof(*config_page)); | ||
| 682 | out: | ||
| 683 | return r; | ||
| 684 | } | ||
| 685 | |||
| 686 | /** | ||
| 687 | * mpt2sas_config_get_iounit_pg3 - obtain iounit page 3 | ||
| 688 | * @ioc: per adapter object | ||
| 689 | * @mpi_reply: reply mf payload returned from firmware | ||
| 690 | * @config_page: contents of the config page | ||
| 691 | * @sz: size of buffer passed in config_page | ||
| 692 | * Context: sleep. | ||
| 693 | * | ||
| 694 | * Returns 0 for success, non-zero for failure. | ||
| 695 | */ | ||
| 696 | int | ||
| 697 | mpt2sas_config_get_iounit_pg3(struct MPT2SAS_ADAPTER *ioc, | ||
| 698 | Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage3_t *config_page, u16 sz) | ||
| 699 | { | ||
| 700 | Mpi2ConfigRequest_t mpi_request; | ||
| 701 | int r; | ||
| 702 | |||
| 703 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
| 704 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
| 705 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
| 706 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; | ||
| 707 | mpi_request.Header.PageNumber = 3; | ||
| 708 | mpi_request.Header.PageVersion = MPI2_IOUNITPAGE3_PAGEVERSION; | ||
| 709 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
| 710 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 711 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | ||
| 712 | if (r) | ||
| 713 | goto out; | ||
| 714 | |||
| 715 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
| 716 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 717 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); | ||
| 718 | out: | ||
| 719 | return r; | ||
| 720 | } | ||
| 721 | |||
| 722 | /** | ||
| 723 | * mpt2sas_config_get_iounit_pg8 - obtain iounit page 8 | ||
| 724 | * @ioc: per adapter object | ||
| 725 | * @mpi_reply: reply mf payload returned from firmware | ||
| 726 | * @config_page: contents of the config page | ||
| 727 | * Context: sleep. | ||
| 728 | * | ||
| 729 | * Returns 0 for success, non-zero for failure. | ||
| 730 | */ | ||
| 731 | int | ||
| 732 | mpt2sas_config_get_iounit_pg8(struct MPT2SAS_ADAPTER *ioc, | ||
| 733 | Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage8_t *config_page) | ||
| 734 | { | ||
| 735 | Mpi2ConfigRequest_t mpi_request; | ||
| 736 | int r; | ||
| 737 | |||
| 738 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
| 739 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
| 740 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
| 741 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; | ||
| 742 | mpi_request.Header.PageNumber = 8; | ||
| 743 | mpi_request.Header.PageVersion = MPI2_IOUNITPAGE8_PAGEVERSION; | ||
| 744 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
| 745 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 746 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | ||
| 747 | if (r) | ||
| 748 | goto out; | ||
| 749 | |||
| 750 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
| 751 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 752 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | ||
| 753 | sizeof(*config_page)); | ||
| 754 | out: | ||
| 755 | return r; | ||
| 756 | } | ||
| 757 | |||
| 758 | /** | ||
| 759 | * mpt2sas_config_get_ioc_pg8 - obtain ioc page 8 | ||
| 760 | * @ioc: per adapter object | ||
| 761 | * @mpi_reply: reply mf payload returned from firmware | ||
| 762 | * @config_page: contents of the config page | ||
| 763 | * Context: sleep. | ||
| 764 | * | ||
| 765 | * Returns 0 for success, non-zero for failure. | ||
| 766 | */ | ||
| 767 | int | ||
| 768 | mpt2sas_config_get_ioc_pg8(struct MPT2SAS_ADAPTER *ioc, | ||
| 769 | Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage8_t *config_page) | ||
| 770 | { | ||
| 771 | Mpi2ConfigRequest_t mpi_request; | ||
| 772 | int r; | ||
| 773 | |||
| 774 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
| 775 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
| 776 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
| 777 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC; | ||
| 778 | mpi_request.Header.PageNumber = 8; | ||
| 779 | mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION; | ||
| 780 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
| 781 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 782 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | ||
| 783 | if (r) | ||
| 784 | goto out; | ||
| 785 | |||
| 786 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
| 787 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 788 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | ||
| 789 | sizeof(*config_page)); | ||
| 790 | out: | ||
| 791 | return r; | ||
| 792 | } | ||
| 793 | |||
| 794 | /** | ||
| 795 | * mpt2sas_config_get_sas_device_pg0 - obtain sas device page 0 | ||
| 796 | * @ioc: per adapter object | ||
| 797 | * @mpi_reply: reply mf payload returned from firmware | ||
| 798 | * @config_page: contents of the config page | ||
| 799 | * @form: GET_NEXT_HANDLE or HANDLE | ||
| 800 | * @handle: device handle | ||
| 801 | * Context: sleep. | ||
| 802 | * | ||
| 803 | * Returns 0 for success, non-zero for failure. | ||
| 804 | */ | ||
| 805 | int | ||
| 806 | mpt2sas_config_get_sas_device_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
| 807 | *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u32 handle) | ||
| 808 | { | ||
| 809 | Mpi2ConfigRequest_t mpi_request; | ||
| 810 | int r; | ||
| 811 | |||
| 812 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
| 813 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
| 814 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
| 815 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | ||
| 816 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; | ||
| 817 | mpi_request.Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION; | ||
| 818 | mpi_request.Header.PageNumber = 0; | ||
| 819 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
| 820 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 821 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | ||
| 822 | if (r) | ||
| 823 | goto out; | ||
| 824 | |||
| 825 | mpi_request.PageAddress = cpu_to_le32(form | handle); | ||
| 826 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
| 827 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 828 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | ||
| 829 | sizeof(*config_page)); | ||
| 830 | out: | ||
| 831 | return r; | ||
| 832 | } | ||
| 833 | |||
| 834 | /** | ||
| 835 | * mpt2sas_config_get_sas_device_pg1 - obtain sas device page 1 | ||
| 836 | * @ioc: per adapter object | ||
| 837 | * @mpi_reply: reply mf payload returned from firmware | ||
| 838 | * @config_page: contents of the config page | ||
| 839 | * @form: GET_NEXT_HANDLE or HANDLE | ||
| 840 | * @handle: device handle | ||
| 841 | * Context: sleep. | ||
| 842 | * | ||
| 843 | * Returns 0 for success, non-zero for failure. | ||
| 844 | */ | ||
| 845 | int | ||
| 846 | mpt2sas_config_get_sas_device_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
| 847 | *mpi_reply, Mpi2SasDevicePage1_t *config_page, u32 form, u32 handle) | ||
| 848 | { | ||
| 849 | Mpi2ConfigRequest_t mpi_request; | ||
| 850 | int r; | ||
| 851 | |||
| 852 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
| 853 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
| 854 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
| 855 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | ||
| 856 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; | ||
| 857 | mpi_request.Header.PageVersion = MPI2_SASDEVICE1_PAGEVERSION; | ||
| 858 | mpi_request.Header.PageNumber = 1; | ||
| 859 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
| 860 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 861 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | ||
| 862 | if (r) | ||
| 863 | goto out; | ||
| 864 | |||
| 865 | mpi_request.PageAddress = cpu_to_le32(form | handle); | ||
| 866 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
| 867 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 868 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | ||
| 869 | sizeof(*config_page)); | ||
| 870 | out: | ||
| 871 | return r; | ||
| 872 | } | ||
| 873 | |||
| 874 | /** | ||
| 875 | * mpt2sas_config_get_number_hba_phys - obtain number of phys on the host | ||
| 876 | * @ioc: per adapter object | ||
| 877 | * @num_phys: pointer returned with the number of phys | ||
| 878 | * Context: sleep. | ||
| 879 | * | ||
| 880 | * Returns 0 for success, non-zero for failure. | ||
| 881 | */ | ||
| 882 | int | ||
| 883 | mpt2sas_config_get_number_hba_phys(struct MPT2SAS_ADAPTER *ioc, u8 *num_phys) | ||
| 884 | { | ||
| 885 | Mpi2ConfigRequest_t mpi_request; | ||
| 886 | int r; | ||
| 887 | u16 ioc_status; | ||
| 888 | Mpi2ConfigReply_t mpi_reply; | ||
| 889 | Mpi2SasIOUnitPage0_t config_page; | ||
| 890 | |||
| 891 | *num_phys = 0; | ||
| 892 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
| 893 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
| 894 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
| 895 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | ||
| 896 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; | ||
| 897 | mpi_request.Header.PageNumber = 0; | ||
| 898 | mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION; | ||
| 899 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
| 900 | r = _config_request(ioc, &mpi_request, &mpi_reply, | ||
| 901 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | ||
| 902 | if (r) | ||
| 903 | goto out; | ||
| 904 | |||
| 905 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
| 906 | r = _config_request(ioc, &mpi_request, &mpi_reply, | ||
| 907 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page, | ||
| 908 | sizeof(Mpi2SasIOUnitPage0_t)); | ||
| 909 | if (!r) { | ||
| 910 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
| 911 | MPI2_IOCSTATUS_MASK; | ||
| 912 | if (ioc_status == MPI2_IOCSTATUS_SUCCESS) | ||
| 913 | *num_phys = config_page.NumPhys; | ||
| 914 | } | ||
| 915 | out: | ||
| 916 | return r; | ||
| 917 | } | ||
| 918 | |||
| 919 | /** | ||
| 920 | * mpt2sas_config_get_sas_iounit_pg0 - obtain sas iounit page 0 | ||
| 921 | * @ioc: per adapter object | ||
| 922 | * @mpi_reply: reply mf payload returned from firmware | ||
| 923 | * @config_page: contents of the config page | ||
| 924 | * @sz: size of buffer passed in config_page | ||
| 925 | * Context: sleep. | ||
| 926 | * | ||
| 927 | * Calling function should call config_get_number_hba_phys prior to | ||
| 928 | * this function, so enough memory is allocated for config_page. | ||
| 929 | * | ||
| 930 | * Returns 0 for success, non-zero for failure. | ||
| 931 | */ | ||
| 932 | int | ||
| 933 | mpt2sas_config_get_sas_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
| 934 | *mpi_reply, Mpi2SasIOUnitPage0_t *config_page, u16 sz) | ||
| 935 | { | ||
| 936 | Mpi2ConfigRequest_t mpi_request; | ||
| 937 | int r; | ||
| 938 | |||
| 939 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
| 940 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
| 941 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
| 942 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | ||
| 943 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; | ||
| 944 | mpi_request.Header.PageNumber = 0; | ||
| 945 | mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION; | ||
| 946 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
| 947 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 948 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | ||
| 949 | if (r) | ||
| 950 | goto out; | ||
| 951 | |||
| 952 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
| 953 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 954 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); | ||
| 955 | out: | ||
| 956 | return r; | ||
| 957 | } | ||
| 958 | |||
| 959 | /** | ||
| 960 | * mpt2sas_config_get_sas_iounit_pg1 - obtain sas iounit page 1 | ||
| 961 | * @ioc: per adapter object | ||
| 962 | * @mpi_reply: reply mf payload returned from firmware | ||
| 963 | * @config_page: contents of the config page | ||
| 964 | * @sz: size of buffer passed in config_page | ||
| 965 | * Context: sleep. | ||
| 966 | * | ||
| 967 | * Calling function should call config_get_number_hba_phys prior to | ||
| 968 | * this function, so enough memory is allocated for config_page. | ||
| 969 | * | ||
| 970 | * Returns 0 for success, non-zero for failure. | ||
| 971 | */ | ||
| 972 | int | ||
| 973 | mpt2sas_config_get_sas_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
| 974 | *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, u16 sz) | ||
| 975 | { | ||
| 976 | Mpi2ConfigRequest_t mpi_request; | ||
| 977 | int r; | ||
| 978 | |||
| 979 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
| 980 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
| 981 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
| 982 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | ||
| 983 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; | ||
| 984 | mpi_request.Header.PageNumber = 1; | ||
| 985 | mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION; | ||
| 986 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
| 987 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 988 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | ||
| 989 | if (r) | ||
| 990 | goto out; | ||
| 991 | |||
| 992 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
| 993 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 994 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); | ||
| 995 | out: | ||
| 996 | return r; | ||
| 997 | } | ||
| 998 | |||
| 999 | /** | ||
| 1000 | * mpt2sas_config_set_sas_iounit_pg1 - send sas iounit page 1 | ||
| 1001 | * @ioc: per adapter object | ||
| 1002 | * @mpi_reply: reply mf payload returned from firmware | ||
| 1003 | * @config_page: contents of the config page | ||
| 1004 | * @sz: size of buffer passed in config_page | ||
| 1005 | * Context: sleep. | ||
| 1006 | * | ||
| 1007 | * Calling function should call config_get_number_hba_phys prior to | ||
| 1008 | * this function, so enough memory is allocated for config_page. | ||
| 1009 | * | ||
| 1010 | * Returns 0 for success, non-zero for failure. | ||
| 1011 | */ | ||
| 1012 | int | ||
| 1013 | mpt2sas_config_set_sas_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
| 1014 | *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, u16 sz) | ||
| 1015 | { | ||
| 1016 | Mpi2ConfigRequest_t mpi_request; | ||
| 1017 | int r; | ||
| 1018 | |||
| 1019 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
| 1020 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
| 1021 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
| 1022 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | ||
| 1023 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; | ||
| 1024 | mpi_request.Header.PageNumber = 1; | ||
| 1025 | mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION; | ||
| 1026 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
| 1027 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 1028 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | ||
| 1029 | if (r) | ||
| 1030 | goto out; | ||
| 1031 | |||
| 1032 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT; | ||
| 1033 | _config_request(ioc, &mpi_request, mpi_reply, | ||
| 1034 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); | ||
| 1035 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM; | ||
| 1036 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 1037 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); | ||
| 1038 | out: | ||
| 1039 | return r; | ||
| 1040 | } | ||
| 1041 | |||
| 1042 | /** | ||
| 1043 | * mpt2sas_config_get_expander_pg0 - obtain expander page 0 | ||
| 1044 | * @ioc: per adapter object | ||
| 1045 | * @mpi_reply: reply mf payload returned from firmware | ||
| 1046 | * @config_page: contents of the config page | ||
| 1047 | * @form: GET_NEXT_HANDLE or HANDLE | ||
| 1048 | * @handle: expander handle | ||
| 1049 | * Context: sleep. | ||
| 1050 | * | ||
| 1051 | * Returns 0 for success, non-zero for failure. | ||
| 1052 | */ | ||
| 1053 | int | ||
| 1054 | mpt2sas_config_get_expander_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
| 1055 | *mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle) | ||
| 1056 | { | ||
| 1057 | Mpi2ConfigRequest_t mpi_request; | ||
| 1058 | int r; | ||
| 1059 | |||
| 1060 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
| 1061 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
| 1062 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
| 1063 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | ||
| 1064 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER; | ||
| 1065 | mpi_request.Header.PageNumber = 0; | ||
| 1066 | mpi_request.Header.PageVersion = MPI2_SASEXPANDER0_PAGEVERSION; | ||
| 1067 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
| 1068 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 1069 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | ||
| 1070 | if (r) | ||
| 1071 | goto out; | ||
| 1072 | |||
| 1073 | mpi_request.PageAddress = cpu_to_le32(form | handle); | ||
| 1074 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
| 1075 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 1076 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | ||
| 1077 | sizeof(*config_page)); | ||
| 1078 | out: | ||
| 1079 | return r; | ||
| 1080 | } | ||
| 1081 | |||
| 1082 | /** | ||
| 1083 | * mpt2sas_config_get_expander_pg1 - obtain expander page 1 | ||
| 1084 | * @ioc: per adapter object | ||
| 1085 | * @mpi_reply: reply mf payload returned from firmware | ||
| 1086 | * @config_page: contents of the config page | ||
| 1087 | * @phy_number: phy number | ||
| 1088 | * @handle: expander handle | ||
| 1089 | * Context: sleep. | ||
| 1090 | * | ||
| 1091 | * Returns 0 for success, non-zero for failure. | ||
| 1092 | */ | ||
| 1093 | int | ||
| 1094 | mpt2sas_config_get_expander_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
| 1095 | *mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number, | ||
| 1096 | u16 handle) | ||
| 1097 | { | ||
| 1098 | Mpi2ConfigRequest_t mpi_request; | ||
| 1099 | int r; | ||
| 1100 | |||
| 1101 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
| 1102 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
| 1103 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
| 1104 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | ||
| 1105 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER; | ||
| 1106 | mpi_request.Header.PageNumber = 1; | ||
| 1107 | mpi_request.Header.PageVersion = MPI2_SASEXPANDER1_PAGEVERSION; | ||
| 1108 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
| 1109 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 1110 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | ||
| 1111 | if (r) | ||
| 1112 | goto out; | ||
| 1113 | |||
| 1114 | mpi_request.PageAddress = | ||
| 1115 | cpu_to_le32(MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM | | ||
| 1116 | (phy_number << MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | handle); | ||
| 1117 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
| 1118 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 1119 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | ||
| 1120 | sizeof(*config_page)); | ||
| 1121 | out: | ||
| 1122 | return r; | ||
| 1123 | } | ||
| 1124 | |||
| 1125 | /** | ||
| 1126 | * mpt2sas_config_get_enclosure_pg0 - obtain enclosure page 0 | ||
| 1127 | * @ioc: per adapter object | ||
| 1128 | * @mpi_reply: reply mf payload returned from firmware | ||
| 1129 | * @config_page: contents of the config page | ||
| 1130 | * @form: GET_NEXT_HANDLE or HANDLE | ||
| 1131 | * @handle: expander handle | ||
| 1132 | * Context: sleep. | ||
| 1133 | * | ||
| 1134 | * Returns 0 for success, non-zero for failure. | ||
| 1135 | */ | ||
| 1136 | int | ||
| 1137 | mpt2sas_config_get_enclosure_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
| 1138 | *mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle) | ||
| 1139 | { | ||
| 1140 | Mpi2ConfigRequest_t mpi_request; | ||
| 1141 | int r; | ||
| 1142 | |||
| 1143 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
| 1144 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
| 1145 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
| 1146 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | ||
| 1147 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE; | ||
| 1148 | mpi_request.Header.PageNumber = 0; | ||
| 1149 | mpi_request.Header.PageVersion = MPI2_SASENCLOSURE0_PAGEVERSION; | ||
| 1150 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
| 1151 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 1152 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | ||
| 1153 | if (r) | ||
| 1154 | goto out; | ||
| 1155 | |||
| 1156 | mpi_request.PageAddress = cpu_to_le32(form | handle); | ||
| 1157 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
| 1158 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 1159 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | ||
| 1160 | sizeof(*config_page)); | ||
| 1161 | out: | ||
| 1162 | return r; | ||
| 1163 | } | ||
| 1164 | |||
| 1165 | /** | ||
| 1166 | * mpt2sas_config_get_phy_pg0 - obtain phy page 0 | ||
| 1167 | * @ioc: per adapter object | ||
| 1168 | * @mpi_reply: reply mf payload returned from firmware | ||
| 1169 | * @config_page: contents of the config page | ||
| 1170 | * @phy_number: phy number | ||
| 1171 | * Context: sleep. | ||
| 1172 | * | ||
| 1173 | * Returns 0 for success, non-zero for failure. | ||
| 1174 | */ | ||
| 1175 | int | ||
| 1176 | mpt2sas_config_get_phy_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
| 1177 | *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number) | ||
| 1178 | { | ||
| 1179 | Mpi2ConfigRequest_t mpi_request; | ||
| 1180 | int r; | ||
| 1181 | |||
| 1182 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
| 1183 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
| 1184 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
| 1185 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | ||
| 1186 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY; | ||
| 1187 | mpi_request.Header.PageNumber = 0; | ||
| 1188 | mpi_request.Header.PageVersion = MPI2_SASPHY0_PAGEVERSION; | ||
| 1189 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
| 1190 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 1191 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | ||
| 1192 | if (r) | ||
| 1193 | goto out; | ||
| 1194 | |||
| 1195 | mpi_request.PageAddress = | ||
| 1196 | cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number); | ||
| 1197 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
| 1198 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 1199 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | ||
| 1200 | sizeof(*config_page)); | ||
| 1201 | out: | ||
| 1202 | return r; | ||
| 1203 | } | ||
| 1204 | |||
| 1205 | /** | ||
| 1206 | * mpt2sas_config_get_phy_pg1 - obtain phy page 1 | ||
| 1207 | * @ioc: per adapter object | ||
| 1208 | * @mpi_reply: reply mf payload returned from firmware | ||
| 1209 | * @config_page: contents of the config page | ||
| 1210 | * @phy_number: phy number | ||
| 1211 | * Context: sleep. | ||
| 1212 | * | ||
| 1213 | * Returns 0 for success, non-zero for failure. | ||
| 1214 | */ | ||
| 1215 | int | ||
| 1216 | mpt2sas_config_get_phy_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
| 1217 | *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number) | ||
| 1218 | { | ||
| 1219 | Mpi2ConfigRequest_t mpi_request; | ||
| 1220 | int r; | ||
| 1221 | |||
| 1222 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
| 1223 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
| 1224 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
| 1225 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | ||
| 1226 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY; | ||
| 1227 | mpi_request.Header.PageNumber = 1; | ||
| 1228 | mpi_request.Header.PageVersion = MPI2_SASPHY1_PAGEVERSION; | ||
| 1229 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
| 1230 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 1231 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | ||
| 1232 | if (r) | ||
| 1233 | goto out; | ||
| 1234 | |||
| 1235 | mpi_request.PageAddress = | ||
| 1236 | cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number); | ||
| 1237 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
| 1238 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 1239 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | ||
| 1240 | sizeof(*config_page)); | ||
| 1241 | out: | ||
| 1242 | return r; | ||
| 1243 | } | ||
| 1244 | |||
| 1245 | /** | ||
| 1246 | * mpt2sas_config_get_raid_volume_pg1 - obtain raid volume page 1 | ||
| 1247 | * @ioc: per adapter object | ||
| 1248 | * @mpi_reply: reply mf payload returned from firmware | ||
| 1249 | * @config_page: contents of the config page | ||
| 1250 | * @form: GET_NEXT_HANDLE or HANDLE | ||
| 1251 | * @handle: volume handle | ||
| 1252 | * Context: sleep. | ||
| 1253 | * | ||
| 1254 | * Returns 0 for success, non-zero for failure. | ||
| 1255 | */ | ||
| 1256 | int | ||
| 1257 | mpt2sas_config_get_raid_volume_pg1(struct MPT2SAS_ADAPTER *ioc, | ||
| 1258 | Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, | ||
| 1259 | u32 handle) | ||
| 1260 | { | ||
| 1261 | Mpi2ConfigRequest_t mpi_request; | ||
| 1262 | int r; | ||
| 1263 | |||
| 1264 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
| 1265 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
| 1266 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
| 1267 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; | ||
| 1268 | mpi_request.Header.PageNumber = 1; | ||
| 1269 | mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION; | ||
| 1270 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
| 1271 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 1272 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | ||
| 1273 | if (r) | ||
| 1274 | goto out; | ||
| 1275 | |||
| 1276 | mpi_request.PageAddress = cpu_to_le32(form | handle); | ||
| 1277 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
| 1278 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 1279 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | ||
| 1280 | sizeof(*config_page)); | ||
| 1281 | out: | ||
| 1282 | return r; | ||
| 1283 | } | ||
| 1284 | |||
| 1285 | /** | ||
| 1286 | * mpt2sas_config_get_number_pds - obtain number of phys disk assigned to volume | ||
| 1287 | * @ioc: per adapter object | ||
| 1288 | * @handle: volume handle | ||
| 1289 | * @num_pds: returns pds count | ||
| 1290 | * Context: sleep. | ||
| 1291 | * | ||
| 1292 | * Returns 0 for success, non-zero for failure. | ||
| 1293 | */ | ||
| 1294 | int | ||
| 1295 | mpt2sas_config_get_number_pds(struct MPT2SAS_ADAPTER *ioc, u16 handle, | ||
| 1296 | u8 *num_pds) | ||
| 1297 | { | ||
| 1298 | Mpi2ConfigRequest_t mpi_request; | ||
| 1299 | Mpi2RaidVolPage0_t config_page; | ||
| 1300 | Mpi2ConfigReply_t mpi_reply; | ||
| 1301 | int r; | ||
| 1302 | u16 ioc_status; | ||
| 1303 | |||
| 1304 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
| 1305 | *num_pds = 0; | ||
| 1306 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
| 1307 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
| 1308 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; | ||
| 1309 | mpi_request.Header.PageNumber = 0; | ||
| 1310 | mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION; | ||
| 1311 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
| 1312 | r = _config_request(ioc, &mpi_request, &mpi_reply, | ||
| 1313 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | ||
| 1314 | if (r) | ||
| 1315 | goto out; | ||
| 1316 | |||
| 1317 | mpi_request.PageAddress = | ||
| 1318 | cpu_to_le32(MPI2_RAID_VOLUME_PGAD_FORM_HANDLE | handle); | ||
| 1319 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
| 1320 | r = _config_request(ioc, &mpi_request, &mpi_reply, | ||
| 1321 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page, | ||
| 1322 | sizeof(Mpi2RaidVolPage0_t)); | ||
| 1323 | if (!r) { | ||
| 1324 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
| 1325 | MPI2_IOCSTATUS_MASK; | ||
| 1326 | if (ioc_status == MPI2_IOCSTATUS_SUCCESS) | ||
| 1327 | *num_pds = config_page.NumPhysDisks; | ||
| 1328 | } | ||
| 1329 | |||
| 1330 | out: | ||
| 1331 | return r; | ||
| 1332 | } | ||
| 1333 | |||
| 1334 | /** | ||
| 1335 | * mpt2sas_config_get_raid_volume_pg0 - obtain raid volume page 0 | ||
| 1336 | * @ioc: per adapter object | ||
| 1337 | * @mpi_reply: reply mf payload returned from firmware | ||
| 1338 | * @config_page: contents of the config page | ||
| 1339 | * @form: GET_NEXT_HANDLE or HANDLE | ||
| 1340 | * @handle: volume handle | ||
| 1341 | * @sz: size of buffer passed in config_page | ||
| 1342 | * Context: sleep. | ||
| 1343 | * | ||
| 1344 | * Returns 0 for success, non-zero for failure. | ||
| 1345 | */ | ||
| 1346 | int | ||
| 1347 | mpt2sas_config_get_raid_volume_pg0(struct MPT2SAS_ADAPTER *ioc, | ||
| 1348 | Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form, | ||
| 1349 | u32 handle, u16 sz) | ||
| 1350 | { | ||
| 1351 | Mpi2ConfigRequest_t mpi_request; | ||
| 1352 | int r; | ||
| 1353 | |||
| 1354 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
| 1355 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
| 1356 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
| 1357 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; | ||
| 1358 | mpi_request.Header.PageNumber = 0; | ||
| 1359 | mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION; | ||
| 1360 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
| 1361 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 1362 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | ||
| 1363 | if (r) | ||
| 1364 | goto out; | ||
| 1365 | |||
| 1366 | mpi_request.PageAddress = cpu_to_le32(form | handle); | ||
| 1367 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
| 1368 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 1369 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); | ||
| 1370 | out: | ||
| 1371 | return r; | ||
| 1372 | } | ||
| 1373 | |||
| 1374 | /** | ||
| 1375 | * mpt2sas_config_get_phys_disk_pg0 - obtain phys disk page 0 | ||
| 1376 | * @ioc: per adapter object | ||
| 1377 | * @mpi_reply: reply mf payload returned from firmware | ||
| 1378 | * @config_page: contents of the config page | ||
| 1379 | * @form: GET_NEXT_PHYSDISKNUM, PHYSDISKNUM, DEVHANDLE | ||
| 1380 | * @form_specific: specific to the form | ||
| 1381 | * Context: sleep. | ||
| 1382 | * | ||
| 1383 | * Returns 0 for success, non-zero for failure. | ||
| 1384 | */ | ||
| 1385 | int | ||
| 1386 | mpt2sas_config_get_phys_disk_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
| 1387 | *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form, | ||
| 1388 | u32 form_specific) | ||
| 1389 | { | ||
| 1390 | Mpi2ConfigRequest_t mpi_request; | ||
| 1391 | int r; | ||
| 1392 | |||
| 1393 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
| 1394 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
| 1395 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
| 1396 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK; | ||
| 1397 | mpi_request.Header.PageNumber = 0; | ||
| 1398 | mpi_request.Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION; | ||
| 1399 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
| 1400 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 1401 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | ||
| 1402 | if (r) | ||
| 1403 | goto out; | ||
| 1404 | |||
| 1405 | mpi_request.PageAddress = cpu_to_le32(form | form_specific); | ||
| 1406 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
| 1407 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 1408 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | ||
| 1409 | sizeof(*config_page)); | ||
| 1410 | out: | ||
| 1411 | return r; | ||
| 1412 | } | ||
| 1413 | |||
| 1414 | /** | ||
| 1415 | * mpt2sas_config_get_volume_handle - returns volume handle for give hidden raid components | ||
| 1416 | * @ioc: per adapter object | ||
| 1417 | * @pd_handle: phys disk handle | ||
| 1418 | * @volume_handle: volume handle | ||
| 1419 | * Context: sleep. | ||
| 1420 | * | ||
| 1421 | * Returns 0 for success, non-zero for failure. | ||
| 1422 | */ | ||
| 1423 | int | ||
| 1424 | mpt2sas_config_get_volume_handle(struct MPT2SAS_ADAPTER *ioc, u16 pd_handle, | ||
| 1425 | u16 *volume_handle) | ||
| 1426 | { | ||
| 1427 | Mpi2RaidConfigurationPage0_t *config_page = NULL; | ||
| 1428 | Mpi2ConfigRequest_t mpi_request; | ||
| 1429 | Mpi2ConfigReply_t mpi_reply; | ||
| 1430 | int r, i, config_page_sz; | ||
| 1431 | u16 ioc_status; | ||
| 1432 | int config_num; | ||
| 1433 | u16 element_type; | ||
| 1434 | u16 phys_disk_dev_handle; | ||
| 1435 | |||
| 1436 | *volume_handle = 0; | ||
| 1437 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
| 1438 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
| 1439 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
| 1440 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | ||
| 1441 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG; | ||
| 1442 | mpi_request.Header.PageVersion = MPI2_RAIDCONFIG0_PAGEVERSION; | ||
| 1443 | mpi_request.Header.PageNumber = 0; | ||
| 1444 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
| 1445 | r = _config_request(ioc, &mpi_request, &mpi_reply, | ||
| 1446 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | ||
| 1447 | if (r) | ||
| 1448 | goto out; | ||
| 1449 | |||
| 1450 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
| 1451 | config_page_sz = (le16_to_cpu(mpi_reply.ExtPageLength) * 4); | ||
| 1452 | config_page = kmalloc(config_page_sz, GFP_KERNEL); | ||
| 1453 | if (!config_page) { | ||
| 1454 | r = -1; | ||
| 1455 | goto out; | ||
| 1456 | } | ||
| 1457 | config_num = 0xff; | ||
| 1458 | while (1) { | ||
| 1459 | mpi_request.PageAddress = cpu_to_le32(config_num + | ||
| 1460 | MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM); | ||
| 1461 | r = _config_request(ioc, &mpi_request, &mpi_reply, | ||
| 1462 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | ||
| 1463 | config_page_sz); | ||
| 1464 | if (r) | ||
| 1465 | goto out; | ||
| 1466 | r = -1; | ||
| 1467 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
| 1468 | MPI2_IOCSTATUS_MASK; | ||
| 1469 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) | ||
| 1470 | goto out; | ||
| 1471 | for (i = 0; i < config_page->NumElements; i++) { | ||
| 1472 | element_type = le16_to_cpu(config_page-> | ||
| 1473 | ConfigElement[i].ElementFlags) & | ||
| 1474 | MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE; | ||
| 1475 | if (element_type == | ||
| 1476 | MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT || | ||
| 1477 | element_type == | ||
| 1478 | MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT) { | ||
| 1479 | phys_disk_dev_handle = | ||
| 1480 | le16_to_cpu(config_page->ConfigElement[i]. | ||
| 1481 | PhysDiskDevHandle); | ||
| 1482 | if (phys_disk_dev_handle == pd_handle) { | ||
| 1483 | *volume_handle = | ||
| 1484 | le16_to_cpu(config_page-> | ||
| 1485 | ConfigElement[i].VolDevHandle); | ||
| 1486 | r = 0; | ||
| 1487 | goto out; | ||
| 1488 | } | ||
| 1489 | } else if (element_type == | ||
| 1490 | MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT) { | ||
| 1491 | *volume_handle = 0; | ||
| 1492 | r = 0; | ||
| 1493 | goto out; | ||
| 1494 | } | ||
| 1495 | } | ||
| 1496 | config_num = config_page->ConfigNum; | ||
| 1497 | } | ||
| 1498 | out: | ||
| 1499 | kfree(config_page); | ||
| 1500 | return r; | ||
| 1501 | } | ||
| 1502 | |||
| 1503 | /** | ||
| 1504 | * mpt2sas_config_get_volume_wwid - returns wwid given the volume handle | ||
| 1505 | * @ioc: per adapter object | ||
| 1506 | * @volume_handle: volume handle | ||
| 1507 | * @wwid: volume wwid | ||
| 1508 | * Context: sleep. | ||
| 1509 | * | ||
| 1510 | * Returns 0 for success, non-zero for failure. | ||
| 1511 | */ | ||
| 1512 | int | ||
| 1513 | mpt2sas_config_get_volume_wwid(struct MPT2SAS_ADAPTER *ioc, u16 volume_handle, | ||
| 1514 | u64 *wwid) | ||
| 1515 | { | ||
| 1516 | Mpi2ConfigReply_t mpi_reply; | ||
| 1517 | Mpi2RaidVolPage1_t raid_vol_pg1; | ||
| 1518 | |||
| 1519 | *wwid = 0; | ||
| 1520 | if (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply, | ||
| 1521 | &raid_vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, | ||
| 1522 | volume_handle))) { | ||
| 1523 | *wwid = le64_to_cpu(raid_vol_pg1.WWID); | ||
| 1524 | return 0; | ||
| 1525 | } else | ||
| 1526 | return -1; | ||
| 1527 | } | ||
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c deleted file mode 100644 index 3694b63bd993..000000000000 --- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c +++ /dev/null | |||
| @@ -1,3101 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Management Module Support for MPT (Message Passing Technology) based | ||
| 3 | * controllers | ||
| 4 | * | ||
| 5 | * This code is based on drivers/scsi/mpt2sas/mpt2_ctl.c | ||
| 6 | * Copyright (C) 2007-2014 LSI Corporation | ||
| 7 | * Copyright (C) 20013-2014 Avago Technologies | ||
| 8 | * (mailto: MPT-FusionLinux.pdl@avagotech.com) | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or | ||
| 11 | * modify it under the terms of the GNU General Public License | ||
| 12 | * as published by the Free Software Foundation; either version 2 | ||
| 13 | * of the License, or (at your option) any later version. | ||
| 14 | * | ||
| 15 | * This program is distributed in the hope that it will be useful, | ||
| 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | * GNU General Public License for more details. | ||
| 19 | * | ||
| 20 | * NO WARRANTY | ||
| 21 | * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR | ||
| 22 | * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT | ||
| 23 | * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, | ||
| 24 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is | ||
| 25 | * solely responsible for determining the appropriateness of using and | ||
| 26 | * distributing the Program and assumes all risks associated with its | ||
| 27 | * exercise of rights under this Agreement, including but not limited to | ||
| 28 | * the risks and costs of program errors, damage to or loss of data, | ||
| 29 | * programs or equipment, and unavailability or interruption of operations. | ||
| 30 | |||
| 31 | * DISCLAIMER OF LIABILITY | ||
| 32 | * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY | ||
| 33 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 34 | * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND | ||
| 35 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR | ||
| 36 | * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | ||
| 37 | * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED | ||
| 38 | * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES | ||
| 39 | |||
| 40 | * You should have received a copy of the GNU General Public License | ||
| 41 | * along with this program; if not, write to the Free Software | ||
| 42 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
| 43 | * USA. | ||
| 44 | */ | ||
| 45 | |||
| 46 | #include <linux/kernel.h> | ||
| 47 | #include <linux/module.h> | ||
| 48 | #include <linux/errno.h> | ||
| 49 | #include <linux/init.h> | ||
| 50 | #include <linux/slab.h> | ||
| 51 | #include <linux/types.h> | ||
| 52 | #include <linux/pci.h> | ||
| 53 | #include <linux/delay.h> | ||
| 54 | #include <linux/mutex.h> | ||
| 55 | #include <linux/compat.h> | ||
| 56 | #include <linux/poll.h> | ||
| 57 | |||
| 58 | #include <linux/io.h> | ||
| 59 | #include <linux/uaccess.h> | ||
| 60 | |||
| 61 | #include "mpt2sas_base.h" | ||
| 62 | #include "mpt2sas_ctl.h" | ||
| 63 | |||
| 64 | static DEFINE_MUTEX(_ctl_mutex); | ||
| 65 | static struct fasync_struct *async_queue; | ||
| 66 | static DECLARE_WAIT_QUEUE_HEAD(ctl_poll_wait); | ||
| 67 | |||
| 68 | static int _ctl_send_release(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type, | ||
| 69 | u8 *issue_reset); | ||
| 70 | |||
| 71 | /** | ||
| 72 | * enum block_state - blocking state | ||
| 73 | * @NON_BLOCKING: non blocking | ||
| 74 | * @BLOCKING: blocking | ||
| 75 | * | ||
| 76 | * These states are for ioctls that need to wait for a response | ||
| 77 | * from firmware, so they probably require sleep. | ||
| 78 | */ | ||
| 79 | enum block_state { | ||
| 80 | NON_BLOCKING, | ||
| 81 | BLOCKING, | ||
| 82 | }; | ||
| 83 | |||
| 84 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | ||
| 85 | /** | ||
| 86 | * _ctl_sas_device_find_by_handle - sas device search | ||
| 87 | * @ioc: per adapter object | ||
| 88 | * @handle: sas device handle (assigned by firmware) | ||
| 89 | * Context: Calling function should acquire ioc->sas_device_lock | ||
| 90 | * | ||
| 91 | * This searches for sas_device based on sas_address, then return sas_device | ||
| 92 | * object. | ||
| 93 | */ | ||
| 94 | static struct _sas_device * | ||
| 95 | _ctl_sas_device_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle) | ||
| 96 | { | ||
| 97 | struct _sas_device *sas_device, *r; | ||
| 98 | |||
| 99 | r = NULL; | ||
| 100 | list_for_each_entry(sas_device, &ioc->sas_device_list, list) { | ||
| 101 | if (sas_device->handle != handle) | ||
| 102 | continue; | ||
| 103 | r = sas_device; | ||
| 104 | goto out; | ||
| 105 | } | ||
| 106 | |||
| 107 | out: | ||
| 108 | return r; | ||
| 109 | } | ||
| 110 | |||
| 111 | /** | ||
| 112 | * _ctl_display_some_debug - debug routine | ||
| 113 | * @ioc: per adapter object | ||
| 114 | * @smid: system request message index | ||
| 115 | * @calling_function_name: string pass from calling function | ||
| 116 | * @mpi_reply: reply message frame | ||
| 117 | * Context: none. | ||
| 118 | * | ||
| 119 | * Function for displaying debug info helpful when debugging issues | ||
| 120 | * in this module. | ||
| 121 | */ | ||
| 122 | static void | ||
| 123 | _ctl_display_some_debug(struct MPT2SAS_ADAPTER *ioc, u16 smid, | ||
| 124 | char *calling_function_name, MPI2DefaultReply_t *mpi_reply) | ||
| 125 | { | ||
| 126 | Mpi2ConfigRequest_t *mpi_request; | ||
| 127 | char *desc = NULL; | ||
| 128 | |||
| 129 | if (!(ioc->logging_level & MPT_DEBUG_IOCTL)) | ||
| 130 | return; | ||
| 131 | |||
| 132 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); | ||
| 133 | switch (mpi_request->Function) { | ||
| 134 | case MPI2_FUNCTION_SCSI_IO_REQUEST: | ||
| 135 | { | ||
| 136 | Mpi2SCSIIORequest_t *scsi_request = | ||
| 137 | (Mpi2SCSIIORequest_t *)mpi_request; | ||
| 138 | |||
| 139 | snprintf(ioc->tmp_string, MPT_STRING_LENGTH, | ||
| 140 | "scsi_io, cmd(0x%02x), cdb_len(%d)", | ||
| 141 | scsi_request->CDB.CDB32[0], | ||
| 142 | le16_to_cpu(scsi_request->IoFlags) & 0xF); | ||
| 143 | desc = ioc->tmp_string; | ||
| 144 | break; | ||
| 145 | } | ||
| 146 | case MPI2_FUNCTION_SCSI_TASK_MGMT: | ||
| 147 | desc = "task_mgmt"; | ||
| 148 | break; | ||
| 149 | case MPI2_FUNCTION_IOC_INIT: | ||
| 150 | desc = "ioc_init"; | ||
| 151 | break; | ||
| 152 | case MPI2_FUNCTION_IOC_FACTS: | ||
| 153 | desc = "ioc_facts"; | ||
| 154 | break; | ||
| 155 | case MPI2_FUNCTION_CONFIG: | ||
| 156 | { | ||
| 157 | Mpi2ConfigRequest_t *config_request = | ||
| 158 | (Mpi2ConfigRequest_t *)mpi_request; | ||
| 159 | |||
| 160 | snprintf(ioc->tmp_string, MPT_STRING_LENGTH, | ||
| 161 | "config, type(0x%02x), ext_type(0x%02x), number(%d)", | ||
| 162 | (config_request->Header.PageType & | ||
| 163 | MPI2_CONFIG_PAGETYPE_MASK), config_request->ExtPageType, | ||
| 164 | config_request->Header.PageNumber); | ||
| 165 | desc = ioc->tmp_string; | ||
| 166 | break; | ||
| 167 | } | ||
| 168 | case MPI2_FUNCTION_PORT_FACTS: | ||
| 169 | desc = "port_facts"; | ||
| 170 | break; | ||
| 171 | case MPI2_FUNCTION_PORT_ENABLE: | ||
| 172 | desc = "port_enable"; | ||
| 173 | break; | ||
| 174 | case MPI2_FUNCTION_EVENT_NOTIFICATION: | ||
| 175 | desc = "event_notification"; | ||
| 176 | break; | ||
| 177 | case MPI2_FUNCTION_FW_DOWNLOAD: | ||
| 178 | desc = "fw_download"; | ||
| 179 | break; | ||
| 180 | case MPI2_FUNCTION_FW_UPLOAD: | ||
| 181 | desc = "fw_upload"; | ||
| 182 | break; | ||
| 183 | case MPI2_FUNCTION_RAID_ACTION: | ||
| 184 | desc = "raid_action"; | ||
| 185 | break; | ||
| 186 | case MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH: | ||
| 187 | { | ||
| 188 | Mpi2SCSIIORequest_t *scsi_request = | ||
| 189 | (Mpi2SCSIIORequest_t *)mpi_request; | ||
| 190 | |||
| 191 | snprintf(ioc->tmp_string, MPT_STRING_LENGTH, | ||
| 192 | "raid_pass, cmd(0x%02x), cdb_len(%d)", | ||
| 193 | scsi_request->CDB.CDB32[0], | ||
| 194 | le16_to_cpu(scsi_request->IoFlags) & 0xF); | ||
| 195 | desc = ioc->tmp_string; | ||
| 196 | break; | ||
| 197 | } | ||
| 198 | case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL: | ||
| 199 | desc = "sas_iounit_cntl"; | ||
| 200 | break; | ||
| 201 | case MPI2_FUNCTION_SATA_PASSTHROUGH: | ||
| 202 | desc = "sata_pass"; | ||
| 203 | break; | ||
| 204 | case MPI2_FUNCTION_DIAG_BUFFER_POST: | ||
| 205 | desc = "diag_buffer_post"; | ||
| 206 | break; | ||
| 207 | case MPI2_FUNCTION_DIAG_RELEASE: | ||
| 208 | desc = "diag_release"; | ||
| 209 | break; | ||
| 210 | case MPI2_FUNCTION_SMP_PASSTHROUGH: | ||
| 211 | desc = "smp_passthrough"; | ||
| 212 | break; | ||
| 213 | } | ||
| 214 | |||
| 215 | if (!desc) | ||
| 216 | return; | ||
| 217 | |||
| 218 | printk(MPT2SAS_INFO_FMT "%s: %s, smid(%d)\n", | ||
| 219 | ioc->name, calling_function_name, desc, smid); | ||
| 220 | |||
| 221 | if (!mpi_reply) | ||
| 222 | return; | ||
| 223 | |||
| 224 | if (mpi_reply->IOCStatus || mpi_reply->IOCLogInfo) | ||
| 225 | printk(MPT2SAS_INFO_FMT | ||
| 226 | "\tiocstatus(0x%04x), loginfo(0x%08x)\n", | ||
| 227 | ioc->name, le16_to_cpu(mpi_reply->IOCStatus), | ||
| 228 | le32_to_cpu(mpi_reply->IOCLogInfo)); | ||
| 229 | |||
| 230 | if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST || | ||
| 231 | mpi_request->Function == | ||
| 232 | MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) { | ||
| 233 | Mpi2SCSIIOReply_t *scsi_reply = | ||
| 234 | (Mpi2SCSIIOReply_t *)mpi_reply; | ||
| 235 | struct _sas_device *sas_device = NULL; | ||
| 236 | unsigned long flags; | ||
| 237 | |||
| 238 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 239 | sas_device = _ctl_sas_device_find_by_handle(ioc, | ||
| 240 | le16_to_cpu(scsi_reply->DevHandle)); | ||
| 241 | if (sas_device) { | ||
| 242 | printk(MPT2SAS_WARN_FMT "\tsas_address(0x%016llx), " | ||
| 243 | "phy(%d)\n", ioc->name, (unsigned long long) | ||
| 244 | sas_device->sas_address, sas_device->phy); | ||
| 245 | printk(MPT2SAS_WARN_FMT | ||
| 246 | "\tenclosure_logical_id(0x%016llx), slot(%d)\n", | ||
| 247 | ioc->name, sas_device->enclosure_logical_id, | ||
| 248 | sas_device->slot); | ||
| 249 | } | ||
| 250 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 251 | if (scsi_reply->SCSIState || scsi_reply->SCSIStatus) | ||
| 252 | printk(MPT2SAS_INFO_FMT | ||
| 253 | "\tscsi_state(0x%02x), scsi_status" | ||
| 254 | "(0x%02x)\n", ioc->name, | ||
| 255 | scsi_reply->SCSIState, | ||
| 256 | scsi_reply->SCSIStatus); | ||
| 257 | } | ||
| 258 | } | ||
| 259 | #endif | ||
| 260 | |||
| 261 | /** | ||
| 262 | * mpt2sas_ctl_done - ctl module completion routine | ||
| 263 | * @ioc: per adapter object | ||
| 264 | * @smid: system request message index | ||
| 265 | * @msix_index: MSIX table index supplied by the OS | ||
| 266 | * @reply: reply message frame(lower 32bit addr) | ||
| 267 | * Context: none. | ||
| 268 | * | ||
| 269 | * The callback handler when using ioc->ctl_cb_idx. | ||
| 270 | * | ||
| 271 | * Return 1 meaning mf should be freed from _base_interrupt | ||
| 272 | * 0 means the mf is freed from this function. | ||
| 273 | */ | ||
| 274 | u8 | ||
| 275 | mpt2sas_ctl_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | ||
| 276 | u32 reply) | ||
| 277 | { | ||
| 278 | MPI2DefaultReply_t *mpi_reply; | ||
| 279 | Mpi2SCSIIOReply_t *scsiio_reply; | ||
| 280 | const void *sense_data; | ||
| 281 | u32 sz; | ||
| 282 | |||
| 283 | if (ioc->ctl_cmds.status == MPT2_CMD_NOT_USED) | ||
| 284 | return 1; | ||
| 285 | if (ioc->ctl_cmds.smid != smid) | ||
| 286 | return 1; | ||
| 287 | ioc->ctl_cmds.status |= MPT2_CMD_COMPLETE; | ||
| 288 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | ||
| 289 | if (mpi_reply) { | ||
| 290 | memcpy(ioc->ctl_cmds.reply, mpi_reply, mpi_reply->MsgLength*4); | ||
| 291 | ioc->ctl_cmds.status |= MPT2_CMD_REPLY_VALID; | ||
| 292 | /* get sense data */ | ||
| 293 | if (mpi_reply->Function == MPI2_FUNCTION_SCSI_IO_REQUEST || | ||
| 294 | mpi_reply->Function == | ||
| 295 | MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) { | ||
| 296 | scsiio_reply = (Mpi2SCSIIOReply_t *)mpi_reply; | ||
| 297 | if (scsiio_reply->SCSIState & | ||
| 298 | MPI2_SCSI_STATE_AUTOSENSE_VALID) { | ||
| 299 | sz = min_t(u32, SCSI_SENSE_BUFFERSIZE, | ||
| 300 | le32_to_cpu(scsiio_reply->SenseCount)); | ||
| 301 | sense_data = mpt2sas_base_get_sense_buffer(ioc, | ||
| 302 | smid); | ||
| 303 | memcpy(ioc->ctl_cmds.sense, sense_data, sz); | ||
| 304 | } | ||
| 305 | } | ||
| 306 | } | ||
| 307 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | ||
| 308 | _ctl_display_some_debug(ioc, smid, "ctl_done", mpi_reply); | ||
| 309 | #endif | ||
| 310 | ioc->ctl_cmds.status &= ~MPT2_CMD_PENDING; | ||
| 311 | complete(&ioc->ctl_cmds.done); | ||
| 312 | return 1; | ||
| 313 | } | ||
| 314 | |||
| 315 | /** | ||
| 316 | * _ctl_check_event_type - determines when an event needs logging | ||
| 317 | * @ioc: per adapter object | ||
| 318 | * @event: firmware event | ||
| 319 | * | ||
| 320 | * The bitmask in ioc->event_type[] indicates which events should be | ||
| 321 | * be saved in the driver event_log. This bitmask is set by application. | ||
| 322 | * | ||
| 323 | * Returns 1 when event should be captured, or zero means no match. | ||
| 324 | */ | ||
| 325 | static int | ||
| 326 | _ctl_check_event_type(struct MPT2SAS_ADAPTER *ioc, u16 event) | ||
| 327 | { | ||
| 328 | u16 i; | ||
| 329 | u32 desired_event; | ||
| 330 | |||
| 331 | if (event >= 128 || !event || !ioc->event_log) | ||
| 332 | return 0; | ||
| 333 | |||
| 334 | desired_event = (1 << (event % 32)); | ||
| 335 | if (!desired_event) | ||
| 336 | desired_event = 1; | ||
| 337 | i = event / 32; | ||
| 338 | return desired_event & ioc->event_type[i]; | ||
| 339 | } | ||
| 340 | |||
| 341 | /** | ||
| 342 | * mpt2sas_ctl_add_to_event_log - add event | ||
| 343 | * @ioc: per adapter object | ||
| 344 | * @mpi_reply: reply message frame | ||
| 345 | * | ||
| 346 | * Return nothing. | ||
| 347 | */ | ||
| 348 | void | ||
| 349 | mpt2sas_ctl_add_to_event_log(struct MPT2SAS_ADAPTER *ioc, | ||
| 350 | Mpi2EventNotificationReply_t *mpi_reply) | ||
| 351 | { | ||
| 352 | struct MPT2_IOCTL_EVENTS *event_log; | ||
| 353 | u16 event; | ||
| 354 | int i; | ||
| 355 | u32 sz, event_data_sz; | ||
| 356 | u8 send_aen = 0; | ||
| 357 | |||
| 358 | if (!ioc->event_log) | ||
| 359 | return; | ||
| 360 | |||
| 361 | event = le16_to_cpu(mpi_reply->Event); | ||
| 362 | |||
| 363 | if (_ctl_check_event_type(ioc, event)) { | ||
| 364 | |||
| 365 | /* insert entry into circular event_log */ | ||
| 366 | i = ioc->event_context % MPT2SAS_CTL_EVENT_LOG_SIZE; | ||
| 367 | event_log = ioc->event_log; | ||
| 368 | event_log[i].event = event; | ||
| 369 | event_log[i].context = ioc->event_context++; | ||
| 370 | |||
| 371 | event_data_sz = le16_to_cpu(mpi_reply->EventDataLength)*4; | ||
| 372 | sz = min_t(u32, event_data_sz, MPT2_EVENT_DATA_SIZE); | ||
| 373 | memset(event_log[i].data, 0, MPT2_EVENT_DATA_SIZE); | ||
| 374 | memcpy(event_log[i].data, mpi_reply->EventData, sz); | ||
| 375 | send_aen = 1; | ||
| 376 | } | ||
| 377 | |||
| 378 | /* This aen_event_read_flag flag is set until the | ||
| 379 | * application has read the event log. | ||
| 380 | * For MPI2_EVENT_LOG_ENTRY_ADDED, we always notify. | ||
| 381 | */ | ||
| 382 | if (event == MPI2_EVENT_LOG_ENTRY_ADDED || | ||
| 383 | (send_aen && !ioc->aen_event_read_flag)) { | ||
| 384 | ioc->aen_event_read_flag = 1; | ||
| 385 | wake_up_interruptible(&ctl_poll_wait); | ||
| 386 | if (async_queue) | ||
| 387 | kill_fasync(&async_queue, SIGIO, POLL_IN); | ||
| 388 | } | ||
| 389 | } | ||
| 390 | |||
| 391 | /** | ||
| 392 | * mpt2sas_ctl_event_callback - firmware event handler (called at ISR time) | ||
| 393 | * @ioc: per adapter object | ||
| 394 | * @msix_index: MSIX table index supplied by the OS | ||
| 395 | * @reply: reply message frame(lower 32bit addr) | ||
| 396 | * Context: interrupt. | ||
| 397 | * | ||
| 398 | * This function merely adds a new work task into ioc->firmware_event_thread. | ||
| 399 | * The tasks are worked from _firmware_event_work in user context. | ||
| 400 | * | ||
| 401 | * Returns void. | ||
| 402 | */ | ||
| 403 | void | ||
| 404 | mpt2sas_ctl_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, | ||
| 405 | u32 reply) | ||
| 406 | { | ||
| 407 | Mpi2EventNotificationReply_t *mpi_reply; | ||
| 408 | |||
| 409 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | ||
| 410 | if (unlikely(!mpi_reply)) { | ||
| 411 | printk(MPT2SAS_ERR_FMT "mpi_reply not valid at %s:%d/%s()!\n", | ||
| 412 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 413 | return; | ||
| 414 | } | ||
| 415 | mpt2sas_ctl_add_to_event_log(ioc, mpi_reply); | ||
| 416 | return; | ||
| 417 | } | ||
| 418 | |||
| 419 | /** | ||
| 420 | * _ctl_verify_adapter - validates ioc_number passed from application | ||
| 421 | * @ioc: per adapter object | ||
| 422 | * @iocpp: The ioc pointer is returned in this. | ||
| 423 | * | ||
| 424 | * Return (-1) means error, else ioc_number. | ||
| 425 | */ | ||
| 426 | static int | ||
| 427 | _ctl_verify_adapter(int ioc_number, struct MPT2SAS_ADAPTER **iocpp) | ||
| 428 | { | ||
| 429 | struct MPT2SAS_ADAPTER *ioc; | ||
| 430 | /* global ioc lock to protect controller on list operations */ | ||
| 431 | spin_lock(&gioc_lock); | ||
| 432 | list_for_each_entry(ioc, &mpt2sas_ioc_list, list) { | ||
| 433 | if (ioc->id != ioc_number) | ||
| 434 | continue; | ||
| 435 | spin_unlock(&gioc_lock); | ||
| 436 | *iocpp = ioc; | ||
| 437 | return ioc_number; | ||
| 438 | } | ||
| 439 | spin_unlock(&gioc_lock); | ||
| 440 | *iocpp = NULL; | ||
| 441 | return -1; | ||
| 442 | } | ||
| 443 | |||
| 444 | /** | ||
| 445 | * mpt2sas_ctl_reset_handler - reset callback handler (for ctl) | ||
| 446 | * @ioc: per adapter object | ||
| 447 | * @reset_phase: phase | ||
| 448 | * | ||
| 449 | * The handler for doing any required cleanup or initialization. | ||
| 450 | * | ||
| 451 | * The reset phase can be MPT2_IOC_PRE_RESET, MPT2_IOC_AFTER_RESET, | ||
| 452 | * MPT2_IOC_DONE_RESET | ||
| 453 | */ | ||
| 454 | void | ||
| 455 | mpt2sas_ctl_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase) | ||
| 456 | { | ||
| 457 | int i; | ||
| 458 | u8 issue_reset; | ||
| 459 | |||
| 460 | switch (reset_phase) { | ||
| 461 | case MPT2_IOC_PRE_RESET: | ||
| 462 | dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " | ||
| 463 | "MPT2_IOC_PRE_RESET\n", ioc->name, __func__)); | ||
| 464 | for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) { | ||
| 465 | if (!(ioc->diag_buffer_status[i] & | ||
| 466 | MPT2_DIAG_BUFFER_IS_REGISTERED)) | ||
| 467 | continue; | ||
| 468 | if ((ioc->diag_buffer_status[i] & | ||
| 469 | MPT2_DIAG_BUFFER_IS_RELEASED)) | ||
| 470 | continue; | ||
| 471 | _ctl_send_release(ioc, i, &issue_reset); | ||
| 472 | } | ||
| 473 | break; | ||
| 474 | case MPT2_IOC_AFTER_RESET: | ||
| 475 | dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " | ||
| 476 | "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__)); | ||
| 477 | if (ioc->ctl_cmds.status & MPT2_CMD_PENDING) { | ||
| 478 | ioc->ctl_cmds.status |= MPT2_CMD_RESET; | ||
| 479 | mpt2sas_base_free_smid(ioc, ioc->ctl_cmds.smid); | ||
| 480 | complete(&ioc->ctl_cmds.done); | ||
| 481 | } | ||
| 482 | break; | ||
| 483 | case MPT2_IOC_DONE_RESET: | ||
| 484 | dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " | ||
| 485 | "MPT2_IOC_DONE_RESET\n", ioc->name, __func__)); | ||
| 486 | |||
| 487 | for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) { | ||
| 488 | if (!(ioc->diag_buffer_status[i] & | ||
| 489 | MPT2_DIAG_BUFFER_IS_REGISTERED)) | ||
| 490 | continue; | ||
| 491 | if ((ioc->diag_buffer_status[i] & | ||
| 492 | MPT2_DIAG_BUFFER_IS_RELEASED)) | ||
| 493 | continue; | ||
| 494 | ioc->diag_buffer_status[i] |= | ||
| 495 | MPT2_DIAG_BUFFER_IS_DIAG_RESET; | ||
| 496 | } | ||
| 497 | break; | ||
| 498 | } | ||
| 499 | } | ||
| 500 | |||
| 501 | /** | ||
| 502 | * _ctl_fasync - | ||
| 503 | * @fd - | ||
| 504 | * @filep - | ||
| 505 | * @mode - | ||
| 506 | * | ||
| 507 | * Called when application request fasyn callback handler. | ||
| 508 | */ | ||
| 509 | static int | ||
| 510 | _ctl_fasync(int fd, struct file *filep, int mode) | ||
| 511 | { | ||
| 512 | return fasync_helper(fd, filep, mode, &async_queue); | ||
| 513 | } | ||
| 514 | |||
| 515 | /** | ||
| 516 | * _ctl_poll - | ||
| 517 | * @file - | ||
| 518 | * @wait - | ||
| 519 | * | ||
| 520 | */ | ||
| 521 | static unsigned int | ||
| 522 | _ctl_poll(struct file *filep, poll_table *wait) | ||
| 523 | { | ||
| 524 | struct MPT2SAS_ADAPTER *ioc; | ||
| 525 | |||
| 526 | poll_wait(filep, &ctl_poll_wait, wait); | ||
| 527 | |||
| 528 | /* global ioc lock to protect controller on list operations */ | ||
| 529 | spin_lock(&gioc_lock); | ||
| 530 | list_for_each_entry(ioc, &mpt2sas_ioc_list, list) { | ||
| 531 | if (ioc->aen_event_read_flag) { | ||
| 532 | spin_unlock(&gioc_lock); | ||
| 533 | return POLLIN | POLLRDNORM; | ||
| 534 | } | ||
| 535 | } | ||
| 536 | spin_unlock(&gioc_lock); | ||
| 537 | return 0; | ||
| 538 | } | ||
| 539 | |||
| 540 | /** | ||
| 541 | * _ctl_set_task_mid - assign an active smid to tm request | ||
| 542 | * @ioc: per adapter object | ||
| 543 | * @karg - (struct mpt2_ioctl_command) | ||
| 544 | * @tm_request - pointer to mf from user space | ||
| 545 | * | ||
| 546 | * Returns 0 when an smid if found, else fail. | ||
| 547 | * during failure, the reply frame is filled. | ||
| 548 | */ | ||
| 549 | static int | ||
| 550 | _ctl_set_task_mid(struct MPT2SAS_ADAPTER *ioc, struct mpt2_ioctl_command *karg, | ||
| 551 | Mpi2SCSITaskManagementRequest_t *tm_request) | ||
| 552 | { | ||
| 553 | u8 found = 0; | ||
| 554 | u16 i; | ||
| 555 | u16 handle; | ||
| 556 | struct scsi_cmnd *scmd; | ||
| 557 | struct MPT2SAS_DEVICE *priv_data; | ||
| 558 | unsigned long flags; | ||
| 559 | Mpi2SCSITaskManagementReply_t *tm_reply; | ||
| 560 | u32 sz; | ||
| 561 | u32 lun; | ||
| 562 | char *desc = NULL; | ||
| 563 | |||
| 564 | if (tm_request->TaskType == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK) | ||
| 565 | desc = "abort_task"; | ||
| 566 | else if (tm_request->TaskType == MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK) | ||
| 567 | desc = "query_task"; | ||
| 568 | else | ||
| 569 | return 0; | ||
| 570 | |||
| 571 | lun = scsilun_to_int((struct scsi_lun *)tm_request->LUN); | ||
| 572 | |||
| 573 | handle = le16_to_cpu(tm_request->DevHandle); | ||
| 574 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | ||
| 575 | for (i = ioc->scsiio_depth; i && !found; i--) { | ||
| 576 | scmd = ioc->scsi_lookup[i - 1].scmd; | ||
| 577 | if (scmd == NULL || scmd->device == NULL || | ||
| 578 | scmd->device->hostdata == NULL) | ||
| 579 | continue; | ||
| 580 | if (lun != scmd->device->lun) | ||
| 581 | continue; | ||
| 582 | priv_data = scmd->device->hostdata; | ||
| 583 | if (priv_data->sas_target == NULL) | ||
| 584 | continue; | ||
| 585 | if (priv_data->sas_target->handle != handle) | ||
| 586 | continue; | ||
| 587 | tm_request->TaskMID = cpu_to_le16(ioc->scsi_lookup[i - 1].smid); | ||
| 588 | found = 1; | ||
| 589 | } | ||
| 590 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | ||
| 591 | |||
| 592 | if (!found) { | ||
| 593 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " | ||
| 594 | "handle(0x%04x), lun(%d), no active mid!!\n", ioc->name, | ||
| 595 | desc, le16_to_cpu(tm_request->DevHandle), lun)); | ||
| 596 | tm_reply = ioc->ctl_cmds.reply; | ||
| 597 | tm_reply->DevHandle = tm_request->DevHandle; | ||
| 598 | tm_reply->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; | ||
| 599 | tm_reply->TaskType = tm_request->TaskType; | ||
| 600 | tm_reply->MsgLength = sizeof(Mpi2SCSITaskManagementReply_t)/4; | ||
| 601 | tm_reply->VP_ID = tm_request->VP_ID; | ||
| 602 | tm_reply->VF_ID = tm_request->VF_ID; | ||
| 603 | sz = min_t(u32, karg->max_reply_bytes, ioc->reply_sz); | ||
| 604 | if (copy_to_user(karg->reply_frame_buf_ptr, ioc->ctl_cmds.reply, | ||
| 605 | sz)) | ||
| 606 | printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, | ||
| 607 | __LINE__, __func__); | ||
| 608 | return 1; | ||
| 609 | } | ||
| 610 | |||
| 611 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " | ||
| 612 | "handle(0x%04x), lun(%d), task_mid(%d)\n", ioc->name, | ||
| 613 | desc, le16_to_cpu(tm_request->DevHandle), lun, | ||
| 614 | le16_to_cpu(tm_request->TaskMID))); | ||
| 615 | return 0; | ||
| 616 | } | ||
| 617 | |||
| 618 | /** | ||
| 619 | * _ctl_do_mpt_command - main handler for MPT2COMMAND opcode | ||
| 620 | * @ioc: per adapter object | ||
| 621 | * @karg - (struct mpt2_ioctl_command) | ||
| 622 | * @mf - pointer to mf in user space | ||
| 623 | */ | ||
| 624 | static long | ||
| 625 | _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, struct mpt2_ioctl_command karg, | ||
| 626 | void __user *mf) | ||
| 627 | { | ||
| 628 | MPI2RequestHeader_t *mpi_request = NULL, *request; | ||
| 629 | MPI2DefaultReply_t *mpi_reply; | ||
| 630 | u32 ioc_state; | ||
| 631 | u16 ioc_status; | ||
| 632 | u16 smid; | ||
| 633 | unsigned long timeout, timeleft; | ||
| 634 | u8 issue_reset; | ||
| 635 | u32 sz; | ||
| 636 | void *psge; | ||
| 637 | void *data_out = NULL; | ||
| 638 | dma_addr_t data_out_dma; | ||
| 639 | size_t data_out_sz = 0; | ||
| 640 | void *data_in = NULL; | ||
| 641 | dma_addr_t data_in_dma; | ||
| 642 | size_t data_in_sz = 0; | ||
| 643 | u32 sgl_flags; | ||
| 644 | long ret; | ||
| 645 | u16 wait_state_count; | ||
| 646 | |||
| 647 | issue_reset = 0; | ||
| 648 | |||
| 649 | if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) { | ||
| 650 | printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n", | ||
| 651 | ioc->name, __func__); | ||
| 652 | ret = -EAGAIN; | ||
| 653 | goto out; | ||
| 654 | } | ||
| 655 | |||
| 656 | wait_state_count = 0; | ||
| 657 | ioc_state = mpt2sas_base_get_iocstate(ioc, 1); | ||
| 658 | while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { | ||
| 659 | if (wait_state_count++ == 10) { | ||
| 660 | printk(MPT2SAS_ERR_FMT | ||
| 661 | "%s: failed due to ioc not operational\n", | ||
| 662 | ioc->name, __func__); | ||
| 663 | ret = -EFAULT; | ||
| 664 | goto out; | ||
| 665 | } | ||
| 666 | ssleep(1); | ||
| 667 | ioc_state = mpt2sas_base_get_iocstate(ioc, 1); | ||
| 668 | printk(MPT2SAS_INFO_FMT "%s: waiting for " | ||
| 669 | "operational state(count=%d)\n", ioc->name, | ||
| 670 | __func__, wait_state_count); | ||
| 671 | } | ||
| 672 | if (wait_state_count) | ||
| 673 | printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n", | ||
| 674 | ioc->name, __func__); | ||
| 675 | |||
| 676 | mpi_request = kzalloc(ioc->request_sz, GFP_KERNEL); | ||
| 677 | if (!mpi_request) { | ||
| 678 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a memory for " | ||
| 679 | "mpi_request\n", ioc->name, __func__); | ||
| 680 | ret = -ENOMEM; | ||
| 681 | goto out; | ||
| 682 | } | ||
| 683 | |||
| 684 | /* Check for overflow and wraparound */ | ||
| 685 | if (karg.data_sge_offset * 4 > ioc->request_sz || | ||
| 686 | karg.data_sge_offset > (UINT_MAX / 4)) { | ||
| 687 | ret = -EINVAL; | ||
| 688 | goto out; | ||
| 689 | } | ||
| 690 | |||
| 691 | /* copy in request message frame from user */ | ||
| 692 | if (copy_from_user(mpi_request, mf, karg.data_sge_offset*4)) { | ||
| 693 | printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, __LINE__, | ||
| 694 | __func__); | ||
| 695 | ret = -EFAULT; | ||
| 696 | goto out; | ||
| 697 | } | ||
| 698 | |||
| 699 | if (mpi_request->Function == MPI2_FUNCTION_SCSI_TASK_MGMT) { | ||
| 700 | smid = mpt2sas_base_get_smid_hpr(ioc, ioc->ctl_cb_idx); | ||
| 701 | if (!smid) { | ||
| 702 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", | ||
| 703 | ioc->name, __func__); | ||
| 704 | ret = -EAGAIN; | ||
| 705 | goto out; | ||
| 706 | } | ||
| 707 | } else { | ||
| 708 | |||
| 709 | smid = mpt2sas_base_get_smid_scsiio(ioc, ioc->ctl_cb_idx, NULL); | ||
| 710 | if (!smid) { | ||
| 711 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", | ||
| 712 | ioc->name, __func__); | ||
| 713 | ret = -EAGAIN; | ||
| 714 | goto out; | ||
| 715 | } | ||
| 716 | } | ||
| 717 | |||
| 718 | ret = 0; | ||
| 719 | ioc->ctl_cmds.status = MPT2_CMD_PENDING; | ||
| 720 | memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz); | ||
| 721 | request = mpt2sas_base_get_msg_frame(ioc, smid); | ||
| 722 | memcpy(request, mpi_request, karg.data_sge_offset*4); | ||
| 723 | ioc->ctl_cmds.smid = smid; | ||
| 724 | data_out_sz = karg.data_out_size; | ||
| 725 | data_in_sz = karg.data_in_size; | ||
| 726 | |||
| 727 | if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST || | ||
| 728 | mpi_request->Function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) { | ||
| 729 | if (!le16_to_cpu(mpi_request->FunctionDependent1) || | ||
| 730 | le16_to_cpu(mpi_request->FunctionDependent1) > | ||
| 731 | ioc->facts.MaxDevHandle) { | ||
| 732 | ret = -EINVAL; | ||
| 733 | mpt2sas_base_free_smid(ioc, smid); | ||
| 734 | goto out; | ||
| 735 | } | ||
| 736 | } | ||
| 737 | |||
| 738 | /* obtain dma-able memory for data transfer */ | ||
| 739 | if (data_out_sz) /* WRITE */ { | ||
| 740 | data_out = pci_alloc_consistent(ioc->pdev, data_out_sz, | ||
| 741 | &data_out_dma); | ||
| 742 | if (!data_out) { | ||
| 743 | printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, | ||
| 744 | __LINE__, __func__); | ||
| 745 | ret = -ENOMEM; | ||
| 746 | mpt2sas_base_free_smid(ioc, smid); | ||
| 747 | goto out; | ||
| 748 | } | ||
| 749 | if (copy_from_user(data_out, karg.data_out_buf_ptr, | ||
| 750 | data_out_sz)) { | ||
| 751 | printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, | ||
| 752 | __LINE__, __func__); | ||
| 753 | ret = -EFAULT; | ||
| 754 | mpt2sas_base_free_smid(ioc, smid); | ||
| 755 | goto out; | ||
| 756 | } | ||
| 757 | } | ||
| 758 | |||
| 759 | if (data_in_sz) /* READ */ { | ||
| 760 | data_in = pci_alloc_consistent(ioc->pdev, data_in_sz, | ||
| 761 | &data_in_dma); | ||
| 762 | if (!data_in) { | ||
| 763 | printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, | ||
| 764 | __LINE__, __func__); | ||
| 765 | ret = -ENOMEM; | ||
| 766 | mpt2sas_base_free_smid(ioc, smid); | ||
| 767 | goto out; | ||
| 768 | } | ||
| 769 | } | ||
| 770 | |||
| 771 | /* add scatter gather elements */ | ||
| 772 | psge = (void *)request + (karg.data_sge_offset*4); | ||
| 773 | |||
| 774 | if (!data_out_sz && !data_in_sz) { | ||
| 775 | mpt2sas_base_build_zero_len_sge(ioc, psge); | ||
| 776 | } else if (data_out_sz && data_in_sz) { | ||
| 777 | /* WRITE sgel first */ | ||
| 778 | sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT | | ||
| 779 | MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC); | ||
| 780 | sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; | ||
| 781 | ioc->base_add_sg_single(psge, sgl_flags | | ||
| 782 | data_out_sz, data_out_dma); | ||
| 783 | |||
| 784 | /* incr sgel */ | ||
| 785 | psge += ioc->sge_size; | ||
| 786 | |||
| 787 | /* READ sgel last */ | ||
| 788 | sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT | | ||
| 789 | MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER | | ||
| 790 | MPI2_SGE_FLAGS_END_OF_LIST); | ||
| 791 | sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; | ||
| 792 | ioc->base_add_sg_single(psge, sgl_flags | | ||
| 793 | data_in_sz, data_in_dma); | ||
| 794 | } else if (data_out_sz) /* WRITE */ { | ||
| 795 | sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT | | ||
| 796 | MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER | | ||
| 797 | MPI2_SGE_FLAGS_END_OF_LIST | MPI2_SGE_FLAGS_HOST_TO_IOC); | ||
| 798 | sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; | ||
| 799 | ioc->base_add_sg_single(psge, sgl_flags | | ||
| 800 | data_out_sz, data_out_dma); | ||
| 801 | } else if (data_in_sz) /* READ */ { | ||
| 802 | sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT | | ||
| 803 | MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER | | ||
| 804 | MPI2_SGE_FLAGS_END_OF_LIST); | ||
| 805 | sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; | ||
| 806 | ioc->base_add_sg_single(psge, sgl_flags | | ||
| 807 | data_in_sz, data_in_dma); | ||
| 808 | } | ||
| 809 | |||
| 810 | /* send command to firmware */ | ||
| 811 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | ||
| 812 | _ctl_display_some_debug(ioc, smid, "ctl_request", NULL); | ||
| 813 | #endif | ||
| 814 | |||
| 815 | init_completion(&ioc->ctl_cmds.done); | ||
| 816 | switch (mpi_request->Function) { | ||
| 817 | case MPI2_FUNCTION_SCSI_IO_REQUEST: | ||
| 818 | case MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH: | ||
| 819 | { | ||
| 820 | Mpi2SCSIIORequest_t *scsiio_request = | ||
| 821 | (Mpi2SCSIIORequest_t *)request; | ||
| 822 | scsiio_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE; | ||
| 823 | scsiio_request->SenseBufferLowAddress = | ||
| 824 | mpt2sas_base_get_sense_buffer_dma(ioc, smid); | ||
| 825 | memset(ioc->ctl_cmds.sense, 0, SCSI_SENSE_BUFFERSIZE); | ||
| 826 | if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST) | ||
| 827 | mpt2sas_base_put_smid_scsi_io(ioc, smid, | ||
| 828 | le16_to_cpu(mpi_request->FunctionDependent1)); | ||
| 829 | else | ||
| 830 | mpt2sas_base_put_smid_default(ioc, smid); | ||
| 831 | break; | ||
| 832 | } | ||
| 833 | case MPI2_FUNCTION_SCSI_TASK_MGMT: | ||
| 834 | { | ||
| 835 | Mpi2SCSITaskManagementRequest_t *tm_request = | ||
| 836 | (Mpi2SCSITaskManagementRequest_t *)request; | ||
| 837 | |||
| 838 | dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "TASK_MGMT: " | ||
| 839 | "handle(0x%04x), task_type(0x%02x)\n", ioc->name, | ||
| 840 | le16_to_cpu(tm_request->DevHandle), tm_request->TaskType)); | ||
| 841 | |||
| 842 | if (tm_request->TaskType == | ||
| 843 | MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK || | ||
| 844 | tm_request->TaskType == | ||
| 845 | MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK) { | ||
| 846 | if (_ctl_set_task_mid(ioc, &karg, tm_request)) { | ||
| 847 | mpt2sas_base_free_smid(ioc, smid); | ||
| 848 | goto out; | ||
| 849 | } | ||
| 850 | } | ||
| 851 | |||
| 852 | mpt2sas_scsih_set_tm_flag(ioc, le16_to_cpu( | ||
| 853 | tm_request->DevHandle)); | ||
| 854 | mpt2sas_base_put_smid_hi_priority(ioc, smid); | ||
| 855 | break; | ||
| 856 | } | ||
| 857 | case MPI2_FUNCTION_SMP_PASSTHROUGH: | ||
| 858 | { | ||
| 859 | Mpi2SmpPassthroughRequest_t *smp_request = | ||
| 860 | (Mpi2SmpPassthroughRequest_t *)mpi_request; | ||
| 861 | u8 *data; | ||
| 862 | |||
| 863 | /* ioc determines which port to use */ | ||
| 864 | smp_request->PhysicalPort = 0xFF; | ||
| 865 | if (smp_request->PassthroughFlags & | ||
| 866 | MPI2_SMP_PT_REQ_PT_FLAGS_IMMEDIATE) | ||
| 867 | data = (u8 *)&smp_request->SGL; | ||
| 868 | else { | ||
| 869 | if (unlikely(data_out == NULL)) { | ||
| 870 | printk(KERN_ERR "failure at %s:%d/%s()!\n", | ||
| 871 | __FILE__, __LINE__, __func__); | ||
| 872 | mpt2sas_base_free_smid(ioc, smid); | ||
| 873 | ret = -EINVAL; | ||
| 874 | goto out; | ||
| 875 | } | ||
| 876 | data = data_out; | ||
| 877 | } | ||
| 878 | |||
| 879 | if (data[1] == 0x91 && (data[10] == 1 || data[10] == 2)) { | ||
| 880 | ioc->ioc_link_reset_in_progress = 1; | ||
| 881 | ioc->ignore_loginfos = 1; | ||
| 882 | } | ||
| 883 | mpt2sas_base_put_smid_default(ioc, smid); | ||
| 884 | break; | ||
| 885 | } | ||
| 886 | case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL: | ||
| 887 | { | ||
| 888 | Mpi2SasIoUnitControlRequest_t *sasiounit_request = | ||
| 889 | (Mpi2SasIoUnitControlRequest_t *)mpi_request; | ||
| 890 | |||
| 891 | if (sasiounit_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET | ||
| 892 | || sasiounit_request->Operation == | ||
| 893 | MPI2_SAS_OP_PHY_LINK_RESET) { | ||
| 894 | ioc->ioc_link_reset_in_progress = 1; | ||
| 895 | ioc->ignore_loginfos = 1; | ||
| 896 | } | ||
| 897 | mpt2sas_base_put_smid_default(ioc, smid); | ||
| 898 | break; | ||
| 899 | } | ||
| 900 | default: | ||
| 901 | mpt2sas_base_put_smid_default(ioc, smid); | ||
| 902 | break; | ||
| 903 | } | ||
| 904 | |||
| 905 | if (karg.timeout < MPT2_IOCTL_DEFAULT_TIMEOUT) | ||
| 906 | timeout = MPT2_IOCTL_DEFAULT_TIMEOUT; | ||
| 907 | else | ||
| 908 | timeout = karg.timeout; | ||
| 909 | timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, | ||
| 910 | timeout*HZ); | ||
| 911 | if (mpi_request->Function == MPI2_FUNCTION_SCSI_TASK_MGMT) { | ||
| 912 | Mpi2SCSITaskManagementRequest_t *tm_request = | ||
| 913 | (Mpi2SCSITaskManagementRequest_t *)mpi_request; | ||
| 914 | mpt2sas_scsih_clear_tm_flag(ioc, le16_to_cpu( | ||
| 915 | tm_request->DevHandle)); | ||
| 916 | } else if ((mpi_request->Function == MPI2_FUNCTION_SMP_PASSTHROUGH || | ||
| 917 | mpi_request->Function == MPI2_FUNCTION_SAS_IO_UNIT_CONTROL) && | ||
| 918 | ioc->ioc_link_reset_in_progress) { | ||
| 919 | ioc->ioc_link_reset_in_progress = 0; | ||
| 920 | ioc->ignore_loginfos = 0; | ||
| 921 | } | ||
| 922 | if (!(ioc->ctl_cmds.status & MPT2_CMD_COMPLETE)) { | ||
| 923 | printk(MPT2SAS_ERR_FMT "%s: timeout\n", ioc->name, | ||
| 924 | __func__); | ||
| 925 | _debug_dump_mf(mpi_request, karg.data_sge_offset); | ||
| 926 | if (!(ioc->ctl_cmds.status & MPT2_CMD_RESET)) | ||
| 927 | issue_reset = 1; | ||
| 928 | goto issue_host_reset; | ||
| 929 | } | ||
| 930 | |||
| 931 | mpi_reply = ioc->ctl_cmds.reply; | ||
| 932 | ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK; | ||
| 933 | |||
| 934 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | ||
| 935 | if (mpi_reply->Function == MPI2_FUNCTION_SCSI_TASK_MGMT && | ||
| 936 | (ioc->logging_level & MPT_DEBUG_TM)) { | ||
| 937 | Mpi2SCSITaskManagementReply_t *tm_reply = | ||
| 938 | (Mpi2SCSITaskManagementReply_t *)mpi_reply; | ||
| 939 | |||
| 940 | printk(MPT2SAS_INFO_FMT "TASK_MGMT: " | ||
| 941 | "IOCStatus(0x%04x), IOCLogInfo(0x%08x), " | ||
| 942 | "TerminationCount(0x%08x)\n", ioc->name, | ||
| 943 | le16_to_cpu(tm_reply->IOCStatus), | ||
| 944 | le32_to_cpu(tm_reply->IOCLogInfo), | ||
| 945 | le32_to_cpu(tm_reply->TerminationCount)); | ||
| 946 | } | ||
| 947 | #endif | ||
| 948 | /* copy out xdata to user */ | ||
| 949 | if (data_in_sz) { | ||
| 950 | if (copy_to_user(karg.data_in_buf_ptr, data_in, | ||
| 951 | data_in_sz)) { | ||
| 952 | printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, | ||
| 953 | __LINE__, __func__); | ||
| 954 | ret = -ENODATA; | ||
| 955 | goto out; | ||
| 956 | } | ||
| 957 | } | ||
| 958 | |||
| 959 | /* copy out reply message frame to user */ | ||
| 960 | if (karg.max_reply_bytes) { | ||
| 961 | sz = min_t(u32, karg.max_reply_bytes, ioc->reply_sz); | ||
| 962 | if (copy_to_user(karg.reply_frame_buf_ptr, ioc->ctl_cmds.reply, | ||
| 963 | sz)) { | ||
| 964 | printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, | ||
| 965 | __LINE__, __func__); | ||
| 966 | ret = -ENODATA; | ||
| 967 | goto out; | ||
| 968 | } | ||
| 969 | } | ||
| 970 | |||
| 971 | /* copy out sense to user */ | ||
| 972 | if (karg.max_sense_bytes && (mpi_request->Function == | ||
| 973 | MPI2_FUNCTION_SCSI_IO_REQUEST || mpi_request->Function == | ||
| 974 | MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) { | ||
| 975 | sz = min_t(u32, karg.max_sense_bytes, SCSI_SENSE_BUFFERSIZE); | ||
| 976 | if (copy_to_user(karg.sense_data_ptr, | ||
| 977 | ioc->ctl_cmds.sense, sz)) { | ||
| 978 | printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, | ||
| 979 | __LINE__, __func__); | ||
| 980 | ret = -ENODATA; | ||
| 981 | goto out; | ||
| 982 | } | ||
| 983 | } | ||
| 984 | |||
| 985 | issue_host_reset: | ||
| 986 | if (issue_reset) { | ||
| 987 | ret = -ENODATA; | ||
| 988 | if ((mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST || | ||
| 989 | mpi_request->Function == | ||
| 990 | MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH || | ||
| 991 | mpi_request->Function == MPI2_FUNCTION_SATA_PASSTHROUGH)) { | ||
| 992 | printk(MPT2SAS_INFO_FMT "issue target reset: handle " | ||
| 993 | "= (0x%04x)\n", ioc->name, | ||
| 994 | le16_to_cpu(mpi_request->FunctionDependent1)); | ||
| 995 | mpt2sas_halt_firmware(ioc); | ||
| 996 | mpt2sas_scsih_issue_tm(ioc, | ||
| 997 | le16_to_cpu(mpi_request->FunctionDependent1), 0, 0, | ||
| 998 | 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 10, | ||
| 999 | TM_MUTEX_ON); | ||
| 1000 | ioc->tm_cmds.status = MPT2_CMD_NOT_USED; | ||
| 1001 | } else | ||
| 1002 | mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, | ||
| 1003 | FORCE_BIG_HAMMER); | ||
| 1004 | } | ||
| 1005 | |||
| 1006 | out: | ||
| 1007 | |||
| 1008 | /* free memory associated with sg buffers */ | ||
| 1009 | if (data_in) | ||
| 1010 | pci_free_consistent(ioc->pdev, data_in_sz, data_in, | ||
| 1011 | data_in_dma); | ||
| 1012 | |||
| 1013 | if (data_out) | ||
| 1014 | pci_free_consistent(ioc->pdev, data_out_sz, data_out, | ||
| 1015 | data_out_dma); | ||
| 1016 | |||
| 1017 | kfree(mpi_request); | ||
| 1018 | ioc->ctl_cmds.status = MPT2_CMD_NOT_USED; | ||
| 1019 | return ret; | ||
| 1020 | } | ||
| 1021 | |||
| 1022 | /** | ||
| 1023 | * _ctl_getiocinfo - main handler for MPT2IOCINFO opcode | ||
| 1024 | * @ioc: per adapter object | ||
| 1025 | * @arg - user space buffer containing ioctl content | ||
| 1026 | */ | ||
| 1027 | static long | ||
| 1028 | _ctl_getiocinfo(struct MPT2SAS_ADAPTER *ioc, void __user *arg) | ||
| 1029 | { | ||
| 1030 | struct mpt2_ioctl_iocinfo karg; | ||
| 1031 | |||
| 1032 | if (copy_from_user(&karg, arg, sizeof(karg))) { | ||
| 1033 | printk(KERN_ERR "failure at %s:%d/%s()!\n", | ||
| 1034 | __FILE__, __LINE__, __func__); | ||
| 1035 | return -EFAULT; | ||
| 1036 | } | ||
| 1037 | |||
| 1038 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name, | ||
| 1039 | __func__)); | ||
| 1040 | |||
| 1041 | memset(&karg, 0 , sizeof(karg)); | ||
| 1042 | if (ioc->is_warpdrive) | ||
| 1043 | karg.adapter_type = MPT2_IOCTL_INTERFACE_SAS2_SSS6200; | ||
| 1044 | else | ||
| 1045 | karg.adapter_type = MPT2_IOCTL_INTERFACE_SAS2; | ||
| 1046 | if (ioc->pfacts) | ||
| 1047 | karg.port_number = ioc->pfacts[0].PortNumber; | ||
| 1048 | karg.hw_rev = ioc->pdev->revision; | ||
| 1049 | karg.pci_id = ioc->pdev->device; | ||
| 1050 | karg.subsystem_device = ioc->pdev->subsystem_device; | ||
| 1051 | karg.subsystem_vendor = ioc->pdev->subsystem_vendor; | ||
| 1052 | karg.pci_information.u.bits.bus = ioc->pdev->bus->number; | ||
| 1053 | karg.pci_information.u.bits.device = PCI_SLOT(ioc->pdev->devfn); | ||
| 1054 | karg.pci_information.u.bits.function = PCI_FUNC(ioc->pdev->devfn); | ||
| 1055 | karg.pci_information.segment_id = pci_domain_nr(ioc->pdev->bus); | ||
| 1056 | karg.firmware_version = ioc->facts.FWVersion.Word; | ||
| 1057 | strcpy(karg.driver_version, MPT2SAS_DRIVER_NAME); | ||
| 1058 | strcat(karg.driver_version, "-"); | ||
| 1059 | strcat(karg.driver_version, MPT2SAS_DRIVER_VERSION); | ||
| 1060 | karg.bios_version = le32_to_cpu(ioc->bios_pg3.BiosVersion); | ||
| 1061 | |||
| 1062 | if (copy_to_user(arg, &karg, sizeof(karg))) { | ||
| 1063 | printk(KERN_ERR "failure at %s:%d/%s()!\n", | ||
| 1064 | __FILE__, __LINE__, __func__); | ||
| 1065 | return -EFAULT; | ||
| 1066 | } | ||
| 1067 | return 0; | ||
| 1068 | } | ||
| 1069 | |||
| 1070 | /** | ||
| 1071 | * _ctl_eventquery - main handler for MPT2EVENTQUERY opcode | ||
| 1072 | * @ioc: per adapter object | ||
| 1073 | * @arg - user space buffer containing ioctl content | ||
| 1074 | */ | ||
| 1075 | static long | ||
| 1076 | _ctl_eventquery(struct MPT2SAS_ADAPTER *ioc, void __user *arg) | ||
| 1077 | { | ||
| 1078 | struct mpt2_ioctl_eventquery karg; | ||
| 1079 | |||
| 1080 | if (copy_from_user(&karg, arg, sizeof(karg))) { | ||
| 1081 | printk(KERN_ERR "failure at %s:%d/%s()!\n", | ||
| 1082 | __FILE__, __LINE__, __func__); | ||
| 1083 | return -EFAULT; | ||
| 1084 | } | ||
| 1085 | |||
| 1086 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name, | ||
| 1087 | __func__)); | ||
| 1088 | |||
| 1089 | karg.event_entries = MPT2SAS_CTL_EVENT_LOG_SIZE; | ||
| 1090 | memcpy(karg.event_types, ioc->event_type, | ||
| 1091 | MPI2_EVENT_NOTIFY_EVENTMASK_WORDS * sizeof(u32)); | ||
| 1092 | |||
| 1093 | if (copy_to_user(arg, &karg, sizeof(karg))) { | ||
| 1094 | printk(KERN_ERR "failure at %s:%d/%s()!\n", | ||
| 1095 | __FILE__, __LINE__, __func__); | ||
| 1096 | return -EFAULT; | ||
| 1097 | } | ||
| 1098 | return 0; | ||
| 1099 | } | ||
| 1100 | |||
| 1101 | /** | ||
| 1102 | * _ctl_eventenable - main handler for MPT2EVENTENABLE opcode | ||
| 1103 | * @ioc: per adapter object | ||
| 1104 | * @arg - user space buffer containing ioctl content | ||
| 1105 | */ | ||
| 1106 | static long | ||
| 1107 | _ctl_eventenable(struct MPT2SAS_ADAPTER *ioc, void __user *arg) | ||
| 1108 | { | ||
| 1109 | struct mpt2_ioctl_eventenable karg; | ||
| 1110 | |||
| 1111 | if (copy_from_user(&karg, arg, sizeof(karg))) { | ||
| 1112 | printk(KERN_ERR "failure at %s:%d/%s()!\n", | ||
| 1113 | __FILE__, __LINE__, __func__); | ||
| 1114 | return -EFAULT; | ||
| 1115 | } | ||
| 1116 | |||
| 1117 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name, | ||
| 1118 | __func__)); | ||
| 1119 | |||
| 1120 | if (ioc->event_log) | ||
| 1121 | return 0; | ||
| 1122 | memcpy(ioc->event_type, karg.event_types, | ||
| 1123 | MPI2_EVENT_NOTIFY_EVENTMASK_WORDS * sizeof(u32)); | ||
| 1124 | mpt2sas_base_validate_event_type(ioc, ioc->event_type); | ||
| 1125 | |||
| 1126 | /* initialize event_log */ | ||
| 1127 | ioc->event_context = 0; | ||
| 1128 | ioc->aen_event_read_flag = 0; | ||
| 1129 | ioc->event_log = kcalloc(MPT2SAS_CTL_EVENT_LOG_SIZE, | ||
| 1130 | sizeof(struct MPT2_IOCTL_EVENTS), GFP_KERNEL); | ||
| 1131 | if (!ioc->event_log) { | ||
| 1132 | printk(KERN_ERR "failure at %s:%d/%s()!\n", | ||
| 1133 | __FILE__, __LINE__, __func__); | ||
| 1134 | return -ENOMEM; | ||
| 1135 | } | ||
| 1136 | return 0; | ||
| 1137 | } | ||
| 1138 | |||
| 1139 | /** | ||
| 1140 | * _ctl_eventreport - main handler for MPT2EVENTREPORT opcode | ||
| 1141 | * @ioc: per adapter object | ||
| 1142 | * @arg - user space buffer containing ioctl content | ||
| 1143 | */ | ||
| 1144 | static long | ||
| 1145 | _ctl_eventreport(struct MPT2SAS_ADAPTER *ioc, void __user *arg) | ||
| 1146 | { | ||
| 1147 | struct mpt2_ioctl_eventreport karg; | ||
| 1148 | u32 number_bytes, max_events, max; | ||
| 1149 | struct mpt2_ioctl_eventreport __user *uarg = arg; | ||
| 1150 | |||
| 1151 | if (copy_from_user(&karg, arg, sizeof(karg))) { | ||
| 1152 | printk(KERN_ERR "failure at %s:%d/%s()!\n", | ||
| 1153 | __FILE__, __LINE__, __func__); | ||
| 1154 | return -EFAULT; | ||
| 1155 | } | ||
| 1156 | |||
| 1157 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name, | ||
| 1158 | __func__)); | ||
| 1159 | |||
| 1160 | number_bytes = karg.hdr.max_data_size - | ||
| 1161 | sizeof(struct mpt2_ioctl_header); | ||
| 1162 | max_events = number_bytes/sizeof(struct MPT2_IOCTL_EVENTS); | ||
| 1163 | max = min_t(u32, MPT2SAS_CTL_EVENT_LOG_SIZE, max_events); | ||
| 1164 | |||
| 1165 | /* If fewer than 1 event is requested, there must have | ||
| 1166 | * been some type of error. | ||
| 1167 | */ | ||
| 1168 | if (!max || !ioc->event_log) | ||
| 1169 | return -ENODATA; | ||
| 1170 | |||
| 1171 | number_bytes = max * sizeof(struct MPT2_IOCTL_EVENTS); | ||
| 1172 | if (copy_to_user(uarg->event_data, ioc->event_log, number_bytes)) { | ||
| 1173 | printk(KERN_ERR "failure at %s:%d/%s()!\n", | ||
| 1174 | __FILE__, __LINE__, __func__); | ||
| 1175 | return -EFAULT; | ||
| 1176 | } | ||
| 1177 | |||
| 1178 | /* reset flag so SIGIO can restart */ | ||
| 1179 | ioc->aen_event_read_flag = 0; | ||
| 1180 | return 0; | ||
| 1181 | } | ||
| 1182 | |||
| 1183 | /** | ||
| 1184 | * _ctl_do_reset - main handler for MPT2HARDRESET opcode | ||
| 1185 | * @ioc: per adapter object | ||
| 1186 | * @arg - user space buffer containing ioctl content | ||
| 1187 | */ | ||
| 1188 | static long | ||
| 1189 | _ctl_do_reset(struct MPT2SAS_ADAPTER *ioc, void __user *arg) | ||
| 1190 | { | ||
| 1191 | struct mpt2_ioctl_diag_reset karg; | ||
| 1192 | int retval; | ||
| 1193 | |||
| 1194 | if (copy_from_user(&karg, arg, sizeof(karg))) { | ||
| 1195 | printk(KERN_ERR "failure at %s:%d/%s()!\n", | ||
| 1196 | __FILE__, __LINE__, __func__); | ||
| 1197 | return -EFAULT; | ||
| 1198 | } | ||
| 1199 | |||
| 1200 | if (ioc->shost_recovery || ioc->pci_error_recovery || | ||
| 1201 | ioc->is_driver_loading) | ||
| 1202 | return -EAGAIN; | ||
| 1203 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name, | ||
| 1204 | __func__)); | ||
| 1205 | |||
| 1206 | retval = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, | ||
| 1207 | FORCE_BIG_HAMMER); | ||
| 1208 | printk(MPT2SAS_INFO_FMT "host reset: %s\n", | ||
| 1209 | ioc->name, ((!retval) ? "SUCCESS" : "FAILED")); | ||
| 1210 | return 0; | ||
| 1211 | } | ||
| 1212 | |||
| 1213 | /** | ||
| 1214 | * _ctl_btdh_search_sas_device - searching for sas device | ||
| 1215 | * @ioc: per adapter object | ||
| 1216 | * @btdh: btdh ioctl payload | ||
| 1217 | */ | ||
| 1218 | static int | ||
| 1219 | _ctl_btdh_search_sas_device(struct MPT2SAS_ADAPTER *ioc, | ||
| 1220 | struct mpt2_ioctl_btdh_mapping *btdh) | ||
| 1221 | { | ||
| 1222 | struct _sas_device *sas_device; | ||
| 1223 | unsigned long flags; | ||
| 1224 | int rc = 0; | ||
| 1225 | |||
| 1226 | if (list_empty(&ioc->sas_device_list)) | ||
| 1227 | return rc; | ||
| 1228 | |||
| 1229 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 1230 | list_for_each_entry(sas_device, &ioc->sas_device_list, list) { | ||
| 1231 | if (btdh->bus == 0xFFFFFFFF && btdh->id == 0xFFFFFFFF && | ||
| 1232 | btdh->handle == sas_device->handle) { | ||
| 1233 | btdh->bus = sas_device->channel; | ||
| 1234 | btdh->id = sas_device->id; | ||
| 1235 | rc = 1; | ||
| 1236 | goto out; | ||
| 1237 | } else if (btdh->bus == sas_device->channel && btdh->id == | ||
| 1238 | sas_device->id && btdh->handle == 0xFFFF) { | ||
| 1239 | btdh->handle = sas_device->handle; | ||
| 1240 | rc = 1; | ||
| 1241 | goto out; | ||
| 1242 | } | ||
| 1243 | } | ||
| 1244 | out: | ||
| 1245 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 1246 | return rc; | ||
| 1247 | } | ||
| 1248 | |||
| 1249 | /** | ||
| 1250 | * _ctl_btdh_search_raid_device - searching for raid device | ||
| 1251 | * @ioc: per adapter object | ||
| 1252 | * @btdh: btdh ioctl payload | ||
| 1253 | */ | ||
| 1254 | static int | ||
| 1255 | _ctl_btdh_search_raid_device(struct MPT2SAS_ADAPTER *ioc, | ||
| 1256 | struct mpt2_ioctl_btdh_mapping *btdh) | ||
| 1257 | { | ||
| 1258 | struct _raid_device *raid_device; | ||
| 1259 | unsigned long flags; | ||
| 1260 | int rc = 0; | ||
| 1261 | |||
| 1262 | if (list_empty(&ioc->raid_device_list)) | ||
| 1263 | return rc; | ||
| 1264 | |||
| 1265 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | ||
| 1266 | list_for_each_entry(raid_device, &ioc->raid_device_list, list) { | ||
| 1267 | if (btdh->bus == 0xFFFFFFFF && btdh->id == 0xFFFFFFFF && | ||
| 1268 | btdh->handle == raid_device->handle) { | ||
| 1269 | btdh->bus = raid_device->channel; | ||
| 1270 | btdh->id = raid_device->id; | ||
| 1271 | rc = 1; | ||
| 1272 | goto out; | ||
| 1273 | } else if (btdh->bus == raid_device->channel && btdh->id == | ||
| 1274 | raid_device->id && btdh->handle == 0xFFFF) { | ||
| 1275 | btdh->handle = raid_device->handle; | ||
| 1276 | rc = 1; | ||
| 1277 | goto out; | ||
| 1278 | } | ||
| 1279 | } | ||
| 1280 | out: | ||
| 1281 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); | ||
| 1282 | return rc; | ||
| 1283 | } | ||
| 1284 | |||
| 1285 | /** | ||
| 1286 | * _ctl_btdh_mapping - main handler for MPT2BTDHMAPPING opcode | ||
| 1287 | * @ioc: per adapter object | ||
| 1288 | * @arg - user space buffer containing ioctl content | ||
| 1289 | */ | ||
| 1290 | static long | ||
| 1291 | _ctl_btdh_mapping(struct MPT2SAS_ADAPTER *ioc, void __user *arg) | ||
| 1292 | { | ||
| 1293 | struct mpt2_ioctl_btdh_mapping karg; | ||
| 1294 | int rc; | ||
| 1295 | |||
| 1296 | if (copy_from_user(&karg, arg, sizeof(karg))) { | ||
| 1297 | printk(KERN_ERR "failure at %s:%d/%s()!\n", | ||
| 1298 | __FILE__, __LINE__, __func__); | ||
| 1299 | return -EFAULT; | ||
| 1300 | } | ||
| 1301 | |||
| 1302 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | ||
| 1303 | __func__)); | ||
| 1304 | |||
| 1305 | rc = _ctl_btdh_search_sas_device(ioc, &karg); | ||
| 1306 | if (!rc) | ||
| 1307 | _ctl_btdh_search_raid_device(ioc, &karg); | ||
| 1308 | |||
| 1309 | if (copy_to_user(arg, &karg, sizeof(karg))) { | ||
| 1310 | printk(KERN_ERR "failure at %s:%d/%s()!\n", | ||
| 1311 | __FILE__, __LINE__, __func__); | ||
| 1312 | return -EFAULT; | ||
| 1313 | } | ||
| 1314 | return 0; | ||
| 1315 | } | ||
| 1316 | |||
| 1317 | /** | ||
| 1318 | * _ctl_diag_capability - return diag buffer capability | ||
| 1319 | * @ioc: per adapter object | ||
| 1320 | * @buffer_type: specifies either TRACE, SNAPSHOT, or EXTENDED | ||
| 1321 | * | ||
| 1322 | * returns 1 when diag buffer support is enabled in firmware | ||
| 1323 | */ | ||
| 1324 | static u8 | ||
| 1325 | _ctl_diag_capability(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type) | ||
| 1326 | { | ||
| 1327 | u8 rc = 0; | ||
| 1328 | |||
| 1329 | switch (buffer_type) { | ||
| 1330 | case MPI2_DIAG_BUF_TYPE_TRACE: | ||
| 1331 | if (ioc->facts.IOCCapabilities & | ||
| 1332 | MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER) | ||
| 1333 | rc = 1; | ||
| 1334 | break; | ||
| 1335 | case MPI2_DIAG_BUF_TYPE_SNAPSHOT: | ||
| 1336 | if (ioc->facts.IOCCapabilities & | ||
| 1337 | MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER) | ||
| 1338 | rc = 1; | ||
| 1339 | break; | ||
| 1340 | case MPI2_DIAG_BUF_TYPE_EXTENDED: | ||
| 1341 | if (ioc->facts.IOCCapabilities & | ||
| 1342 | MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER) | ||
| 1343 | rc = 1; | ||
| 1344 | } | ||
| 1345 | |||
| 1346 | return rc; | ||
| 1347 | } | ||
| 1348 | |||
| 1349 | /** | ||
| 1350 | * _ctl_diag_register_2 - wrapper for registering diag buffer support | ||
| 1351 | * @ioc: per adapter object | ||
| 1352 | * @diag_register: the diag_register struct passed in from user space | ||
| 1353 | * | ||
| 1354 | */ | ||
| 1355 | static long | ||
| 1356 | _ctl_diag_register_2(struct MPT2SAS_ADAPTER *ioc, | ||
| 1357 | struct mpt2_diag_register *diag_register) | ||
| 1358 | { | ||
| 1359 | int rc, i; | ||
| 1360 | void *request_data = NULL; | ||
| 1361 | dma_addr_t request_data_dma; | ||
| 1362 | u32 request_data_sz = 0; | ||
| 1363 | Mpi2DiagBufferPostRequest_t *mpi_request; | ||
| 1364 | Mpi2DiagBufferPostReply_t *mpi_reply; | ||
| 1365 | u8 buffer_type; | ||
| 1366 | unsigned long timeleft; | ||
| 1367 | u16 smid; | ||
| 1368 | u16 ioc_status; | ||
| 1369 | u8 issue_reset = 0; | ||
| 1370 | |||
| 1371 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | ||
| 1372 | __func__)); | ||
| 1373 | |||
| 1374 | if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) { | ||
| 1375 | printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n", | ||
| 1376 | ioc->name, __func__); | ||
| 1377 | rc = -EAGAIN; | ||
| 1378 | goto out; | ||
| 1379 | } | ||
| 1380 | |||
| 1381 | buffer_type = diag_register->buffer_type; | ||
| 1382 | if (!_ctl_diag_capability(ioc, buffer_type)) { | ||
| 1383 | printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for " | ||
| 1384 | "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type); | ||
| 1385 | return -EPERM; | ||
| 1386 | } | ||
| 1387 | |||
| 1388 | if (ioc->diag_buffer_status[buffer_type] & | ||
| 1389 | MPT2_DIAG_BUFFER_IS_REGISTERED) { | ||
| 1390 | printk(MPT2SAS_ERR_FMT "%s: already has a registered " | ||
| 1391 | "buffer for buffer_type(0x%02x)\n", ioc->name, __func__, | ||
| 1392 | buffer_type); | ||
| 1393 | return -EINVAL; | ||
| 1394 | } | ||
| 1395 | |||
| 1396 | if (diag_register->requested_buffer_size % 4) { | ||
| 1397 | printk(MPT2SAS_ERR_FMT "%s: the requested_buffer_size " | ||
| 1398 | "is not 4 byte aligned\n", ioc->name, __func__); | ||
| 1399 | return -EINVAL; | ||
| 1400 | } | ||
| 1401 | |||
| 1402 | smid = mpt2sas_base_get_smid(ioc, ioc->ctl_cb_idx); | ||
| 1403 | if (!smid) { | ||
| 1404 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", | ||
| 1405 | ioc->name, __func__); | ||
| 1406 | rc = -EAGAIN; | ||
| 1407 | goto out; | ||
| 1408 | } | ||
| 1409 | |||
| 1410 | rc = 0; | ||
| 1411 | ioc->ctl_cmds.status = MPT2_CMD_PENDING; | ||
| 1412 | memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz); | ||
| 1413 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); | ||
| 1414 | ioc->ctl_cmds.smid = smid; | ||
| 1415 | |||
| 1416 | request_data = ioc->diag_buffer[buffer_type]; | ||
| 1417 | request_data_sz = diag_register->requested_buffer_size; | ||
| 1418 | ioc->unique_id[buffer_type] = diag_register->unique_id; | ||
| 1419 | ioc->diag_buffer_status[buffer_type] = 0; | ||
| 1420 | memcpy(ioc->product_specific[buffer_type], | ||
| 1421 | diag_register->product_specific, MPT2_PRODUCT_SPECIFIC_DWORDS); | ||
| 1422 | ioc->diagnostic_flags[buffer_type] = diag_register->diagnostic_flags; | ||
| 1423 | |||
| 1424 | if (request_data) { | ||
| 1425 | request_data_dma = ioc->diag_buffer_dma[buffer_type]; | ||
| 1426 | if (request_data_sz != ioc->diag_buffer_sz[buffer_type]) { | ||
| 1427 | pci_free_consistent(ioc->pdev, | ||
| 1428 | ioc->diag_buffer_sz[buffer_type], | ||
| 1429 | request_data, request_data_dma); | ||
| 1430 | request_data = NULL; | ||
| 1431 | } | ||
| 1432 | } | ||
| 1433 | |||
| 1434 | if (request_data == NULL) { | ||
| 1435 | ioc->diag_buffer_sz[buffer_type] = 0; | ||
| 1436 | ioc->diag_buffer_dma[buffer_type] = 0; | ||
| 1437 | request_data = pci_alloc_consistent( | ||
| 1438 | ioc->pdev, request_data_sz, &request_data_dma); | ||
| 1439 | if (request_data == NULL) { | ||
| 1440 | printk(MPT2SAS_ERR_FMT "%s: failed allocating memory" | ||
| 1441 | " for diag buffers, requested size(%d)\n", | ||
| 1442 | ioc->name, __func__, request_data_sz); | ||
| 1443 | mpt2sas_base_free_smid(ioc, smid); | ||
| 1444 | return -ENOMEM; | ||
| 1445 | } | ||
| 1446 | ioc->diag_buffer[buffer_type] = request_data; | ||
| 1447 | ioc->diag_buffer_sz[buffer_type] = request_data_sz; | ||
| 1448 | ioc->diag_buffer_dma[buffer_type] = request_data_dma; | ||
| 1449 | } | ||
| 1450 | |||
| 1451 | mpi_request->Function = MPI2_FUNCTION_DIAG_BUFFER_POST; | ||
| 1452 | mpi_request->BufferType = diag_register->buffer_type; | ||
| 1453 | mpi_request->Flags = cpu_to_le32(diag_register->diagnostic_flags); | ||
| 1454 | mpi_request->BufferAddress = cpu_to_le64(request_data_dma); | ||
| 1455 | mpi_request->BufferLength = cpu_to_le32(request_data_sz); | ||
| 1456 | mpi_request->VF_ID = 0; /* TODO */ | ||
| 1457 | mpi_request->VP_ID = 0; | ||
| 1458 | |||
| 1459 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: diag_buffer(0x%p), " | ||
| 1460 | "dma(0x%llx), sz(%d)\n", ioc->name, __func__, request_data, | ||
| 1461 | (unsigned long long)request_data_dma, | ||
| 1462 | le32_to_cpu(mpi_request->BufferLength))); | ||
| 1463 | |||
| 1464 | for (i = 0; i < MPT2_PRODUCT_SPECIFIC_DWORDS; i++) | ||
| 1465 | mpi_request->ProductSpecific[i] = | ||
| 1466 | cpu_to_le32(ioc->product_specific[buffer_type][i]); | ||
| 1467 | |||
| 1468 | init_completion(&ioc->ctl_cmds.done); | ||
| 1469 | mpt2sas_base_put_smid_default(ioc, smid); | ||
| 1470 | timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, | ||
| 1471 | MPT2_IOCTL_DEFAULT_TIMEOUT*HZ); | ||
| 1472 | |||
| 1473 | if (!(ioc->ctl_cmds.status & MPT2_CMD_COMPLETE)) { | ||
| 1474 | printk(MPT2SAS_ERR_FMT "%s: timeout\n", ioc->name, | ||
| 1475 | __func__); | ||
| 1476 | _debug_dump_mf(mpi_request, | ||
| 1477 | sizeof(Mpi2DiagBufferPostRequest_t)/4); | ||
| 1478 | if (!(ioc->ctl_cmds.status & MPT2_CMD_RESET)) | ||
| 1479 | issue_reset = 1; | ||
| 1480 | goto issue_host_reset; | ||
| 1481 | } | ||
| 1482 | |||
| 1483 | /* process the completed Reply Message Frame */ | ||
| 1484 | if ((ioc->ctl_cmds.status & MPT2_CMD_REPLY_VALID) == 0) { | ||
| 1485 | printk(MPT2SAS_ERR_FMT "%s: no reply message\n", | ||
| 1486 | ioc->name, __func__); | ||
| 1487 | rc = -EFAULT; | ||
| 1488 | goto out; | ||
| 1489 | } | ||
| 1490 | |||
| 1491 | mpi_reply = ioc->ctl_cmds.reply; | ||
| 1492 | ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK; | ||
| 1493 | |||
| 1494 | if (ioc_status == MPI2_IOCSTATUS_SUCCESS) { | ||
| 1495 | ioc->diag_buffer_status[buffer_type] |= | ||
| 1496 | MPT2_DIAG_BUFFER_IS_REGISTERED; | ||
| 1497 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: success\n", | ||
| 1498 | ioc->name, __func__)); | ||
| 1499 | } else { | ||
| 1500 | printk(MPT2SAS_INFO_FMT "%s: ioc_status(0x%04x) " | ||
| 1501 | "log_info(0x%08x)\n", ioc->name, __func__, | ||
| 1502 | ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo)); | ||
| 1503 | rc = -EFAULT; | ||
| 1504 | } | ||
| 1505 | |||
| 1506 | issue_host_reset: | ||
| 1507 | if (issue_reset) | ||
| 1508 | mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, | ||
| 1509 | FORCE_BIG_HAMMER); | ||
| 1510 | |||
| 1511 | out: | ||
| 1512 | |||
| 1513 | if (rc && request_data) | ||
| 1514 | pci_free_consistent(ioc->pdev, request_data_sz, | ||
| 1515 | request_data, request_data_dma); | ||
| 1516 | |||
| 1517 | ioc->ctl_cmds.status = MPT2_CMD_NOT_USED; | ||
| 1518 | return rc; | ||
| 1519 | } | ||
| 1520 | |||
| 1521 | /** | ||
| 1522 | * mpt2sas_enable_diag_buffer - enabling diag_buffers support driver load time | ||
| 1523 | * @ioc: per adapter object | ||
| 1524 | * @bits_to_register: bitwise field where trace is bit 0, and snapshot is bit 1 | ||
| 1525 | * | ||
| 1526 | * This is called when command line option diag_buffer_enable is enabled | ||
| 1527 | * at driver load time. | ||
| 1528 | */ | ||
| 1529 | void | ||
| 1530 | mpt2sas_enable_diag_buffer(struct MPT2SAS_ADAPTER *ioc, u8 bits_to_register) | ||
| 1531 | { | ||
| 1532 | struct mpt2_diag_register diag_register; | ||
| 1533 | |||
| 1534 | memset(&diag_register, 0, sizeof(struct mpt2_diag_register)); | ||
| 1535 | |||
| 1536 | if (bits_to_register & 1) { | ||
| 1537 | printk(MPT2SAS_INFO_FMT "registering trace buffer support\n", | ||
| 1538 | ioc->name); | ||
| 1539 | diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_TRACE; | ||
| 1540 | /* register for 1MB buffers */ | ||
| 1541 | diag_register.requested_buffer_size = (1024 * 1024); | ||
| 1542 | diag_register.unique_id = 0x7075900; | ||
| 1543 | _ctl_diag_register_2(ioc, &diag_register); | ||
| 1544 | } | ||
| 1545 | |||
| 1546 | if (bits_to_register & 2) { | ||
| 1547 | printk(MPT2SAS_INFO_FMT "registering snapshot buffer support\n", | ||
| 1548 | ioc->name); | ||
| 1549 | diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_SNAPSHOT; | ||
| 1550 | /* register for 2MB buffers */ | ||
| 1551 | diag_register.requested_buffer_size = 2 * (1024 * 1024); | ||
| 1552 | diag_register.unique_id = 0x7075901; | ||
| 1553 | _ctl_diag_register_2(ioc, &diag_register); | ||
| 1554 | } | ||
| 1555 | |||
| 1556 | if (bits_to_register & 4) { | ||
| 1557 | printk(MPT2SAS_INFO_FMT "registering extended buffer support\n", | ||
| 1558 | ioc->name); | ||
| 1559 | diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_EXTENDED; | ||
| 1560 | /* register for 2MB buffers */ | ||
| 1561 | diag_register.requested_buffer_size = 2 * (1024 * 1024); | ||
| 1562 | diag_register.unique_id = 0x7075901; | ||
| 1563 | _ctl_diag_register_2(ioc, &diag_register); | ||
| 1564 | } | ||
| 1565 | } | ||
| 1566 | |||
| 1567 | /** | ||
| 1568 | * _ctl_diag_register - application register with driver | ||
| 1569 | * @ioc: per adapter object | ||
| 1570 | * @arg - user space buffer containing ioctl content | ||
| 1571 | * | ||
| 1572 | * This will allow the driver to setup any required buffers that will be | ||
| 1573 | * needed by firmware to communicate with the driver. | ||
| 1574 | */ | ||
| 1575 | static long | ||
| 1576 | _ctl_diag_register(struct MPT2SAS_ADAPTER *ioc, void __user *arg) | ||
| 1577 | { | ||
| 1578 | struct mpt2_diag_register karg; | ||
| 1579 | long rc; | ||
| 1580 | |||
| 1581 | if (copy_from_user(&karg, arg, sizeof(karg))) { | ||
| 1582 | printk(KERN_ERR "failure at %s:%d/%s()!\n", | ||
| 1583 | __FILE__, __LINE__, __func__); | ||
| 1584 | return -EFAULT; | ||
| 1585 | } | ||
| 1586 | |||
| 1587 | rc = _ctl_diag_register_2(ioc, &karg); | ||
| 1588 | return rc; | ||
| 1589 | } | ||
| 1590 | |||
| 1591 | /** | ||
| 1592 | * _ctl_diag_unregister - application unregister with driver | ||
| 1593 | * @ioc: per adapter object | ||
| 1594 | * @arg - user space buffer containing ioctl content | ||
| 1595 | * | ||
| 1596 | * This will allow the driver to cleanup any memory allocated for diag | ||
| 1597 | * messages and to free up any resources. | ||
| 1598 | */ | ||
| 1599 | static long | ||
| 1600 | _ctl_diag_unregister(struct MPT2SAS_ADAPTER *ioc, void __user *arg) | ||
| 1601 | { | ||
| 1602 | struct mpt2_diag_unregister karg; | ||
| 1603 | void *request_data; | ||
| 1604 | dma_addr_t request_data_dma; | ||
| 1605 | u32 request_data_sz; | ||
| 1606 | u8 buffer_type; | ||
| 1607 | |||
| 1608 | if (copy_from_user(&karg, arg, sizeof(karg))) { | ||
| 1609 | printk(KERN_ERR "failure at %s:%d/%s()!\n", | ||
| 1610 | __FILE__, __LINE__, __func__); | ||
| 1611 | return -EFAULT; | ||
| 1612 | } | ||
| 1613 | |||
| 1614 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | ||
| 1615 | __func__)); | ||
| 1616 | |||
| 1617 | buffer_type = karg.unique_id & 0x000000ff; | ||
| 1618 | if (!_ctl_diag_capability(ioc, buffer_type)) { | ||
| 1619 | printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for " | ||
| 1620 | "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type); | ||
| 1621 | return -EPERM; | ||
| 1622 | } | ||
| 1623 | |||
| 1624 | if ((ioc->diag_buffer_status[buffer_type] & | ||
| 1625 | MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) { | ||
| 1626 | printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) is not " | ||
| 1627 | "registered\n", ioc->name, __func__, buffer_type); | ||
| 1628 | return -EINVAL; | ||
| 1629 | } | ||
| 1630 | if ((ioc->diag_buffer_status[buffer_type] & | ||
| 1631 | MPT2_DIAG_BUFFER_IS_RELEASED) == 0) { | ||
| 1632 | printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) has not been " | ||
| 1633 | "released\n", ioc->name, __func__, buffer_type); | ||
| 1634 | return -EINVAL; | ||
| 1635 | } | ||
| 1636 | |||
| 1637 | if (karg.unique_id != ioc->unique_id[buffer_type]) { | ||
| 1638 | printk(MPT2SAS_ERR_FMT "%s: unique_id(0x%08x) is not " | ||
| 1639 | "registered\n", ioc->name, __func__, karg.unique_id); | ||
| 1640 | return -EINVAL; | ||
| 1641 | } | ||
| 1642 | |||
| 1643 | request_data = ioc->diag_buffer[buffer_type]; | ||
| 1644 | if (!request_data) { | ||
| 1645 | printk(MPT2SAS_ERR_FMT "%s: doesn't have memory allocated for " | ||
| 1646 | "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type); | ||
| 1647 | return -ENOMEM; | ||
| 1648 | } | ||
| 1649 | |||
| 1650 | request_data_sz = ioc->diag_buffer_sz[buffer_type]; | ||
| 1651 | request_data_dma = ioc->diag_buffer_dma[buffer_type]; | ||
| 1652 | pci_free_consistent(ioc->pdev, request_data_sz, | ||
| 1653 | request_data, request_data_dma); | ||
| 1654 | ioc->diag_buffer[buffer_type] = NULL; | ||
| 1655 | ioc->diag_buffer_status[buffer_type] = 0; | ||
| 1656 | return 0; | ||
| 1657 | } | ||
| 1658 | |||
| 1659 | /** | ||
| 1660 | * _ctl_diag_query - query relevant info associated with diag buffers | ||
| 1661 | * @ioc: per adapter object | ||
| 1662 | * @arg - user space buffer containing ioctl content | ||
| 1663 | * | ||
| 1664 | * The application will send only buffer_type and unique_id. Driver will | ||
| 1665 | * inspect unique_id first, if valid, fill in all the info. If unique_id is | ||
| 1666 | * 0x00, the driver will return info specified by Buffer Type. | ||
| 1667 | */ | ||
| 1668 | static long | ||
| 1669 | _ctl_diag_query(struct MPT2SAS_ADAPTER *ioc, void __user *arg) | ||
| 1670 | { | ||
| 1671 | struct mpt2_diag_query karg; | ||
| 1672 | void *request_data; | ||
| 1673 | int i; | ||
| 1674 | u8 buffer_type; | ||
| 1675 | |||
| 1676 | if (copy_from_user(&karg, arg, sizeof(karg))) { | ||
| 1677 | printk(KERN_ERR "failure at %s:%d/%s()!\n", | ||
| 1678 | __FILE__, __LINE__, __func__); | ||
| 1679 | return -EFAULT; | ||
| 1680 | } | ||
| 1681 | |||
| 1682 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | ||
| 1683 | __func__)); | ||
| 1684 | |||
| 1685 | karg.application_flags = 0; | ||
| 1686 | buffer_type = karg.buffer_type; | ||
| 1687 | |||
| 1688 | if (!_ctl_diag_capability(ioc, buffer_type)) { | ||
| 1689 | printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for " | ||
| 1690 | "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type); | ||
| 1691 | return -EPERM; | ||
| 1692 | } | ||
| 1693 | |||
| 1694 | if ((ioc->diag_buffer_status[buffer_type] & | ||
| 1695 | MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) { | ||
| 1696 | printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) is not " | ||
| 1697 | "registered\n", ioc->name, __func__, buffer_type); | ||
| 1698 | return -EINVAL; | ||
| 1699 | } | ||
| 1700 | |||
| 1701 | if (karg.unique_id & 0xffffff00) { | ||
| 1702 | if (karg.unique_id != ioc->unique_id[buffer_type]) { | ||
| 1703 | printk(MPT2SAS_ERR_FMT "%s: unique_id(0x%08x) is not " | ||
| 1704 | "registered\n", ioc->name, __func__, | ||
| 1705 | karg.unique_id); | ||
| 1706 | return -EINVAL; | ||
| 1707 | } | ||
| 1708 | } | ||
| 1709 | |||
| 1710 | request_data = ioc->diag_buffer[buffer_type]; | ||
| 1711 | if (!request_data) { | ||
| 1712 | printk(MPT2SAS_ERR_FMT "%s: doesn't have buffer for " | ||
| 1713 | "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type); | ||
| 1714 | return -ENOMEM; | ||
| 1715 | } | ||
| 1716 | |||
| 1717 | if (ioc->diag_buffer_status[buffer_type] & MPT2_DIAG_BUFFER_IS_RELEASED) | ||
| 1718 | karg.application_flags = (MPT2_APP_FLAGS_APP_OWNED | | ||
| 1719 | MPT2_APP_FLAGS_BUFFER_VALID); | ||
| 1720 | else | ||
| 1721 | karg.application_flags = (MPT2_APP_FLAGS_APP_OWNED | | ||
| 1722 | MPT2_APP_FLAGS_BUFFER_VALID | | ||
| 1723 | MPT2_APP_FLAGS_FW_BUFFER_ACCESS); | ||
| 1724 | |||
| 1725 | for (i = 0; i < MPT2_PRODUCT_SPECIFIC_DWORDS; i++) | ||
| 1726 | karg.product_specific[i] = | ||
| 1727 | ioc->product_specific[buffer_type][i]; | ||
| 1728 | |||
| 1729 | karg.total_buffer_size = ioc->diag_buffer_sz[buffer_type]; | ||
| 1730 | karg.driver_added_buffer_size = 0; | ||
| 1731 | karg.unique_id = ioc->unique_id[buffer_type]; | ||
| 1732 | karg.diagnostic_flags = ioc->diagnostic_flags[buffer_type]; | ||
| 1733 | |||
| 1734 | if (copy_to_user(arg, &karg, sizeof(struct mpt2_diag_query))) { | ||
| 1735 | printk(MPT2SAS_ERR_FMT "%s: unable to write mpt2_diag_query " | ||
| 1736 | "data @ %p\n", ioc->name, __func__, arg); | ||
| 1737 | return -EFAULT; | ||
| 1738 | } | ||
| 1739 | return 0; | ||
| 1740 | } | ||
| 1741 | |||
| 1742 | /** | ||
| 1743 | * _ctl_send_release - Diag Release Message | ||
| 1744 | * @ioc: per adapter object | ||
| 1745 | * @buffer_type - specifies either TRACE, SNAPSHOT, or EXTENDED | ||
| 1746 | * @issue_reset - specifies whether host reset is required. | ||
| 1747 | * | ||
| 1748 | */ | ||
| 1749 | static int | ||
| 1750 | _ctl_send_release(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type, u8 *issue_reset) | ||
| 1751 | { | ||
| 1752 | Mpi2DiagReleaseRequest_t *mpi_request; | ||
| 1753 | Mpi2DiagReleaseReply_t *mpi_reply; | ||
| 1754 | u16 smid; | ||
| 1755 | u16 ioc_status; | ||
| 1756 | u32 ioc_state; | ||
| 1757 | int rc; | ||
| 1758 | unsigned long timeleft; | ||
| 1759 | |||
| 1760 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | ||
| 1761 | __func__)); | ||
| 1762 | |||
| 1763 | rc = 0; | ||
| 1764 | *issue_reset = 0; | ||
| 1765 | |||
| 1766 | ioc_state = mpt2sas_base_get_iocstate(ioc, 1); | ||
| 1767 | if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { | ||
| 1768 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " | ||
| 1769 | "skipping due to FAULT state\n", ioc->name, | ||
| 1770 | __func__)); | ||
| 1771 | rc = -EAGAIN; | ||
| 1772 | goto out; | ||
| 1773 | } | ||
| 1774 | |||
| 1775 | if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) { | ||
| 1776 | printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n", | ||
| 1777 | ioc->name, __func__); | ||
| 1778 | rc = -EAGAIN; | ||
| 1779 | goto out; | ||
| 1780 | } | ||
| 1781 | |||
| 1782 | smid = mpt2sas_base_get_smid(ioc, ioc->ctl_cb_idx); | ||
| 1783 | if (!smid) { | ||
| 1784 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", | ||
| 1785 | ioc->name, __func__); | ||
| 1786 | rc = -EAGAIN; | ||
| 1787 | goto out; | ||
| 1788 | } | ||
| 1789 | |||
| 1790 | ioc->ctl_cmds.status = MPT2_CMD_PENDING; | ||
| 1791 | memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz); | ||
| 1792 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); | ||
| 1793 | ioc->ctl_cmds.smid = smid; | ||
| 1794 | |||
| 1795 | mpi_request->Function = MPI2_FUNCTION_DIAG_RELEASE; | ||
| 1796 | mpi_request->BufferType = buffer_type; | ||
| 1797 | mpi_request->VF_ID = 0; /* TODO */ | ||
| 1798 | mpi_request->VP_ID = 0; | ||
| 1799 | |||
| 1800 | init_completion(&ioc->ctl_cmds.done); | ||
| 1801 | mpt2sas_base_put_smid_default(ioc, smid); | ||
| 1802 | timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, | ||
| 1803 | MPT2_IOCTL_DEFAULT_TIMEOUT*HZ); | ||
| 1804 | |||
| 1805 | if (!(ioc->ctl_cmds.status & MPT2_CMD_COMPLETE)) { | ||
| 1806 | printk(MPT2SAS_ERR_FMT "%s: timeout\n", ioc->name, | ||
| 1807 | __func__); | ||
| 1808 | _debug_dump_mf(mpi_request, | ||
| 1809 | sizeof(Mpi2DiagReleaseRequest_t)/4); | ||
| 1810 | if (!(ioc->ctl_cmds.status & MPT2_CMD_RESET)) | ||
| 1811 | *issue_reset = 1; | ||
| 1812 | rc = -EFAULT; | ||
| 1813 | goto out; | ||
| 1814 | } | ||
| 1815 | |||
| 1816 | /* process the completed Reply Message Frame */ | ||
| 1817 | if ((ioc->ctl_cmds.status & MPT2_CMD_REPLY_VALID) == 0) { | ||
| 1818 | printk(MPT2SAS_ERR_FMT "%s: no reply message\n", | ||
| 1819 | ioc->name, __func__); | ||
| 1820 | rc = -EFAULT; | ||
| 1821 | goto out; | ||
| 1822 | } | ||
| 1823 | |||
| 1824 | mpi_reply = ioc->ctl_cmds.reply; | ||
| 1825 | ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK; | ||
| 1826 | |||
| 1827 | if (ioc_status == MPI2_IOCSTATUS_SUCCESS) { | ||
| 1828 | ioc->diag_buffer_status[buffer_type] |= | ||
| 1829 | MPT2_DIAG_BUFFER_IS_RELEASED; | ||
| 1830 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: success\n", | ||
| 1831 | ioc->name, __func__)); | ||
| 1832 | } else { | ||
| 1833 | printk(MPT2SAS_INFO_FMT "%s: ioc_status(0x%04x) " | ||
| 1834 | "log_info(0x%08x)\n", ioc->name, __func__, | ||
| 1835 | ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo)); | ||
| 1836 | rc = -EFAULT; | ||
| 1837 | } | ||
| 1838 | |||
| 1839 | out: | ||
| 1840 | ioc->ctl_cmds.status = MPT2_CMD_NOT_USED; | ||
| 1841 | return rc; | ||
| 1842 | } | ||
| 1843 | |||
| 1844 | /** | ||
| 1845 | * _ctl_diag_release - request to send Diag Release Message to firmware | ||
| 1846 | * @arg - user space buffer containing ioctl content | ||
| 1847 | * | ||
| 1848 | * This allows ownership of the specified buffer to returned to the driver, | ||
| 1849 | * allowing an application to read the buffer without fear that firmware is | ||
| 1850 | * overwritting information in the buffer. | ||
| 1851 | */ | ||
| 1852 | static long | ||
| 1853 | _ctl_diag_release(struct MPT2SAS_ADAPTER *ioc, void __user *arg) | ||
| 1854 | { | ||
| 1855 | struct mpt2_diag_release karg; | ||
| 1856 | void *request_data; | ||
| 1857 | int rc; | ||
| 1858 | u8 buffer_type; | ||
| 1859 | u8 issue_reset = 0; | ||
| 1860 | |||
| 1861 | if (copy_from_user(&karg, arg, sizeof(karg))) { | ||
| 1862 | printk(KERN_ERR "failure at %s:%d/%s()!\n", | ||
| 1863 | __FILE__, __LINE__, __func__); | ||
| 1864 | return -EFAULT; | ||
| 1865 | } | ||
| 1866 | |||
| 1867 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | ||
| 1868 | __func__)); | ||
| 1869 | |||
| 1870 | buffer_type = karg.unique_id & 0x000000ff; | ||
| 1871 | if (!_ctl_diag_capability(ioc, buffer_type)) { | ||
| 1872 | printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for " | ||
| 1873 | "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type); | ||
| 1874 | return -EPERM; | ||
| 1875 | } | ||
| 1876 | |||
| 1877 | if ((ioc->diag_buffer_status[buffer_type] & | ||
| 1878 | MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) { | ||
| 1879 | printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) is not " | ||
| 1880 | "registered\n", ioc->name, __func__, buffer_type); | ||
| 1881 | return -EINVAL; | ||
| 1882 | } | ||
| 1883 | |||
| 1884 | if (karg.unique_id != ioc->unique_id[buffer_type]) { | ||
| 1885 | printk(MPT2SAS_ERR_FMT "%s: unique_id(0x%08x) is not " | ||
| 1886 | "registered\n", ioc->name, __func__, karg.unique_id); | ||
| 1887 | return -EINVAL; | ||
| 1888 | } | ||
| 1889 | |||
| 1890 | if (ioc->diag_buffer_status[buffer_type] & | ||
| 1891 | MPT2_DIAG_BUFFER_IS_RELEASED) { | ||
| 1892 | printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) " | ||
| 1893 | "is already released\n", ioc->name, __func__, | ||
| 1894 | buffer_type); | ||
| 1895 | return 0; | ||
| 1896 | } | ||
| 1897 | |||
| 1898 | request_data = ioc->diag_buffer[buffer_type]; | ||
| 1899 | |||
| 1900 | if (!request_data) { | ||
| 1901 | printk(MPT2SAS_ERR_FMT "%s: doesn't have memory allocated for " | ||
| 1902 | "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type); | ||
| 1903 | return -ENOMEM; | ||
| 1904 | } | ||
| 1905 | |||
| 1906 | /* buffers were released by due to host reset */ | ||
| 1907 | if ((ioc->diag_buffer_status[buffer_type] & | ||
| 1908 | MPT2_DIAG_BUFFER_IS_DIAG_RESET)) { | ||
| 1909 | ioc->diag_buffer_status[buffer_type] |= | ||
| 1910 | MPT2_DIAG_BUFFER_IS_RELEASED; | ||
| 1911 | ioc->diag_buffer_status[buffer_type] &= | ||
| 1912 | ~MPT2_DIAG_BUFFER_IS_DIAG_RESET; | ||
| 1913 | printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) " | ||
| 1914 | "was released due to host reset\n", ioc->name, __func__, | ||
| 1915 | buffer_type); | ||
| 1916 | return 0; | ||
| 1917 | } | ||
| 1918 | |||
| 1919 | rc = _ctl_send_release(ioc, buffer_type, &issue_reset); | ||
| 1920 | |||
| 1921 | if (issue_reset) | ||
| 1922 | mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, | ||
| 1923 | FORCE_BIG_HAMMER); | ||
| 1924 | |||
| 1925 | return rc; | ||
| 1926 | } | ||
| 1927 | |||
| 1928 | /** | ||
| 1929 | * _ctl_diag_read_buffer - request for copy of the diag buffer | ||
| 1930 | * @ioc: per adapter object | ||
| 1931 | * @arg - user space buffer containing ioctl content | ||
| 1932 | */ | ||
| 1933 | static long | ||
| 1934 | _ctl_diag_read_buffer(struct MPT2SAS_ADAPTER *ioc, void __user *arg) | ||
| 1935 | { | ||
| 1936 | struct mpt2_diag_read_buffer karg; | ||
| 1937 | struct mpt2_diag_read_buffer __user *uarg = arg; | ||
| 1938 | void *request_data, *diag_data; | ||
| 1939 | Mpi2DiagBufferPostRequest_t *mpi_request; | ||
| 1940 | Mpi2DiagBufferPostReply_t *mpi_reply; | ||
| 1941 | int rc, i; | ||
| 1942 | u8 buffer_type; | ||
| 1943 | unsigned long timeleft, request_size, copy_size; | ||
| 1944 | u16 smid; | ||
| 1945 | u16 ioc_status; | ||
| 1946 | u8 issue_reset = 0; | ||
| 1947 | |||
| 1948 | if (copy_from_user(&karg, arg, sizeof(karg))) { | ||
| 1949 | printk(KERN_ERR "failure at %s:%d/%s()!\n", | ||
| 1950 | __FILE__, __LINE__, __func__); | ||
| 1951 | return -EFAULT; | ||
| 1952 | } | ||
| 1953 | |||
| 1954 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | ||
| 1955 | __func__)); | ||
| 1956 | |||
| 1957 | buffer_type = karg.unique_id & 0x000000ff; | ||
| 1958 | if (!_ctl_diag_capability(ioc, buffer_type)) { | ||
| 1959 | printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for " | ||
| 1960 | "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type); | ||
| 1961 | return -EPERM; | ||
| 1962 | } | ||
| 1963 | |||
| 1964 | if (karg.unique_id != ioc->unique_id[buffer_type]) { | ||
| 1965 | printk(MPT2SAS_ERR_FMT "%s: unique_id(0x%08x) is not " | ||
| 1966 | "registered\n", ioc->name, __func__, karg.unique_id); | ||
| 1967 | return -EINVAL; | ||
| 1968 | } | ||
| 1969 | |||
| 1970 | request_data = ioc->diag_buffer[buffer_type]; | ||
| 1971 | if (!request_data) { | ||
| 1972 | printk(MPT2SAS_ERR_FMT "%s: doesn't have buffer for " | ||
| 1973 | "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type); | ||
| 1974 | return -ENOMEM; | ||
| 1975 | } | ||
| 1976 | |||
| 1977 | request_size = ioc->diag_buffer_sz[buffer_type]; | ||
| 1978 | |||
| 1979 | if ((karg.starting_offset % 4) || (karg.bytes_to_read % 4)) { | ||
| 1980 | printk(MPT2SAS_ERR_FMT "%s: either the starting_offset " | ||
| 1981 | "or bytes_to_read are not 4 byte aligned\n", ioc->name, | ||
| 1982 | __func__); | ||
| 1983 | return -EINVAL; | ||
| 1984 | } | ||
| 1985 | |||
| 1986 | if (karg.starting_offset > request_size) | ||
| 1987 | return -EINVAL; | ||
| 1988 | |||
| 1989 | diag_data = (void *)(request_data + karg.starting_offset); | ||
| 1990 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: diag_buffer(%p), " | ||
| 1991 | "offset(%d), sz(%d)\n", ioc->name, __func__, | ||
| 1992 | diag_data, karg.starting_offset, karg.bytes_to_read)); | ||
| 1993 | |||
| 1994 | /* Truncate data on requests that are too large */ | ||
| 1995 | if ((diag_data + karg.bytes_to_read < diag_data) || | ||
| 1996 | (diag_data + karg.bytes_to_read > request_data + request_size)) | ||
| 1997 | copy_size = request_size - karg.starting_offset; | ||
| 1998 | else | ||
| 1999 | copy_size = karg.bytes_to_read; | ||
| 2000 | |||
| 2001 | if (copy_to_user((void __user *)uarg->diagnostic_data, | ||
| 2002 | diag_data, copy_size)) { | ||
| 2003 | printk(MPT2SAS_ERR_FMT "%s: Unable to write " | ||
| 2004 | "mpt_diag_read_buffer_t data @ %p\n", ioc->name, | ||
| 2005 | __func__, diag_data); | ||
| 2006 | return -EFAULT; | ||
| 2007 | } | ||
| 2008 | |||
| 2009 | if ((karg.flags & MPT2_FLAGS_REREGISTER) == 0) | ||
| 2010 | return 0; | ||
| 2011 | |||
| 2012 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: Reregister " | ||
| 2013 | "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type)); | ||
| 2014 | if ((ioc->diag_buffer_status[buffer_type] & | ||
| 2015 | MPT2_DIAG_BUFFER_IS_RELEASED) == 0) { | ||
| 2016 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " | ||
| 2017 | "buffer_type(0x%02x) is still registered\n", ioc->name, | ||
| 2018 | __func__, buffer_type)); | ||
| 2019 | return 0; | ||
| 2020 | } | ||
| 2021 | /* Get a free request frame and save the message context. | ||
| 2022 | */ | ||
| 2023 | |||
| 2024 | if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) { | ||
| 2025 | printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n", | ||
| 2026 | ioc->name, __func__); | ||
| 2027 | rc = -EAGAIN; | ||
| 2028 | goto out; | ||
| 2029 | } | ||
| 2030 | |||
| 2031 | smid = mpt2sas_base_get_smid(ioc, ioc->ctl_cb_idx); | ||
| 2032 | if (!smid) { | ||
| 2033 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", | ||
| 2034 | ioc->name, __func__); | ||
| 2035 | rc = -EAGAIN; | ||
| 2036 | goto out; | ||
| 2037 | } | ||
| 2038 | |||
| 2039 | rc = 0; | ||
| 2040 | ioc->ctl_cmds.status = MPT2_CMD_PENDING; | ||
| 2041 | memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz); | ||
| 2042 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); | ||
| 2043 | ioc->ctl_cmds.smid = smid; | ||
| 2044 | |||
| 2045 | mpi_request->Function = MPI2_FUNCTION_DIAG_BUFFER_POST; | ||
| 2046 | mpi_request->BufferType = buffer_type; | ||
| 2047 | mpi_request->BufferLength = | ||
| 2048 | cpu_to_le32(ioc->diag_buffer_sz[buffer_type]); | ||
| 2049 | mpi_request->BufferAddress = | ||
| 2050 | cpu_to_le64(ioc->diag_buffer_dma[buffer_type]); | ||
| 2051 | for (i = 0; i < MPT2_PRODUCT_SPECIFIC_DWORDS; i++) | ||
| 2052 | mpi_request->ProductSpecific[i] = | ||
| 2053 | cpu_to_le32(ioc->product_specific[buffer_type][i]); | ||
| 2054 | mpi_request->VF_ID = 0; /* TODO */ | ||
| 2055 | mpi_request->VP_ID = 0; | ||
| 2056 | |||
| 2057 | init_completion(&ioc->ctl_cmds.done); | ||
| 2058 | mpt2sas_base_put_smid_default(ioc, smid); | ||
| 2059 | timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, | ||
| 2060 | MPT2_IOCTL_DEFAULT_TIMEOUT*HZ); | ||
| 2061 | |||
| 2062 | if (!(ioc->ctl_cmds.status & MPT2_CMD_COMPLETE)) { | ||
| 2063 | printk(MPT2SAS_ERR_FMT "%s: timeout\n", ioc->name, | ||
| 2064 | __func__); | ||
| 2065 | _debug_dump_mf(mpi_request, | ||
| 2066 | sizeof(Mpi2DiagBufferPostRequest_t)/4); | ||
| 2067 | if (!(ioc->ctl_cmds.status & MPT2_CMD_RESET)) | ||
| 2068 | issue_reset = 1; | ||
| 2069 | goto issue_host_reset; | ||
| 2070 | } | ||
| 2071 | |||
| 2072 | /* process the completed Reply Message Frame */ | ||
| 2073 | if ((ioc->ctl_cmds.status & MPT2_CMD_REPLY_VALID) == 0) { | ||
| 2074 | printk(MPT2SAS_ERR_FMT "%s: no reply message\n", | ||
| 2075 | ioc->name, __func__); | ||
| 2076 | rc = -EFAULT; | ||
| 2077 | goto out; | ||
| 2078 | } | ||
| 2079 | |||
| 2080 | mpi_reply = ioc->ctl_cmds.reply; | ||
| 2081 | ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK; | ||
| 2082 | |||
| 2083 | if (ioc_status == MPI2_IOCSTATUS_SUCCESS) { | ||
| 2084 | ioc->diag_buffer_status[buffer_type] |= | ||
| 2085 | MPT2_DIAG_BUFFER_IS_REGISTERED; | ||
| 2086 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: success\n", | ||
| 2087 | ioc->name, __func__)); | ||
| 2088 | } else { | ||
| 2089 | printk(MPT2SAS_INFO_FMT "%s: ioc_status(0x%04x) " | ||
| 2090 | "log_info(0x%08x)\n", ioc->name, __func__, | ||
| 2091 | ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo)); | ||
| 2092 | rc = -EFAULT; | ||
| 2093 | } | ||
| 2094 | |||
| 2095 | issue_host_reset: | ||
| 2096 | if (issue_reset) | ||
| 2097 | mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, | ||
| 2098 | FORCE_BIG_HAMMER); | ||
| 2099 | |||
| 2100 | out: | ||
| 2101 | |||
| 2102 | ioc->ctl_cmds.status = MPT2_CMD_NOT_USED; | ||
| 2103 | return rc; | ||
| 2104 | } | ||
| 2105 | |||
| 2106 | |||
| 2107 | #ifdef CONFIG_COMPAT | ||
| 2108 | /** | ||
| 2109 | * _ctl_compat_mpt_command - convert 32bit pointers to 64bit. | ||
| 2110 | * @ioc: per adapter object | ||
| 2111 | * @cmd - ioctl opcode | ||
| 2112 | * @arg - (struct mpt2_ioctl_command32) | ||
| 2113 | * | ||
| 2114 | * MPT2COMMAND32 - Handle 32bit applications running on 64bit os. | ||
| 2115 | */ | ||
| 2116 | static long | ||
| 2117 | _ctl_compat_mpt_command(struct MPT2SAS_ADAPTER *ioc, unsigned cmd, | ||
| 2118 | void __user *arg) | ||
| 2119 | { | ||
| 2120 | struct mpt2_ioctl_command32 karg32; | ||
| 2121 | struct mpt2_ioctl_command32 __user *uarg; | ||
| 2122 | struct mpt2_ioctl_command karg; | ||
| 2123 | |||
| 2124 | if (_IOC_SIZE(cmd) != sizeof(struct mpt2_ioctl_command32)) | ||
| 2125 | return -EINVAL; | ||
| 2126 | |||
| 2127 | uarg = (struct mpt2_ioctl_command32 __user *) arg; | ||
| 2128 | |||
| 2129 | if (copy_from_user(&karg32, (char __user *)arg, sizeof(karg32))) { | ||
| 2130 | printk(KERN_ERR "failure at %s:%d/%s()!\n", | ||
| 2131 | __FILE__, __LINE__, __func__); | ||
| 2132 | return -EFAULT; | ||
| 2133 | } | ||
| 2134 | |||
| 2135 | memset(&karg, 0, sizeof(struct mpt2_ioctl_command)); | ||
| 2136 | karg.hdr.ioc_number = karg32.hdr.ioc_number; | ||
| 2137 | karg.hdr.port_number = karg32.hdr.port_number; | ||
| 2138 | karg.hdr.max_data_size = karg32.hdr.max_data_size; | ||
| 2139 | karg.timeout = karg32.timeout; | ||
| 2140 | karg.max_reply_bytes = karg32.max_reply_bytes; | ||
| 2141 | karg.data_in_size = karg32.data_in_size; | ||
| 2142 | karg.data_out_size = karg32.data_out_size; | ||
| 2143 | karg.max_sense_bytes = karg32.max_sense_bytes; | ||
| 2144 | karg.data_sge_offset = karg32.data_sge_offset; | ||
| 2145 | karg.reply_frame_buf_ptr = compat_ptr(karg32.reply_frame_buf_ptr); | ||
| 2146 | karg.data_in_buf_ptr = compat_ptr(karg32.data_in_buf_ptr); | ||
| 2147 | karg.data_out_buf_ptr = compat_ptr(karg32.data_out_buf_ptr); | ||
| 2148 | karg.sense_data_ptr = compat_ptr(karg32.sense_data_ptr); | ||
| 2149 | return _ctl_do_mpt_command(ioc, karg, &uarg->mf); | ||
| 2150 | } | ||
| 2151 | #endif | ||
| 2152 | |||
| 2153 | /** | ||
| 2154 | * _ctl_ioctl_main - main ioctl entry point | ||
| 2155 | * @file - (struct file) | ||
| 2156 | * @cmd - ioctl opcode | ||
| 2157 | * @arg - | ||
| 2158 | * compat - handles 32 bit applications in 64bit os | ||
| 2159 | */ | ||
| 2160 | static long | ||
| 2161 | _ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg, | ||
| 2162 | u8 compat) | ||
| 2163 | { | ||
| 2164 | struct MPT2SAS_ADAPTER *ioc; | ||
| 2165 | struct mpt2_ioctl_header ioctl_header; | ||
| 2166 | enum block_state state; | ||
| 2167 | long ret = -EINVAL; | ||
| 2168 | |||
| 2169 | /* get IOCTL header */ | ||
| 2170 | if (copy_from_user(&ioctl_header, (char __user *)arg, | ||
| 2171 | sizeof(struct mpt2_ioctl_header))) { | ||
| 2172 | printk(KERN_ERR "failure at %s:%d/%s()!\n", | ||
| 2173 | __FILE__, __LINE__, __func__); | ||
| 2174 | return -EFAULT; | ||
| 2175 | } | ||
| 2176 | |||
| 2177 | if (_ctl_verify_adapter(ioctl_header.ioc_number, &ioc) == -1 || !ioc) | ||
| 2178 | return -ENODEV; | ||
| 2179 | /* pci_access_mutex lock acquired by ioctl path */ | ||
| 2180 | mutex_lock(&ioc->pci_access_mutex); | ||
| 2181 | if (ioc->shost_recovery || ioc->pci_error_recovery || | ||
| 2182 | ioc->is_driver_loading || ioc->remove_host) { | ||
| 2183 | ret = -EAGAIN; | ||
| 2184 | goto out_unlock_pciaccess; | ||
| 2185 | } | ||
| 2186 | |||
| 2187 | state = (file->f_flags & O_NONBLOCK) ? NON_BLOCKING : BLOCKING; | ||
| 2188 | if (state == NON_BLOCKING) { | ||
| 2189 | if (!mutex_trylock(&ioc->ctl_cmds.mutex)) { | ||
| 2190 | ret = -EAGAIN; | ||
| 2191 | goto out_unlock_pciaccess; | ||
| 2192 | } | ||
| 2193 | } else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex)) { | ||
| 2194 | ret = -ERESTARTSYS; | ||
| 2195 | goto out_unlock_pciaccess; | ||
| 2196 | } | ||
| 2197 | |||
| 2198 | switch (cmd) { | ||
| 2199 | case MPT2IOCINFO: | ||
| 2200 | if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_iocinfo)) | ||
| 2201 | ret = _ctl_getiocinfo(ioc, arg); | ||
| 2202 | break; | ||
| 2203 | #ifdef CONFIG_COMPAT | ||
| 2204 | case MPT2COMMAND32: | ||
| 2205 | #endif | ||
| 2206 | case MPT2COMMAND: | ||
| 2207 | { | ||
| 2208 | struct mpt2_ioctl_command __user *uarg; | ||
| 2209 | struct mpt2_ioctl_command karg; | ||
| 2210 | #ifdef CONFIG_COMPAT | ||
| 2211 | if (compat) { | ||
| 2212 | ret = _ctl_compat_mpt_command(ioc, cmd, arg); | ||
| 2213 | break; | ||
| 2214 | } | ||
| 2215 | #endif | ||
| 2216 | if (copy_from_user(&karg, arg, sizeof(karg))) { | ||
| 2217 | printk(KERN_ERR "failure at %s:%d/%s()!\n", | ||
| 2218 | __FILE__, __LINE__, __func__); | ||
| 2219 | ret = -EFAULT; | ||
| 2220 | break; | ||
| 2221 | } | ||
| 2222 | |||
| 2223 | if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_command)) { | ||
| 2224 | uarg = arg; | ||
| 2225 | ret = _ctl_do_mpt_command(ioc, karg, &uarg->mf); | ||
| 2226 | } | ||
| 2227 | break; | ||
| 2228 | } | ||
| 2229 | case MPT2EVENTQUERY: | ||
| 2230 | if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_eventquery)) | ||
| 2231 | ret = _ctl_eventquery(ioc, arg); | ||
| 2232 | break; | ||
| 2233 | case MPT2EVENTENABLE: | ||
| 2234 | if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_eventenable)) | ||
| 2235 | ret = _ctl_eventenable(ioc, arg); | ||
| 2236 | break; | ||
| 2237 | case MPT2EVENTREPORT: | ||
| 2238 | ret = _ctl_eventreport(ioc, arg); | ||
| 2239 | break; | ||
| 2240 | case MPT2HARDRESET: | ||
| 2241 | if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_diag_reset)) | ||
| 2242 | ret = _ctl_do_reset(ioc, arg); | ||
| 2243 | break; | ||
| 2244 | case MPT2BTDHMAPPING: | ||
| 2245 | if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_btdh_mapping)) | ||
| 2246 | ret = _ctl_btdh_mapping(ioc, arg); | ||
| 2247 | break; | ||
| 2248 | case MPT2DIAGREGISTER: | ||
| 2249 | if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_register)) | ||
| 2250 | ret = _ctl_diag_register(ioc, arg); | ||
| 2251 | break; | ||
| 2252 | case MPT2DIAGUNREGISTER: | ||
| 2253 | if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_unregister)) | ||
| 2254 | ret = _ctl_diag_unregister(ioc, arg); | ||
| 2255 | break; | ||
| 2256 | case MPT2DIAGQUERY: | ||
| 2257 | if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_query)) | ||
| 2258 | ret = _ctl_diag_query(ioc, arg); | ||
| 2259 | break; | ||
| 2260 | case MPT2DIAGRELEASE: | ||
| 2261 | if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_release)) | ||
| 2262 | ret = _ctl_diag_release(ioc, arg); | ||
| 2263 | break; | ||
| 2264 | case MPT2DIAGREADBUFFER: | ||
| 2265 | if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_read_buffer)) | ||
| 2266 | ret = _ctl_diag_read_buffer(ioc, arg); | ||
| 2267 | break; | ||
| 2268 | default: | ||
| 2269 | |||
| 2270 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 2271 | "unsupported ioctl opcode(0x%08x)\n", ioc->name, cmd)); | ||
| 2272 | break; | ||
| 2273 | } | ||
| 2274 | |||
| 2275 | mutex_unlock(&ioc->ctl_cmds.mutex); | ||
| 2276 | out_unlock_pciaccess: | ||
| 2277 | mutex_unlock(&ioc->pci_access_mutex); | ||
| 2278 | return ret; | ||
| 2279 | } | ||
| 2280 | |||
| 2281 | /** | ||
| 2282 | * _ctl_ioctl - main ioctl entry point (unlocked) | ||
| 2283 | * @file - (struct file) | ||
| 2284 | * @cmd - ioctl opcode | ||
| 2285 | * @arg - | ||
| 2286 | */ | ||
| 2287 | static long | ||
| 2288 | _ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
| 2289 | { | ||
| 2290 | long ret; | ||
| 2291 | |||
| 2292 | ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 0); | ||
| 2293 | return ret; | ||
| 2294 | } | ||
| 2295 | #ifdef CONFIG_COMPAT | ||
| 2296 | /** | ||
| 2297 | * _ctl_ioctl_compat - main ioctl entry point (compat) | ||
| 2298 | * @file - | ||
| 2299 | * @cmd - | ||
| 2300 | * @arg - | ||
| 2301 | * | ||
| 2302 | * This routine handles 32 bit applications in 64bit os. | ||
| 2303 | */ | ||
| 2304 | static long | ||
| 2305 | _ctl_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg) | ||
| 2306 | { | ||
| 2307 | long ret; | ||
| 2308 | |||
| 2309 | ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 1); | ||
| 2310 | return ret; | ||
| 2311 | } | ||
| 2312 | #endif | ||
| 2313 | |||
| 2314 | /* scsi host attributes */ | ||
| 2315 | |||
| 2316 | /** | ||
| 2317 | * _ctl_version_fw_show - firmware version | ||
| 2318 | * @cdev - pointer to embedded class device | ||
| 2319 | * @buf - the buffer returned | ||
| 2320 | * | ||
| 2321 | * A sysfs 'read-only' shost attribute. | ||
| 2322 | */ | ||
| 2323 | static ssize_t | ||
| 2324 | _ctl_version_fw_show(struct device *cdev, struct device_attribute *attr, | ||
| 2325 | char *buf) | ||
| 2326 | { | ||
| 2327 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
| 2328 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 2329 | |||
| 2330 | return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n", | ||
| 2331 | (ioc->facts.FWVersion.Word & 0xFF000000) >> 24, | ||
| 2332 | (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16, | ||
| 2333 | (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8, | ||
| 2334 | ioc->facts.FWVersion.Word & 0x000000FF); | ||
| 2335 | } | ||
| 2336 | static DEVICE_ATTR(version_fw, S_IRUGO, _ctl_version_fw_show, NULL); | ||
| 2337 | |||
| 2338 | /** | ||
| 2339 | * _ctl_version_bios_show - bios version | ||
| 2340 | * @cdev - pointer to embedded class device | ||
| 2341 | * @buf - the buffer returned | ||
| 2342 | * | ||
| 2343 | * A sysfs 'read-only' shost attribute. | ||
| 2344 | */ | ||
| 2345 | static ssize_t | ||
| 2346 | _ctl_version_bios_show(struct device *cdev, struct device_attribute *attr, | ||
| 2347 | char *buf) | ||
| 2348 | { | ||
| 2349 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
| 2350 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 2351 | |||
| 2352 | u32 version = le32_to_cpu(ioc->bios_pg3.BiosVersion); | ||
| 2353 | |||
| 2354 | return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n", | ||
| 2355 | (version & 0xFF000000) >> 24, | ||
| 2356 | (version & 0x00FF0000) >> 16, | ||
| 2357 | (version & 0x0000FF00) >> 8, | ||
| 2358 | version & 0x000000FF); | ||
| 2359 | } | ||
| 2360 | static DEVICE_ATTR(version_bios, S_IRUGO, _ctl_version_bios_show, NULL); | ||
| 2361 | |||
| 2362 | /** | ||
| 2363 | * _ctl_version_mpi_show - MPI (message passing interface) version | ||
| 2364 | * @cdev - pointer to embedded class device | ||
| 2365 | * @buf - the buffer returned | ||
| 2366 | * | ||
| 2367 | * A sysfs 'read-only' shost attribute. | ||
| 2368 | */ | ||
| 2369 | static ssize_t | ||
| 2370 | _ctl_version_mpi_show(struct device *cdev, struct device_attribute *attr, | ||
| 2371 | char *buf) | ||
| 2372 | { | ||
| 2373 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
| 2374 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 2375 | |||
| 2376 | return snprintf(buf, PAGE_SIZE, "%03x.%02x\n", | ||
| 2377 | ioc->facts.MsgVersion, ioc->facts.HeaderVersion >> 8); | ||
| 2378 | } | ||
| 2379 | static DEVICE_ATTR(version_mpi, S_IRUGO, _ctl_version_mpi_show, NULL); | ||
| 2380 | |||
| 2381 | /** | ||
| 2382 | * _ctl_version_product_show - product name | ||
| 2383 | * @cdev - pointer to embedded class device | ||
| 2384 | * @buf - the buffer returned | ||
| 2385 | * | ||
| 2386 | * A sysfs 'read-only' shost attribute. | ||
| 2387 | */ | ||
| 2388 | static ssize_t | ||
| 2389 | _ctl_version_product_show(struct device *cdev, struct device_attribute *attr, | ||
| 2390 | char *buf) | ||
| 2391 | { | ||
| 2392 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
| 2393 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 2394 | |||
| 2395 | return snprintf(buf, 16, "%s\n", ioc->manu_pg0.ChipName); | ||
| 2396 | } | ||
| 2397 | static DEVICE_ATTR(version_product, S_IRUGO, | ||
| 2398 | _ctl_version_product_show, NULL); | ||
| 2399 | |||
| 2400 | /** | ||
| 2401 | * _ctl_version_nvdata_persistent_show - ndvata persistent version | ||
| 2402 | * @cdev - pointer to embedded class device | ||
| 2403 | * @buf - the buffer returned | ||
| 2404 | * | ||
| 2405 | * A sysfs 'read-only' shost attribute. | ||
| 2406 | */ | ||
| 2407 | static ssize_t | ||
| 2408 | _ctl_version_nvdata_persistent_show(struct device *cdev, | ||
| 2409 | struct device_attribute *attr, char *buf) | ||
| 2410 | { | ||
| 2411 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
| 2412 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 2413 | |||
| 2414 | return snprintf(buf, PAGE_SIZE, "%08xh\n", | ||
| 2415 | le32_to_cpu(ioc->iounit_pg0.NvdataVersionPersistent.Word)); | ||
| 2416 | } | ||
| 2417 | static DEVICE_ATTR(version_nvdata_persistent, S_IRUGO, | ||
| 2418 | _ctl_version_nvdata_persistent_show, NULL); | ||
| 2419 | |||
| 2420 | /** | ||
| 2421 | * _ctl_version_nvdata_default_show - nvdata default version | ||
| 2422 | * @cdev - pointer to embedded class device | ||
| 2423 | * @buf - the buffer returned | ||
| 2424 | * | ||
| 2425 | * A sysfs 'read-only' shost attribute. | ||
| 2426 | */ | ||
| 2427 | static ssize_t | ||
| 2428 | _ctl_version_nvdata_default_show(struct device *cdev, | ||
| 2429 | struct device_attribute *attr, char *buf) | ||
| 2430 | { | ||
| 2431 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
| 2432 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 2433 | |||
| 2434 | return snprintf(buf, PAGE_SIZE, "%08xh\n", | ||
| 2435 | le32_to_cpu(ioc->iounit_pg0.NvdataVersionDefault.Word)); | ||
| 2436 | } | ||
| 2437 | static DEVICE_ATTR(version_nvdata_default, S_IRUGO, | ||
| 2438 | _ctl_version_nvdata_default_show, NULL); | ||
| 2439 | |||
| 2440 | /** | ||
| 2441 | * _ctl_board_name_show - board name | ||
| 2442 | * @cdev - pointer to embedded class device | ||
| 2443 | * @buf - the buffer returned | ||
| 2444 | * | ||
| 2445 | * A sysfs 'read-only' shost attribute. | ||
| 2446 | */ | ||
| 2447 | static ssize_t | ||
| 2448 | _ctl_board_name_show(struct device *cdev, struct device_attribute *attr, | ||
| 2449 | char *buf) | ||
| 2450 | { | ||
| 2451 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
| 2452 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 2453 | |||
| 2454 | return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardName); | ||
| 2455 | } | ||
| 2456 | static DEVICE_ATTR(board_name, S_IRUGO, _ctl_board_name_show, NULL); | ||
| 2457 | |||
| 2458 | /** | ||
| 2459 | * _ctl_board_assembly_show - board assembly name | ||
| 2460 | * @cdev - pointer to embedded class device | ||
| 2461 | * @buf - the buffer returned | ||
| 2462 | * | ||
| 2463 | * A sysfs 'read-only' shost attribute. | ||
| 2464 | */ | ||
| 2465 | static ssize_t | ||
| 2466 | _ctl_board_assembly_show(struct device *cdev, struct device_attribute *attr, | ||
| 2467 | char *buf) | ||
| 2468 | { | ||
| 2469 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
| 2470 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 2471 | |||
| 2472 | return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardAssembly); | ||
| 2473 | } | ||
| 2474 | static DEVICE_ATTR(board_assembly, S_IRUGO, | ||
| 2475 | _ctl_board_assembly_show, NULL); | ||
| 2476 | |||
| 2477 | /** | ||
| 2478 | * _ctl_board_tracer_show - board tracer number | ||
| 2479 | * @cdev - pointer to embedded class device | ||
| 2480 | * @buf - the buffer returned | ||
| 2481 | * | ||
| 2482 | * A sysfs 'read-only' shost attribute. | ||
| 2483 | */ | ||
| 2484 | static ssize_t | ||
| 2485 | _ctl_board_tracer_show(struct device *cdev, struct device_attribute *attr, | ||
| 2486 | char *buf) | ||
| 2487 | { | ||
| 2488 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
| 2489 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 2490 | |||
| 2491 | return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardTracerNumber); | ||
| 2492 | } | ||
| 2493 | static DEVICE_ATTR(board_tracer, S_IRUGO, | ||
| 2494 | _ctl_board_tracer_show, NULL); | ||
| 2495 | |||
| 2496 | /** | ||
| 2497 | * _ctl_io_delay_show - io missing delay | ||
| 2498 | * @cdev - pointer to embedded class device | ||
| 2499 | * @buf - the buffer returned | ||
| 2500 | * | ||
| 2501 | * This is for firmware implemention for deboucing device | ||
| 2502 | * removal events. | ||
| 2503 | * | ||
| 2504 | * A sysfs 'read-only' shost attribute. | ||
| 2505 | */ | ||
| 2506 | static ssize_t | ||
| 2507 | _ctl_io_delay_show(struct device *cdev, struct device_attribute *attr, | ||
| 2508 | char *buf) | ||
| 2509 | { | ||
| 2510 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
| 2511 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 2512 | |||
| 2513 | return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->io_missing_delay); | ||
| 2514 | } | ||
| 2515 | static DEVICE_ATTR(io_delay, S_IRUGO, | ||
| 2516 | _ctl_io_delay_show, NULL); | ||
| 2517 | |||
| 2518 | /** | ||
| 2519 | * _ctl_device_delay_show - device missing delay | ||
| 2520 | * @cdev - pointer to embedded class device | ||
| 2521 | * @buf - the buffer returned | ||
| 2522 | * | ||
| 2523 | * This is for firmware implemention for deboucing device | ||
| 2524 | * removal events. | ||
| 2525 | * | ||
| 2526 | * A sysfs 'read-only' shost attribute. | ||
| 2527 | */ | ||
| 2528 | static ssize_t | ||
| 2529 | _ctl_device_delay_show(struct device *cdev, struct device_attribute *attr, | ||
| 2530 | char *buf) | ||
| 2531 | { | ||
| 2532 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
| 2533 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 2534 | |||
| 2535 | return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->device_missing_delay); | ||
| 2536 | } | ||
| 2537 | static DEVICE_ATTR(device_delay, S_IRUGO, | ||
| 2538 | _ctl_device_delay_show, NULL); | ||
| 2539 | |||
| 2540 | /** | ||
| 2541 | * _ctl_fw_queue_depth_show - global credits | ||
| 2542 | * @cdev - pointer to embedded class device | ||
| 2543 | * @buf - the buffer returned | ||
| 2544 | * | ||
| 2545 | * This is firmware queue depth limit | ||
| 2546 | * | ||
| 2547 | * A sysfs 'read-only' shost attribute. | ||
| 2548 | */ | ||
| 2549 | static ssize_t | ||
| 2550 | _ctl_fw_queue_depth_show(struct device *cdev, struct device_attribute *attr, | ||
| 2551 | char *buf) | ||
| 2552 | { | ||
| 2553 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
| 2554 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 2555 | |||
| 2556 | return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->facts.RequestCredit); | ||
| 2557 | } | ||
| 2558 | static DEVICE_ATTR(fw_queue_depth, S_IRUGO, | ||
| 2559 | _ctl_fw_queue_depth_show, NULL); | ||
| 2560 | |||
| 2561 | /** | ||
| 2562 | * _ctl_sas_address_show - sas address | ||
| 2563 | * @cdev - pointer to embedded class device | ||
| 2564 | * @buf - the buffer returned | ||
| 2565 | * | ||
| 2566 | * This is the controller sas address | ||
| 2567 | * | ||
| 2568 | * A sysfs 'read-only' shost attribute. | ||
| 2569 | */ | ||
| 2570 | static ssize_t | ||
| 2571 | _ctl_host_sas_address_show(struct device *cdev, struct device_attribute *attr, | ||
| 2572 | char *buf) | ||
| 2573 | { | ||
| 2574 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
| 2575 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 2576 | |||
| 2577 | return snprintf(buf, PAGE_SIZE, "0x%016llx\n", | ||
| 2578 | (unsigned long long)ioc->sas_hba.sas_address); | ||
| 2579 | } | ||
| 2580 | static DEVICE_ATTR(host_sas_address, S_IRUGO, | ||
| 2581 | _ctl_host_sas_address_show, NULL); | ||
| 2582 | |||
| 2583 | /** | ||
| 2584 | * _ctl_logging_level_show - logging level | ||
| 2585 | * @cdev - pointer to embedded class device | ||
| 2586 | * @buf - the buffer returned | ||
| 2587 | * | ||
| 2588 | * A sysfs 'read/write' shost attribute. | ||
| 2589 | */ | ||
| 2590 | static ssize_t | ||
| 2591 | _ctl_logging_level_show(struct device *cdev, struct device_attribute *attr, | ||
| 2592 | char *buf) | ||
| 2593 | { | ||
| 2594 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
| 2595 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 2596 | |||
| 2597 | return snprintf(buf, PAGE_SIZE, "%08xh\n", ioc->logging_level); | ||
| 2598 | } | ||
| 2599 | static ssize_t | ||
| 2600 | _ctl_logging_level_store(struct device *cdev, struct device_attribute *attr, | ||
| 2601 | const char *buf, size_t count) | ||
| 2602 | { | ||
| 2603 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
| 2604 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 2605 | int val = 0; | ||
| 2606 | |||
| 2607 | if (sscanf(buf, "%x", &val) != 1) | ||
| 2608 | return -EINVAL; | ||
| 2609 | |||
| 2610 | ioc->logging_level = val; | ||
| 2611 | printk(MPT2SAS_INFO_FMT "logging_level=%08xh\n", ioc->name, | ||
| 2612 | ioc->logging_level); | ||
| 2613 | return strlen(buf); | ||
| 2614 | } | ||
| 2615 | static DEVICE_ATTR(logging_level, S_IRUGO | S_IWUSR, | ||
| 2616 | _ctl_logging_level_show, _ctl_logging_level_store); | ||
| 2617 | |||
| 2618 | /* device attributes */ | ||
| 2619 | /* | ||
| 2620 | * _ctl_fwfault_debug_show - show/store fwfault_debug | ||
| 2621 | * @cdev - pointer to embedded class device | ||
| 2622 | * @buf - the buffer returned | ||
| 2623 | * | ||
| 2624 | * mpt2sas_fwfault_debug is command line option | ||
| 2625 | * A sysfs 'read/write' shost attribute. | ||
| 2626 | */ | ||
| 2627 | static ssize_t | ||
| 2628 | _ctl_fwfault_debug_show(struct device *cdev, | ||
| 2629 | struct device_attribute *attr, char *buf) | ||
| 2630 | { | ||
| 2631 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
| 2632 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 2633 | |||
| 2634 | return snprintf(buf, PAGE_SIZE, "%d\n", ioc->fwfault_debug); | ||
| 2635 | } | ||
| 2636 | static ssize_t | ||
| 2637 | _ctl_fwfault_debug_store(struct device *cdev, | ||
| 2638 | struct device_attribute *attr, const char *buf, size_t count) | ||
| 2639 | { | ||
| 2640 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
| 2641 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 2642 | int val = 0; | ||
| 2643 | |||
| 2644 | if (sscanf(buf, "%d", &val) != 1) | ||
| 2645 | return -EINVAL; | ||
| 2646 | |||
| 2647 | ioc->fwfault_debug = val; | ||
| 2648 | printk(MPT2SAS_INFO_FMT "fwfault_debug=%d\n", ioc->name, | ||
| 2649 | ioc->fwfault_debug); | ||
| 2650 | return strlen(buf); | ||
| 2651 | } | ||
| 2652 | static DEVICE_ATTR(fwfault_debug, S_IRUGO | S_IWUSR, | ||
| 2653 | _ctl_fwfault_debug_show, _ctl_fwfault_debug_store); | ||
| 2654 | |||
| 2655 | |||
| 2656 | /** | ||
| 2657 | * _ctl_ioc_reset_count_show - ioc reset count | ||
| 2658 | * @cdev - pointer to embedded class device | ||
| 2659 | * @buf - the buffer returned | ||
| 2660 | * | ||
| 2661 | * This is firmware queue depth limit | ||
| 2662 | * | ||
| 2663 | * A sysfs 'read-only' shost attribute. | ||
| 2664 | */ | ||
| 2665 | static ssize_t | ||
| 2666 | _ctl_ioc_reset_count_show(struct device *cdev, struct device_attribute *attr, | ||
| 2667 | char *buf) | ||
| 2668 | { | ||
| 2669 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
| 2670 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 2671 | |||
| 2672 | return snprintf(buf, PAGE_SIZE, "%08d\n", ioc->ioc_reset_count); | ||
| 2673 | } | ||
| 2674 | static DEVICE_ATTR(ioc_reset_count, S_IRUGO, | ||
| 2675 | _ctl_ioc_reset_count_show, NULL); | ||
| 2676 | |||
| 2677 | /** | ||
| 2678 | * _ctl_ioc_reply_queue_count_show - number of reply queues | ||
| 2679 | * @cdev - pointer to embedded class device | ||
| 2680 | * @buf - the buffer returned | ||
| 2681 | * | ||
| 2682 | * This is number of reply queues | ||
| 2683 | * | ||
| 2684 | * A sysfs 'read-only' shost attribute. | ||
| 2685 | */ | ||
| 2686 | static ssize_t | ||
| 2687 | _ctl_ioc_reply_queue_count_show(struct device *cdev, | ||
| 2688 | struct device_attribute *attr, char *buf) | ||
| 2689 | { | ||
| 2690 | u8 reply_queue_count; | ||
| 2691 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
| 2692 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 2693 | |||
| 2694 | if ((ioc->facts.IOCCapabilities & | ||
| 2695 | MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX) && ioc->msix_enable) | ||
| 2696 | reply_queue_count = ioc->reply_queue_count; | ||
| 2697 | else | ||
| 2698 | reply_queue_count = 1; | ||
| 2699 | return snprintf(buf, PAGE_SIZE, "%d\n", reply_queue_count); | ||
| 2700 | } | ||
| 2701 | static DEVICE_ATTR(reply_queue_count, S_IRUGO, | ||
| 2702 | _ctl_ioc_reply_queue_count_show, NULL); | ||
| 2703 | |||
| 2704 | /** | ||
| 2705 | * _ctl_BRM_status_show - Backup Rail Monitor Status | ||
| 2706 | * @cdev - pointer to embedded class device | ||
| 2707 | * @buf - the buffer returned | ||
| 2708 | * | ||
| 2709 | * This is number of reply queues | ||
| 2710 | * | ||
| 2711 | * A sysfs 'read-only' shost attribute. | ||
| 2712 | */ | ||
| 2713 | static ssize_t | ||
| 2714 | _ctl_BRM_status_show(struct device *cdev, struct device_attribute *attr, | ||
| 2715 | char *buf) | ||
| 2716 | { | ||
| 2717 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
| 2718 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 2719 | Mpi2IOUnitPage3_t *io_unit_pg3 = NULL; | ||
| 2720 | Mpi2ConfigReply_t mpi_reply; | ||
| 2721 | u16 backup_rail_monitor_status = 0; | ||
| 2722 | u16 ioc_status; | ||
| 2723 | int sz; | ||
| 2724 | ssize_t rc = 0; | ||
| 2725 | |||
| 2726 | if (!ioc->is_warpdrive) { | ||
| 2727 | printk(MPT2SAS_ERR_FMT "%s: BRM attribute is only for"\ | ||
| 2728 | "warpdrive\n", ioc->name, __func__); | ||
| 2729 | goto out; | ||
| 2730 | } | ||
| 2731 | /* pci_access_mutex lock acquired by sysfs show path */ | ||
| 2732 | mutex_lock(&ioc->pci_access_mutex); | ||
| 2733 | if (ioc->pci_error_recovery || ioc->remove_host) { | ||
| 2734 | mutex_unlock(&ioc->pci_access_mutex); | ||
| 2735 | return 0; | ||
| 2736 | } | ||
| 2737 | |||
| 2738 | /* allocate upto GPIOVal 36 entries */ | ||
| 2739 | sz = offsetof(Mpi2IOUnitPage3_t, GPIOVal) + (sizeof(u16) * 36); | ||
| 2740 | io_unit_pg3 = kzalloc(sz, GFP_KERNEL); | ||
| 2741 | if (!io_unit_pg3) { | ||
| 2742 | printk(MPT2SAS_ERR_FMT "%s: failed allocating memory"\ | ||
| 2743 | "for iounit_pg3: (%d) bytes\n", ioc->name, __func__, sz); | ||
| 2744 | goto out; | ||
| 2745 | } | ||
| 2746 | |||
| 2747 | if (mpt2sas_config_get_iounit_pg3(ioc, &mpi_reply, io_unit_pg3, sz) != | ||
| 2748 | 0) { | ||
| 2749 | printk(MPT2SAS_ERR_FMT | ||
| 2750 | "%s: failed reading iounit_pg3\n", ioc->name, | ||
| 2751 | __func__); | ||
| 2752 | goto out; | ||
| 2753 | } | ||
| 2754 | |||
| 2755 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; | ||
| 2756 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { | ||
| 2757 | printk(MPT2SAS_ERR_FMT "%s: iounit_pg3 failed with"\ | ||
| 2758 | "ioc_status(0x%04x)\n", ioc->name, __func__, ioc_status); | ||
| 2759 | goto out; | ||
| 2760 | } | ||
| 2761 | |||
| 2762 | if (io_unit_pg3->GPIOCount < 25) { | ||
| 2763 | printk(MPT2SAS_ERR_FMT "%s: iounit_pg3->GPIOCount less than"\ | ||
| 2764 | "25 entries, detected (%d) entries\n", ioc->name, __func__, | ||
| 2765 | io_unit_pg3->GPIOCount); | ||
| 2766 | goto out; | ||
| 2767 | } | ||
| 2768 | |||
| 2769 | /* BRM status is in bit zero of GPIOVal[24] */ | ||
| 2770 | backup_rail_monitor_status = le16_to_cpu(io_unit_pg3->GPIOVal[24]); | ||
| 2771 | rc = snprintf(buf, PAGE_SIZE, "%d\n", (backup_rail_monitor_status & 1)); | ||
| 2772 | |||
| 2773 | out: | ||
| 2774 | kfree(io_unit_pg3); | ||
| 2775 | mutex_unlock(&ioc->pci_access_mutex); | ||
| 2776 | return rc; | ||
| 2777 | } | ||
| 2778 | static DEVICE_ATTR(BRM_status, S_IRUGO, _ctl_BRM_status_show, NULL); | ||
| 2779 | |||
| 2780 | struct DIAG_BUFFER_START { | ||
| 2781 | __le32 Size; | ||
| 2782 | __le32 DiagVersion; | ||
| 2783 | u8 BufferType; | ||
| 2784 | u8 Reserved[3]; | ||
| 2785 | __le32 Reserved1; | ||
| 2786 | __le32 Reserved2; | ||
| 2787 | __le32 Reserved3; | ||
| 2788 | }; | ||
| 2789 | /** | ||
| 2790 | * _ctl_host_trace_buffer_size_show - host buffer size (trace only) | ||
| 2791 | * @cdev - pointer to embedded class device | ||
| 2792 | * @buf - the buffer returned | ||
| 2793 | * | ||
| 2794 | * A sysfs 'read-only' shost attribute. | ||
| 2795 | */ | ||
| 2796 | static ssize_t | ||
| 2797 | _ctl_host_trace_buffer_size_show(struct device *cdev, | ||
| 2798 | struct device_attribute *attr, char *buf) | ||
| 2799 | { | ||
| 2800 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
| 2801 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 2802 | u32 size = 0; | ||
| 2803 | struct DIAG_BUFFER_START *request_data; | ||
| 2804 | |||
| 2805 | if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) { | ||
| 2806 | printk(MPT2SAS_ERR_FMT "%s: host_trace_buffer is not " | ||
| 2807 | "registered\n", ioc->name, __func__); | ||
| 2808 | return 0; | ||
| 2809 | } | ||
| 2810 | |||
| 2811 | if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & | ||
| 2812 | MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) { | ||
| 2813 | printk(MPT2SAS_ERR_FMT "%s: host_trace_buffer is not " | ||
| 2814 | "registered\n", ioc->name, __func__); | ||
| 2815 | return 0; | ||
| 2816 | } | ||
| 2817 | |||
| 2818 | request_data = (struct DIAG_BUFFER_START *) | ||
| 2819 | ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]; | ||
| 2820 | if ((le32_to_cpu(request_data->DiagVersion) == 0x00000000 || | ||
| 2821 | le32_to_cpu(request_data->DiagVersion) == 0x01000000) && | ||
| 2822 | le32_to_cpu(request_data->Reserved3) == 0x4742444c) | ||
| 2823 | size = le32_to_cpu(request_data->Size); | ||
| 2824 | |||
| 2825 | ioc->ring_buffer_sz = size; | ||
| 2826 | return snprintf(buf, PAGE_SIZE, "%d\n", size); | ||
| 2827 | } | ||
| 2828 | static DEVICE_ATTR(host_trace_buffer_size, S_IRUGO, | ||
| 2829 | _ctl_host_trace_buffer_size_show, NULL); | ||
| 2830 | |||
| 2831 | /** | ||
| 2832 | * _ctl_host_trace_buffer_show - firmware ring buffer (trace only) | ||
| 2833 | * @cdev - pointer to embedded class device | ||
| 2834 | * @buf - the buffer returned | ||
| 2835 | * | ||
| 2836 | * A sysfs 'read/write' shost attribute. | ||
| 2837 | * | ||
| 2838 | * You will only be able to read 4k bytes of ring buffer at a time. | ||
| 2839 | * In order to read beyond 4k bytes, you will have to write out the | ||
| 2840 | * offset to the same attribute, it will move the pointer. | ||
| 2841 | */ | ||
| 2842 | static ssize_t | ||
| 2843 | _ctl_host_trace_buffer_show(struct device *cdev, struct device_attribute *attr, | ||
| 2844 | char *buf) | ||
| 2845 | { | ||
| 2846 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
| 2847 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 2848 | void *request_data; | ||
| 2849 | u32 size; | ||
| 2850 | |||
| 2851 | if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) { | ||
| 2852 | printk(MPT2SAS_ERR_FMT "%s: host_trace_buffer is not " | ||
| 2853 | "registered\n", ioc->name, __func__); | ||
| 2854 | return 0; | ||
| 2855 | } | ||
| 2856 | |||
| 2857 | if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & | ||
| 2858 | MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) { | ||
| 2859 | printk(MPT2SAS_ERR_FMT "%s: host_trace_buffer is not " | ||
| 2860 | "registered\n", ioc->name, __func__); | ||
| 2861 | return 0; | ||
| 2862 | } | ||
| 2863 | |||
| 2864 | if (ioc->ring_buffer_offset > ioc->ring_buffer_sz) | ||
| 2865 | return 0; | ||
| 2866 | |||
| 2867 | size = ioc->ring_buffer_sz - ioc->ring_buffer_offset; | ||
| 2868 | size = (size > PAGE_SIZE) ? PAGE_SIZE : size; | ||
| 2869 | request_data = ioc->diag_buffer[0] + ioc->ring_buffer_offset; | ||
| 2870 | memcpy(buf, request_data, size); | ||
| 2871 | return size; | ||
| 2872 | } | ||
| 2873 | |||
| 2874 | static ssize_t | ||
| 2875 | _ctl_host_trace_buffer_store(struct device *cdev, struct device_attribute *attr, | ||
| 2876 | const char *buf, size_t count) | ||
| 2877 | { | ||
| 2878 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
| 2879 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 2880 | int val = 0; | ||
| 2881 | |||
| 2882 | if (sscanf(buf, "%d", &val) != 1) | ||
| 2883 | return -EINVAL; | ||
| 2884 | |||
| 2885 | ioc->ring_buffer_offset = val; | ||
| 2886 | return strlen(buf); | ||
| 2887 | } | ||
| 2888 | static DEVICE_ATTR(host_trace_buffer, S_IRUGO | S_IWUSR, | ||
| 2889 | _ctl_host_trace_buffer_show, _ctl_host_trace_buffer_store); | ||
| 2890 | |||
| 2891 | /*****************************************/ | ||
| 2892 | |||
| 2893 | /** | ||
| 2894 | * _ctl_host_trace_buffer_enable_show - firmware ring buffer (trace only) | ||
| 2895 | * @cdev - pointer to embedded class device | ||
| 2896 | * @buf - the buffer returned | ||
| 2897 | * | ||
| 2898 | * A sysfs 'read/write' shost attribute. | ||
| 2899 | * | ||
| 2900 | * This is a mechnism to post/release host_trace_buffers | ||
| 2901 | */ | ||
| 2902 | static ssize_t | ||
| 2903 | _ctl_host_trace_buffer_enable_show(struct device *cdev, | ||
| 2904 | struct device_attribute *attr, char *buf) | ||
| 2905 | { | ||
| 2906 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
| 2907 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 2908 | |||
| 2909 | if ((!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) || | ||
| 2910 | ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & | ||
| 2911 | MPT2_DIAG_BUFFER_IS_REGISTERED) == 0)) | ||
| 2912 | return snprintf(buf, PAGE_SIZE, "off\n"); | ||
| 2913 | else if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & | ||
| 2914 | MPT2_DIAG_BUFFER_IS_RELEASED)) | ||
| 2915 | return snprintf(buf, PAGE_SIZE, "release\n"); | ||
| 2916 | else | ||
| 2917 | return snprintf(buf, PAGE_SIZE, "post\n"); | ||
| 2918 | } | ||
| 2919 | |||
| 2920 | static ssize_t | ||
| 2921 | _ctl_host_trace_buffer_enable_store(struct device *cdev, | ||
| 2922 | struct device_attribute *attr, const char *buf, size_t count) | ||
| 2923 | { | ||
| 2924 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
| 2925 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 2926 | char str[10] = ""; | ||
| 2927 | struct mpt2_diag_register diag_register; | ||
| 2928 | u8 issue_reset = 0; | ||
| 2929 | |||
| 2930 | if (sscanf(buf, "%9s", str) != 1) | ||
| 2931 | return -EINVAL; | ||
| 2932 | |||
| 2933 | if (!strcmp(str, "post")) { | ||
| 2934 | /* exit out if host buffers are already posted */ | ||
| 2935 | if ((ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) && | ||
| 2936 | (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & | ||
| 2937 | MPT2_DIAG_BUFFER_IS_REGISTERED) && | ||
| 2938 | ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & | ||
| 2939 | MPT2_DIAG_BUFFER_IS_RELEASED) == 0)) | ||
| 2940 | goto out; | ||
| 2941 | memset(&diag_register, 0, sizeof(struct mpt2_diag_register)); | ||
| 2942 | printk(MPT2SAS_INFO_FMT "posting host trace buffers\n", | ||
| 2943 | ioc->name); | ||
| 2944 | diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_TRACE; | ||
| 2945 | diag_register.requested_buffer_size = (1024 * 1024); | ||
| 2946 | diag_register.unique_id = 0x7075900; | ||
| 2947 | ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] = 0; | ||
| 2948 | _ctl_diag_register_2(ioc, &diag_register); | ||
| 2949 | } else if (!strcmp(str, "release")) { | ||
| 2950 | /* exit out if host buffers are already released */ | ||
| 2951 | if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) | ||
| 2952 | goto out; | ||
| 2953 | if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & | ||
| 2954 | MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) | ||
| 2955 | goto out; | ||
| 2956 | if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & | ||
| 2957 | MPT2_DIAG_BUFFER_IS_RELEASED)) | ||
| 2958 | goto out; | ||
| 2959 | printk(MPT2SAS_INFO_FMT "releasing host trace buffer\n", | ||
| 2960 | ioc->name); | ||
| 2961 | _ctl_send_release(ioc, MPI2_DIAG_BUF_TYPE_TRACE, &issue_reset); | ||
| 2962 | } | ||
| 2963 | |||
| 2964 | out: | ||
| 2965 | return strlen(buf); | ||
| 2966 | } | ||
| 2967 | static DEVICE_ATTR(host_trace_buffer_enable, S_IRUGO | S_IWUSR, | ||
| 2968 | _ctl_host_trace_buffer_enable_show, _ctl_host_trace_buffer_enable_store); | ||
| 2969 | |||
| 2970 | struct device_attribute *mpt2sas_host_attrs[] = { | ||
| 2971 | &dev_attr_version_fw, | ||
| 2972 | &dev_attr_version_bios, | ||
| 2973 | &dev_attr_version_mpi, | ||
| 2974 | &dev_attr_version_product, | ||
| 2975 | &dev_attr_version_nvdata_persistent, | ||
| 2976 | &dev_attr_version_nvdata_default, | ||
| 2977 | &dev_attr_board_name, | ||
| 2978 | &dev_attr_board_assembly, | ||
| 2979 | &dev_attr_board_tracer, | ||
| 2980 | &dev_attr_io_delay, | ||
| 2981 | &dev_attr_device_delay, | ||
| 2982 | &dev_attr_logging_level, | ||
| 2983 | &dev_attr_fwfault_debug, | ||
| 2984 | &dev_attr_fw_queue_depth, | ||
| 2985 | &dev_attr_host_sas_address, | ||
| 2986 | &dev_attr_ioc_reset_count, | ||
| 2987 | &dev_attr_host_trace_buffer_size, | ||
| 2988 | &dev_attr_host_trace_buffer, | ||
| 2989 | &dev_attr_host_trace_buffer_enable, | ||
| 2990 | &dev_attr_reply_queue_count, | ||
| 2991 | &dev_attr_BRM_status, | ||
| 2992 | NULL, | ||
| 2993 | }; | ||
| 2994 | |||
| 2995 | /** | ||
| 2996 | * _ctl_device_sas_address_show - sas address | ||
| 2997 | * @cdev - pointer to embedded class device | ||
| 2998 | * @buf - the buffer returned | ||
| 2999 | * | ||
| 3000 | * This is the sas address for the target | ||
| 3001 | * | ||
| 3002 | * A sysfs 'read-only' shost attribute. | ||
| 3003 | */ | ||
| 3004 | static ssize_t | ||
| 3005 | _ctl_device_sas_address_show(struct device *dev, struct device_attribute *attr, | ||
| 3006 | char *buf) | ||
| 3007 | { | ||
| 3008 | struct scsi_device *sdev = to_scsi_device(dev); | ||
| 3009 | struct MPT2SAS_DEVICE *sas_device_priv_data = sdev->hostdata; | ||
| 3010 | |||
| 3011 | return snprintf(buf, PAGE_SIZE, "0x%016llx\n", | ||
| 3012 | (unsigned long long)sas_device_priv_data->sas_target->sas_address); | ||
| 3013 | } | ||
| 3014 | static DEVICE_ATTR(sas_address, S_IRUGO, _ctl_device_sas_address_show, NULL); | ||
| 3015 | |||
| 3016 | /** | ||
| 3017 | * _ctl_device_handle_show - device handle | ||
| 3018 | * @cdev - pointer to embedded class device | ||
| 3019 | * @buf - the buffer returned | ||
| 3020 | * | ||
| 3021 | * This is the firmware assigned device handle | ||
| 3022 | * | ||
| 3023 | * A sysfs 'read-only' shost attribute. | ||
| 3024 | */ | ||
| 3025 | static ssize_t | ||
| 3026 | _ctl_device_handle_show(struct device *dev, struct device_attribute *attr, | ||
| 3027 | char *buf) | ||
| 3028 | { | ||
| 3029 | struct scsi_device *sdev = to_scsi_device(dev); | ||
| 3030 | struct MPT2SAS_DEVICE *sas_device_priv_data = sdev->hostdata; | ||
| 3031 | |||
| 3032 | return snprintf(buf, PAGE_SIZE, "0x%04x\n", | ||
| 3033 | sas_device_priv_data->sas_target->handle); | ||
| 3034 | } | ||
| 3035 | static DEVICE_ATTR(sas_device_handle, S_IRUGO, _ctl_device_handle_show, NULL); | ||
| 3036 | |||
| 3037 | struct device_attribute *mpt2sas_dev_attrs[] = { | ||
| 3038 | &dev_attr_sas_address, | ||
| 3039 | &dev_attr_sas_device_handle, | ||
| 3040 | NULL, | ||
| 3041 | }; | ||
| 3042 | |||
| 3043 | static const struct file_operations ctl_fops = { | ||
| 3044 | .owner = THIS_MODULE, | ||
| 3045 | .unlocked_ioctl = _ctl_ioctl, | ||
| 3046 | .poll = _ctl_poll, | ||
| 3047 | .fasync = _ctl_fasync, | ||
| 3048 | #ifdef CONFIG_COMPAT | ||
| 3049 | .compat_ioctl = _ctl_ioctl_compat, | ||
| 3050 | #endif | ||
| 3051 | .llseek = noop_llseek, | ||
| 3052 | }; | ||
| 3053 | |||
| 3054 | static struct miscdevice ctl_dev = { | ||
| 3055 | .minor = MPT2SAS_MINOR, | ||
| 3056 | .name = MPT2SAS_DEV_NAME, | ||
| 3057 | .fops = &ctl_fops, | ||
| 3058 | }; | ||
| 3059 | |||
| 3060 | /** | ||
| 3061 | * mpt2sas_ctl_init - main entry point for ctl. | ||
| 3062 | * | ||
| 3063 | */ | ||
| 3064 | void | ||
| 3065 | mpt2sas_ctl_init(void) | ||
| 3066 | { | ||
| 3067 | async_queue = NULL; | ||
| 3068 | if (misc_register(&ctl_dev) < 0) | ||
| 3069 | printk(KERN_ERR "%s can't register misc device [minor=%d]\n", | ||
| 3070 | MPT2SAS_DRIVER_NAME, MPT2SAS_MINOR); | ||
| 3071 | |||
| 3072 | init_waitqueue_head(&ctl_poll_wait); | ||
| 3073 | } | ||
| 3074 | |||
| 3075 | /** | ||
| 3076 | * mpt2sas_ctl_exit - exit point for ctl | ||
| 3077 | * | ||
| 3078 | */ | ||
| 3079 | void | ||
| 3080 | mpt2sas_ctl_exit(void) | ||
| 3081 | { | ||
| 3082 | struct MPT2SAS_ADAPTER *ioc; | ||
| 3083 | int i; | ||
| 3084 | |||
| 3085 | list_for_each_entry(ioc, &mpt2sas_ioc_list, list) { | ||
| 3086 | |||
| 3087 | /* free memory associated to diag buffers */ | ||
| 3088 | for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) { | ||
| 3089 | if (!ioc->diag_buffer[i]) | ||
| 3090 | continue; | ||
| 3091 | pci_free_consistent(ioc->pdev, ioc->diag_buffer_sz[i], | ||
| 3092 | ioc->diag_buffer[i], ioc->diag_buffer_dma[i]); | ||
| 3093 | ioc->diag_buffer[i] = NULL; | ||
| 3094 | ioc->diag_buffer_status[i] = 0; | ||
| 3095 | } | ||
| 3096 | |||
| 3097 | kfree(ioc->event_log); | ||
| 3098 | } | ||
| 3099 | misc_deregister(&ctl_dev); | ||
| 3100 | } | ||
| 3101 | |||
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.h b/drivers/scsi/mpt2sas/mpt2sas_ctl.h deleted file mode 100644 index 46b2fc5b74af..000000000000 --- a/drivers/scsi/mpt2sas/mpt2sas_ctl.h +++ /dev/null | |||
| @@ -1,419 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Management Module Support for MPT (Message Passing Technology) based | ||
| 3 | * controllers | ||
| 4 | * | ||
| 5 | * This code is based on drivers/scsi/mpt2sas/mpt2_ctl.h | ||
| 6 | * Copyright (C) 2007-2014 LSI Corporation | ||
| 7 | * Copyright (C) 20013-2014 Avago Technologies | ||
| 8 | * (mailto: MPT-FusionLinux.pdl@avagotech.com) | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or | ||
| 11 | * modify it under the terms of the GNU General Public License | ||
| 12 | * as published by the Free Software Foundation; either version 2 | ||
| 13 | * of the License, or (at your option) any later version. | ||
| 14 | * | ||
| 15 | * This program is distributed in the hope that it will be useful, | ||
| 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | * GNU General Public License for more details. | ||
| 19 | * | ||
| 20 | * NO WARRANTY | ||
| 21 | * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR | ||
| 22 | * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT | ||
| 23 | * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, | ||
| 24 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is | ||
| 25 | * solely responsible for determining the appropriateness of using and | ||
| 26 | * distributing the Program and assumes all risks associated with its | ||
| 27 | * exercise of rights under this Agreement, including but not limited to | ||
| 28 | * the risks and costs of program errors, damage to or loss of data, | ||
| 29 | * programs or equipment, and unavailability or interruption of operations. | ||
| 30 | |||
| 31 | * DISCLAIMER OF LIABILITY | ||
| 32 | * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY | ||
| 33 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 34 | * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND | ||
| 35 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR | ||
| 36 | * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | ||
| 37 | * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED | ||
| 38 | * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES | ||
| 39 | |||
| 40 | * You should have received a copy of the GNU General Public License | ||
| 41 | * along with this program; if not, write to the Free Software | ||
| 42 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
| 43 | * USA. | ||
| 44 | */ | ||
| 45 | |||
| 46 | #ifndef MPT2SAS_CTL_H_INCLUDED | ||
| 47 | #define MPT2SAS_CTL_H_INCLUDED | ||
| 48 | |||
| 49 | #ifdef __KERNEL__ | ||
| 50 | #include <linux/miscdevice.h> | ||
| 51 | #endif | ||
| 52 | |||
| 53 | #define MPT2SAS_DEV_NAME "mpt2ctl" | ||
| 54 | #define MPT2_MAGIC_NUMBER 'L' | ||
| 55 | #define MPT2_IOCTL_DEFAULT_TIMEOUT (10) /* in seconds */ | ||
| 56 | |||
| 57 | /** | ||
| 58 | * IOCTL opcodes | ||
| 59 | */ | ||
| 60 | #define MPT2IOCINFO _IOWR(MPT2_MAGIC_NUMBER, 17, \ | ||
| 61 | struct mpt2_ioctl_iocinfo) | ||
| 62 | #define MPT2COMMAND _IOWR(MPT2_MAGIC_NUMBER, 20, \ | ||
| 63 | struct mpt2_ioctl_command) | ||
| 64 | #ifdef CONFIG_COMPAT | ||
| 65 | #define MPT2COMMAND32 _IOWR(MPT2_MAGIC_NUMBER, 20, \ | ||
| 66 | struct mpt2_ioctl_command32) | ||
| 67 | #endif | ||
| 68 | #define MPT2EVENTQUERY _IOWR(MPT2_MAGIC_NUMBER, 21, \ | ||
| 69 | struct mpt2_ioctl_eventquery) | ||
| 70 | #define MPT2EVENTENABLE _IOWR(MPT2_MAGIC_NUMBER, 22, \ | ||
| 71 | struct mpt2_ioctl_eventenable) | ||
| 72 | #define MPT2EVENTREPORT _IOWR(MPT2_MAGIC_NUMBER, 23, \ | ||
| 73 | struct mpt2_ioctl_eventreport) | ||
| 74 | #define MPT2HARDRESET _IOWR(MPT2_MAGIC_NUMBER, 24, \ | ||
| 75 | struct mpt2_ioctl_diag_reset) | ||
| 76 | #define MPT2BTDHMAPPING _IOWR(MPT2_MAGIC_NUMBER, 31, \ | ||
| 77 | struct mpt2_ioctl_btdh_mapping) | ||
| 78 | |||
| 79 | /* diag buffer support */ | ||
| 80 | #define MPT2DIAGREGISTER _IOWR(MPT2_MAGIC_NUMBER, 26, \ | ||
| 81 | struct mpt2_diag_register) | ||
| 82 | #define MPT2DIAGRELEASE _IOWR(MPT2_MAGIC_NUMBER, 27, \ | ||
| 83 | struct mpt2_diag_release) | ||
| 84 | #define MPT2DIAGUNREGISTER _IOWR(MPT2_MAGIC_NUMBER, 28, \ | ||
| 85 | struct mpt2_diag_unregister) | ||
| 86 | #define MPT2DIAGQUERY _IOWR(MPT2_MAGIC_NUMBER, 29, \ | ||
| 87 | struct mpt2_diag_query) | ||
| 88 | #define MPT2DIAGREADBUFFER _IOWR(MPT2_MAGIC_NUMBER, 30, \ | ||
| 89 | struct mpt2_diag_read_buffer) | ||
| 90 | |||
| 91 | /** | ||
| 92 | * struct mpt2_ioctl_header - main header structure | ||
| 93 | * @ioc_number - IOC unit number | ||
| 94 | * @port_number - IOC port number | ||
| 95 | * @max_data_size - maximum number bytes to transfer on read | ||
| 96 | */ | ||
| 97 | struct mpt2_ioctl_header { | ||
| 98 | uint32_t ioc_number; | ||
| 99 | uint32_t port_number; | ||
| 100 | uint32_t max_data_size; | ||
| 101 | }; | ||
| 102 | |||
| 103 | /** | ||
| 104 | * struct mpt2_ioctl_diag_reset - diagnostic reset | ||
| 105 | * @hdr - generic header | ||
| 106 | */ | ||
| 107 | struct mpt2_ioctl_diag_reset { | ||
| 108 | struct mpt2_ioctl_header hdr; | ||
| 109 | }; | ||
| 110 | |||
| 111 | |||
| 112 | /** | ||
| 113 | * struct mpt2_ioctl_pci_info - pci device info | ||
| 114 | * @device - pci device id | ||
| 115 | * @function - pci function id | ||
| 116 | * @bus - pci bus id | ||
| 117 | * @segment_id - pci segment id | ||
| 118 | */ | ||
| 119 | struct mpt2_ioctl_pci_info { | ||
| 120 | union { | ||
| 121 | struct { | ||
| 122 | uint32_t device:5; | ||
| 123 | uint32_t function:3; | ||
| 124 | uint32_t bus:24; | ||
| 125 | } bits; | ||
| 126 | uint32_t word; | ||
| 127 | } u; | ||
| 128 | uint32_t segment_id; | ||
| 129 | }; | ||
| 130 | |||
| 131 | |||
| 132 | #define MPT2_IOCTL_INTERFACE_SCSI (0x00) | ||
| 133 | #define MPT2_IOCTL_INTERFACE_FC (0x01) | ||
| 134 | #define MPT2_IOCTL_INTERFACE_FC_IP (0x02) | ||
| 135 | #define MPT2_IOCTL_INTERFACE_SAS (0x03) | ||
| 136 | #define MPT2_IOCTL_INTERFACE_SAS2 (0x04) | ||
| 137 | #define MPT2_IOCTL_INTERFACE_SAS2_SSS6200 (0x05) | ||
| 138 | #define MPT2_IOCTL_VERSION_LENGTH (32) | ||
| 139 | |||
| 140 | /** | ||
| 141 | * struct mpt2_ioctl_iocinfo - generic controller info | ||
| 142 | * @hdr - generic header | ||
| 143 | * @adapter_type - type of adapter (spi, fc, sas) | ||
| 144 | * @port_number - port number | ||
| 145 | * @pci_id - PCI Id | ||
| 146 | * @hw_rev - hardware revision | ||
| 147 | * @sub_system_device - PCI subsystem Device ID | ||
| 148 | * @sub_system_vendor - PCI subsystem Vendor ID | ||
| 149 | * @rsvd0 - reserved | ||
| 150 | * @firmware_version - firmware version | ||
| 151 | * @bios_version - BIOS version | ||
| 152 | * @driver_version - driver version - 32 ASCII characters | ||
| 153 | * @rsvd1 - reserved | ||
| 154 | * @scsi_id - scsi id of adapter 0 | ||
| 155 | * @rsvd2 - reserved | ||
| 156 | * @pci_information - pci info (2nd revision) | ||
| 157 | */ | ||
| 158 | struct mpt2_ioctl_iocinfo { | ||
| 159 | struct mpt2_ioctl_header hdr; | ||
| 160 | uint32_t adapter_type; | ||
| 161 | uint32_t port_number; | ||
| 162 | uint32_t pci_id; | ||
| 163 | uint32_t hw_rev; | ||
| 164 | uint32_t subsystem_device; | ||
| 165 | uint32_t subsystem_vendor; | ||
| 166 | uint32_t rsvd0; | ||
| 167 | uint32_t firmware_version; | ||
| 168 | uint32_t bios_version; | ||
| 169 | uint8_t driver_version[MPT2_IOCTL_VERSION_LENGTH]; | ||
| 170 | uint8_t rsvd1; | ||
| 171 | uint8_t scsi_id; | ||
| 172 | uint16_t rsvd2; | ||
| 173 | struct mpt2_ioctl_pci_info pci_information; | ||
| 174 | }; | ||
| 175 | |||
| 176 | |||
| 177 | /* number of event log entries */ | ||
| 178 | #define MPT2SAS_CTL_EVENT_LOG_SIZE (50) | ||
| 179 | |||
| 180 | /** | ||
| 181 | * struct mpt2_ioctl_eventquery - query event count and type | ||
| 182 | * @hdr - generic header | ||
| 183 | * @event_entries - number of events returned by get_event_report | ||
| 184 | * @rsvd - reserved | ||
| 185 | * @event_types - type of events currently being captured | ||
| 186 | */ | ||
| 187 | struct mpt2_ioctl_eventquery { | ||
| 188 | struct mpt2_ioctl_header hdr; | ||
| 189 | uint16_t event_entries; | ||
| 190 | uint16_t rsvd; | ||
| 191 | uint32_t event_types[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS]; | ||
| 192 | }; | ||
| 193 | |||
| 194 | /** | ||
| 195 | * struct mpt2_ioctl_eventenable - enable/disable event capturing | ||
| 196 | * @hdr - generic header | ||
| 197 | * @event_types - toggle off/on type of events to be captured | ||
| 198 | */ | ||
| 199 | struct mpt2_ioctl_eventenable { | ||
| 200 | struct mpt2_ioctl_header hdr; | ||
| 201 | uint32_t event_types[4]; | ||
| 202 | }; | ||
| 203 | |||
| 204 | #define MPT2_EVENT_DATA_SIZE (192) | ||
| 205 | /** | ||
| 206 | * struct MPT2_IOCTL_EVENTS - | ||
| 207 | * @event - the event that was reported | ||
| 208 | * @context - unique value for each event assigned by driver | ||
| 209 | * @data - event data returned in fw reply message | ||
| 210 | */ | ||
| 211 | struct MPT2_IOCTL_EVENTS { | ||
| 212 | uint32_t event; | ||
| 213 | uint32_t context; | ||
| 214 | uint8_t data[MPT2_EVENT_DATA_SIZE]; | ||
| 215 | }; | ||
| 216 | |||
| 217 | /** | ||
| 218 | * struct mpt2_ioctl_eventreport - returing event log | ||
| 219 | * @hdr - generic header | ||
| 220 | * @event_data - (see struct MPT2_IOCTL_EVENTS) | ||
| 221 | */ | ||
| 222 | struct mpt2_ioctl_eventreport { | ||
| 223 | struct mpt2_ioctl_header hdr; | ||
| 224 | struct MPT2_IOCTL_EVENTS event_data[1]; | ||
| 225 | }; | ||
| 226 | |||
| 227 | /** | ||
| 228 | * struct mpt2_ioctl_command - generic mpt firmware passthru ioctl | ||
| 229 | * @hdr - generic header | ||
| 230 | * @timeout - command timeout in seconds. (if zero then use driver default | ||
| 231 | * value). | ||
| 232 | * @reply_frame_buf_ptr - reply location | ||
| 233 | * @data_in_buf_ptr - destination for read | ||
| 234 | * @data_out_buf_ptr - data source for write | ||
| 235 | * @sense_data_ptr - sense data location | ||
| 236 | * @max_reply_bytes - maximum number of reply bytes to be sent to app. | ||
| 237 | * @data_in_size - number bytes for data transfer in (read) | ||
| 238 | * @data_out_size - number bytes for data transfer out (write) | ||
| 239 | * @max_sense_bytes - maximum number of bytes for auto sense buffers | ||
| 240 | * @data_sge_offset - offset in words from the start of the request message to | ||
| 241 | * the first SGL | ||
| 242 | * @mf[1]; | ||
| 243 | */ | ||
| 244 | struct mpt2_ioctl_command { | ||
| 245 | struct mpt2_ioctl_header hdr; | ||
| 246 | uint32_t timeout; | ||
| 247 | void __user *reply_frame_buf_ptr; | ||
| 248 | void __user *data_in_buf_ptr; | ||
| 249 | void __user *data_out_buf_ptr; | ||
| 250 | void __user *sense_data_ptr; | ||
| 251 | uint32_t max_reply_bytes; | ||
| 252 | uint32_t data_in_size; | ||
| 253 | uint32_t data_out_size; | ||
| 254 | uint32_t max_sense_bytes; | ||
| 255 | uint32_t data_sge_offset; | ||
| 256 | uint8_t mf[1]; | ||
| 257 | }; | ||
| 258 | |||
| 259 | #ifdef CONFIG_COMPAT | ||
| 260 | struct mpt2_ioctl_command32 { | ||
| 261 | struct mpt2_ioctl_header hdr; | ||
| 262 | uint32_t timeout; | ||
| 263 | uint32_t reply_frame_buf_ptr; | ||
| 264 | uint32_t data_in_buf_ptr; | ||
| 265 | uint32_t data_out_buf_ptr; | ||
| 266 | uint32_t sense_data_ptr; | ||
| 267 | uint32_t max_reply_bytes; | ||
| 268 | uint32_t data_in_size; | ||
| 269 | uint32_t data_out_size; | ||
| 270 | uint32_t max_sense_bytes; | ||
| 271 | uint32_t data_sge_offset; | ||
| 272 | uint8_t mf[1]; | ||
| 273 | }; | ||
| 274 | #endif | ||
| 275 | |||
| 276 | /** | ||
| 277 | * struct mpt2_ioctl_btdh_mapping - mapping info | ||
| 278 | * @hdr - generic header | ||
| 279 | * @id - target device identification number | ||
| 280 | * @bus - SCSI bus number that the target device exists on | ||
| 281 | * @handle - device handle for the target device | ||
| 282 | * @rsvd - reserved | ||
| 283 | * | ||
| 284 | * To obtain a bus/id the application sets | ||
| 285 | * handle to valid handle, and bus/id to 0xFFFF. | ||
| 286 | * | ||
| 287 | * To obtain the device handle the application sets | ||
| 288 | * bus/id valid value, and the handle to 0xFFFF. | ||
| 289 | */ | ||
| 290 | struct mpt2_ioctl_btdh_mapping { | ||
| 291 | struct mpt2_ioctl_header hdr; | ||
| 292 | uint32_t id; | ||
| 293 | uint32_t bus; | ||
| 294 | uint16_t handle; | ||
| 295 | uint16_t rsvd; | ||
| 296 | }; | ||
| 297 | |||
| 298 | |||
| 299 | /* status bits for ioc->diag_buffer_status */ | ||
| 300 | #define MPT2_DIAG_BUFFER_IS_REGISTERED (0x01) | ||
| 301 | #define MPT2_DIAG_BUFFER_IS_RELEASED (0x02) | ||
| 302 | #define MPT2_DIAG_BUFFER_IS_DIAG_RESET (0x04) | ||
| 303 | |||
| 304 | /* application flags for mpt2_diag_register, mpt2_diag_query */ | ||
| 305 | #define MPT2_APP_FLAGS_APP_OWNED (0x0001) | ||
| 306 | #define MPT2_APP_FLAGS_BUFFER_VALID (0x0002) | ||
| 307 | #define MPT2_APP_FLAGS_FW_BUFFER_ACCESS (0x0004) | ||
| 308 | |||
| 309 | /* flags for mpt2_diag_read_buffer */ | ||
| 310 | #define MPT2_FLAGS_REREGISTER (0x0001) | ||
| 311 | |||
| 312 | #define MPT2_PRODUCT_SPECIFIC_DWORDS 23 | ||
| 313 | |||
| 314 | /** | ||
| 315 | * struct mpt2_diag_register - application register with driver | ||
| 316 | * @hdr - generic header | ||
| 317 | * @reserved - | ||
| 318 | * @buffer_type - specifies either TRACE, SNAPSHOT, or EXTENDED | ||
| 319 | * @application_flags - misc flags | ||
| 320 | * @diagnostic_flags - specifies flags affecting command processing | ||
| 321 | * @product_specific - product specific information | ||
| 322 | * @requested_buffer_size - buffers size in bytes | ||
| 323 | * @unique_id - tag specified by application that is used to signal ownership | ||
| 324 | * of the buffer. | ||
| 325 | * | ||
| 326 | * This will allow the driver to setup any required buffers that will be | ||
| 327 | * needed by firmware to communicate with the driver. | ||
| 328 | */ | ||
| 329 | struct mpt2_diag_register { | ||
| 330 | struct mpt2_ioctl_header hdr; | ||
| 331 | uint8_t reserved; | ||
| 332 | uint8_t buffer_type; | ||
| 333 | uint16_t application_flags; | ||
| 334 | uint32_t diagnostic_flags; | ||
| 335 | uint32_t product_specific[MPT2_PRODUCT_SPECIFIC_DWORDS]; | ||
| 336 | uint32_t requested_buffer_size; | ||
| 337 | uint32_t unique_id; | ||
| 338 | }; | ||
| 339 | |||
| 340 | /** | ||
| 341 | * struct mpt2_diag_unregister - application unregister with driver | ||
| 342 | * @hdr - generic header | ||
| 343 | * @unique_id - tag uniquely identifies the buffer to be unregistered | ||
| 344 | * | ||
| 345 | * This will allow the driver to cleanup any memory allocated for diag | ||
| 346 | * messages and to free up any resources. | ||
| 347 | */ | ||
| 348 | struct mpt2_diag_unregister { | ||
| 349 | struct mpt2_ioctl_header hdr; | ||
| 350 | uint32_t unique_id; | ||
| 351 | }; | ||
| 352 | |||
| 353 | /** | ||
| 354 | * struct mpt2_diag_query - query relevant info associated with diag buffers | ||
| 355 | * @hdr - generic header | ||
| 356 | * @reserved - | ||
| 357 | * @buffer_type - specifies either TRACE, SNAPSHOT, or EXTENDED | ||
| 358 | * @application_flags - misc flags | ||
| 359 | * @diagnostic_flags - specifies flags affecting command processing | ||
| 360 | * @product_specific - product specific information | ||
| 361 | * @total_buffer_size - diag buffer size in bytes | ||
| 362 | * @driver_added_buffer_size - size of extra space appended to end of buffer | ||
| 363 | * @unique_id - unique id associated with this buffer. | ||
| 364 | * | ||
| 365 | * The application will send only buffer_type and unique_id. Driver will | ||
| 366 | * inspect unique_id first, if valid, fill in all the info. If unique_id is | ||
| 367 | * 0x00, the driver will return info specified by Buffer Type. | ||
| 368 | */ | ||
| 369 | struct mpt2_diag_query { | ||
| 370 | struct mpt2_ioctl_header hdr; | ||
| 371 | uint8_t reserved; | ||
| 372 | uint8_t buffer_type; | ||
| 373 | uint16_t application_flags; | ||
| 374 | uint32_t diagnostic_flags; | ||
| 375 | uint32_t product_specific[MPT2_PRODUCT_SPECIFIC_DWORDS]; | ||
| 376 | uint32_t total_buffer_size; | ||
| 377 | uint32_t driver_added_buffer_size; | ||
| 378 | uint32_t unique_id; | ||
| 379 | }; | ||
| 380 | |||
| 381 | /** | ||
| 382 | * struct mpt2_diag_release - request to send Diag Release Message to firmware | ||
| 383 | * @hdr - generic header | ||
| 384 | * @unique_id - tag uniquely identifies the buffer to be released | ||
| 385 | * | ||
| 386 | * This allows ownership of the specified buffer to returned to the driver, | ||
| 387 | * allowing an application to read the buffer without fear that firmware is | ||
| 388 | * overwritting information in the buffer. | ||
| 389 | */ | ||
| 390 | struct mpt2_diag_release { | ||
| 391 | struct mpt2_ioctl_header hdr; | ||
| 392 | uint32_t unique_id; | ||
| 393 | }; | ||
| 394 | |||
| 395 | /** | ||
| 396 | * struct mpt2_diag_read_buffer - request for copy of the diag buffer | ||
| 397 | * @hdr - generic header | ||
| 398 | * @status - | ||
| 399 | * @reserved - | ||
| 400 | * @flags - misc flags | ||
| 401 | * @starting_offset - starting offset within drivers buffer where to start | ||
| 402 | * reading data at into the specified application buffer | ||
| 403 | * @bytes_to_read - number of bytes to copy from the drivers buffer into the | ||
| 404 | * application buffer starting at starting_offset. | ||
| 405 | * @unique_id - unique id associated with this buffer. | ||
| 406 | * @diagnostic_data - data payload | ||
| 407 | */ | ||
| 408 | struct mpt2_diag_read_buffer { | ||
| 409 | struct mpt2_ioctl_header hdr; | ||
| 410 | uint8_t status; | ||
| 411 | uint8_t reserved; | ||
| 412 | uint16_t flags; | ||
| 413 | uint32_t starting_offset; | ||
| 414 | uint32_t bytes_to_read; | ||
| 415 | uint32_t unique_id; | ||
| 416 | uint32_t diagnostic_data[1]; | ||
| 417 | }; | ||
| 418 | |||
| 419 | #endif /* MPT2SAS_CTL_H_INCLUDED */ | ||
diff --git a/drivers/scsi/mpt2sas/mpt2sas_debug.h b/drivers/scsi/mpt2sas/mpt2sas_debug.h deleted file mode 100644 index 277120d45648..000000000000 --- a/drivers/scsi/mpt2sas/mpt2sas_debug.h +++ /dev/null | |||
| @@ -1,182 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Logging Support for MPT (Message Passing Technology) based controllers | ||
| 3 | * | ||
| 4 | * This code is based on drivers/scsi/mpt2sas/mpt2_debug.c | ||
| 5 | * Copyright (C) 2007-2014 LSI Corporation | ||
| 6 | * Copyright (C) 20013-2014 Avago Technologies | ||
| 7 | * (mailto: MPT-FusionLinux.pdl@avagotech.com) | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or | ||
| 10 | * modify it under the terms of the GNU General Public License | ||
| 11 | * as published by the Free Software Foundation; either version 2 | ||
| 12 | * of the License, or (at your option) any later version. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | * NO WARRANTY | ||
| 20 | * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR | ||
| 21 | * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT | ||
| 22 | * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, | ||
| 23 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is | ||
| 24 | * solely responsible for determining the appropriateness of using and | ||
| 25 | * distributing the Program and assumes all risks associated with its | ||
| 26 | * exercise of rights under this Agreement, including but not limited to | ||
| 27 | * the risks and costs of program errors, damage to or loss of data, | ||
| 28 | * programs or equipment, and unavailability or interruption of operations. | ||
| 29 | |||
| 30 | * DISCLAIMER OF LIABILITY | ||
| 31 | * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY | ||
| 32 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 33 | * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND | ||
| 34 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR | ||
| 35 | * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | ||
| 36 | * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED | ||
| 37 | * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES | ||
| 38 | |||
| 39 | * You should have received a copy of the GNU General Public License | ||
| 40 | * along with this program; if not, write to the Free Software | ||
| 41 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
| 42 | * USA. | ||
| 43 | */ | ||
| 44 | |||
| 45 | #ifndef MPT2SAS_DEBUG_H_INCLUDED | ||
| 46 | #define MPT2SAS_DEBUG_H_INCLUDED | ||
| 47 | |||
| 48 | #define MPT_DEBUG 0x00000001 | ||
| 49 | #define MPT_DEBUG_MSG_FRAME 0x00000002 | ||
| 50 | #define MPT_DEBUG_SG 0x00000004 | ||
| 51 | #define MPT_DEBUG_EVENTS 0x00000008 | ||
| 52 | #define MPT_DEBUG_EVENT_WORK_TASK 0x00000010 | ||
| 53 | #define MPT_DEBUG_INIT 0x00000020 | ||
| 54 | #define MPT_DEBUG_EXIT 0x00000040 | ||
| 55 | #define MPT_DEBUG_FAIL 0x00000080 | ||
| 56 | #define MPT_DEBUG_TM 0x00000100 | ||
| 57 | #define MPT_DEBUG_REPLY 0x00000200 | ||
| 58 | #define MPT_DEBUG_HANDSHAKE 0x00000400 | ||
| 59 | #define MPT_DEBUG_CONFIG 0x00000800 | ||
| 60 | #define MPT_DEBUG_DL 0x00001000 | ||
| 61 | #define MPT_DEBUG_RESET 0x00002000 | ||
| 62 | #define MPT_DEBUG_SCSI 0x00004000 | ||
| 63 | #define MPT_DEBUG_IOCTL 0x00008000 | ||
| 64 | #define MPT_DEBUG_CSMISAS 0x00010000 | ||
| 65 | #define MPT_DEBUG_SAS 0x00020000 | ||
| 66 | #define MPT_DEBUG_TRANSPORT 0x00040000 | ||
| 67 | #define MPT_DEBUG_TASK_SET_FULL 0x00080000 | ||
| 68 | |||
| 69 | #define MPT_DEBUG_TARGET_MODE 0x00100000 | ||
| 70 | |||
| 71 | |||
| 72 | /* | ||
| 73 | * CONFIG_SCSI_MPT2SAS_LOGGING - enabled in Kconfig | ||
| 74 | */ | ||
| 75 | |||
| 76 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | ||
| 77 | #define MPT_CHECK_LOGGING(IOC, CMD, BITS) \ | ||
| 78 | { \ | ||
| 79 | if (IOC->logging_level & BITS) \ | ||
| 80 | CMD; \ | ||
| 81 | } | ||
| 82 | #else | ||
| 83 | #define MPT_CHECK_LOGGING(IOC, CMD, BITS) | ||
| 84 | #endif /* CONFIG_SCSI_MPT2SAS_LOGGING */ | ||
| 85 | |||
| 86 | |||
| 87 | /* | ||
| 88 | * debug macros | ||
| 89 | */ | ||
| 90 | |||
| 91 | #define dprintk(IOC, CMD) \ | ||
| 92 | MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG) | ||
| 93 | |||
| 94 | #define dsgprintk(IOC, CMD) \ | ||
| 95 | MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SG) | ||
| 96 | |||
| 97 | #define devtprintk(IOC, CMD) \ | ||
| 98 | MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_EVENTS) | ||
| 99 | |||
| 100 | #define dewtprintk(IOC, CMD) \ | ||
| 101 | MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_EVENT_WORK_TASK) | ||
| 102 | |||
| 103 | #define dinitprintk(IOC, CMD) \ | ||
| 104 | MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_INIT) | ||
| 105 | |||
| 106 | #define dexitprintk(IOC, CMD) \ | ||
| 107 | MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_EXIT) | ||
| 108 | |||
| 109 | #define dfailprintk(IOC, CMD) \ | ||
| 110 | MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_FAIL) | ||
| 111 | |||
| 112 | #define dtmprintk(IOC, CMD) \ | ||
| 113 | MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TM) | ||
| 114 | |||
| 115 | #define dreplyprintk(IOC, CMD) \ | ||
| 116 | MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_REPLY) | ||
| 117 | |||
| 118 | #define dhsprintk(IOC, CMD) \ | ||
| 119 | MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_HANDSHAKE) | ||
| 120 | |||
| 121 | #define dcprintk(IOC, CMD) \ | ||
| 122 | MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_CONFIG) | ||
| 123 | |||
| 124 | #define ddlprintk(IOC, CMD) \ | ||
| 125 | MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_DL) | ||
| 126 | |||
| 127 | #define drsprintk(IOC, CMD) \ | ||
| 128 | MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_RESET) | ||
| 129 | |||
| 130 | #define dsprintk(IOC, CMD) \ | ||
| 131 | MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SCSI) | ||
| 132 | |||
| 133 | #define dctlprintk(IOC, CMD) \ | ||
| 134 | MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_IOCTL) | ||
| 135 | |||
| 136 | #define dcsmisasprintk(IOC, CMD) \ | ||
| 137 | MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_CSMISAS) | ||
| 138 | |||
| 139 | #define dsasprintk(IOC, CMD) \ | ||
| 140 | MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SAS) | ||
| 141 | |||
| 142 | #define dsastransport(IOC, CMD) \ | ||
| 143 | MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SAS_WIDE) | ||
| 144 | |||
| 145 | #define dmfprintk(IOC, CMD) \ | ||
| 146 | MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_MSG_FRAME) | ||
| 147 | |||
| 148 | #define dtsfprintk(IOC, CMD) \ | ||
| 149 | MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TASK_SET_FULL) | ||
| 150 | |||
| 151 | #define dtransportprintk(IOC, CMD) \ | ||
| 152 | MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TRANSPORT) | ||
| 153 | |||
| 154 | #define dTMprintk(IOC, CMD) \ | ||
| 155 | MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TARGET_MODE) | ||
| 156 | |||
| 157 | /* inline functions for dumping debug data*/ | ||
| 158 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | ||
| 159 | /** | ||
| 160 | * _debug_dump_mf - print message frame contents | ||
| 161 | * @mpi_request: pointer to message frame | ||
| 162 | * @sz: number of dwords | ||
| 163 | */ | ||
| 164 | static inline void | ||
| 165 | _debug_dump_mf(void *mpi_request, int sz) | ||
| 166 | { | ||
| 167 | int i; | ||
| 168 | __le32 *mfp = (__le32 *)mpi_request; | ||
| 169 | |||
| 170 | printk(KERN_INFO "mf:\n\t"); | ||
| 171 | for (i = 0; i < sz; i++) { | ||
| 172 | if (i && ((i % 8) == 0)) | ||
| 173 | printk("\n\t"); | ||
| 174 | printk("%08x ", le32_to_cpu(mfp[i])); | ||
| 175 | } | ||
| 176 | printk("\n"); | ||
| 177 | } | ||
| 178 | #else | ||
| 179 | #define _debug_dump_mf(mpi_request, sz) | ||
| 180 | #endif /* CONFIG_SCSI_MPT2SAS_LOGGING */ | ||
| 181 | |||
| 182 | #endif /* MPT2SAS_DEBUG_H_INCLUDED */ | ||
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c deleted file mode 100644 index 0ad09b2bff9c..000000000000 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ /dev/null | |||
| @@ -1,8855 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Scsi Host Layer for MPT (Message Passing Technology) based controllers | ||
| 3 | * | ||
| 4 | * This code is based on drivers/scsi/mpt2sas/mpt2_scsih.c | ||
| 5 | * Copyright (C) 2007-2014 LSI Corporation | ||
| 6 | * Copyright (C) 20013-2014 Avago Technologies | ||
| 7 | * (mailto: MPT-FusionLinux.pdl@avagotech.com) | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or | ||
| 10 | * modify it under the terms of the GNU General Public License | ||
| 11 | * as published by the Free Software Foundation; either version 2 | ||
| 12 | * of the License, or (at your option) any later version. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | * NO WARRANTY | ||
| 20 | * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR | ||
| 21 | * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT | ||
| 22 | * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, | ||
| 23 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is | ||
| 24 | * solely responsible for determining the appropriateness of using and | ||
| 25 | * distributing the Program and assumes all risks associated with its | ||
| 26 | * exercise of rights under this Agreement, including but not limited to | ||
| 27 | * the risks and costs of program errors, damage to or loss of data, | ||
| 28 | * programs or equipment, and unavailability or interruption of operations. | ||
| 29 | |||
| 30 | * DISCLAIMER OF LIABILITY | ||
| 31 | * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY | ||
| 32 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 33 | * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND | ||
| 34 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR | ||
| 35 | * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | ||
| 36 | * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED | ||
| 37 | * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES | ||
| 38 | |||
| 39 | * You should have received a copy of the GNU General Public License | ||
| 40 | * along with this program; if not, write to the Free Software | ||
| 41 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
| 42 | * USA. | ||
| 43 | */ | ||
| 44 | |||
| 45 | #include <linux/module.h> | ||
| 46 | #include <linux/kernel.h> | ||
| 47 | #include <linux/init.h> | ||
| 48 | #include <linux/errno.h> | ||
| 49 | #include <linux/blkdev.h> | ||
| 50 | #include <linux/sched.h> | ||
| 51 | #include <linux/workqueue.h> | ||
| 52 | #include <linux/delay.h> | ||
| 53 | #include <linux/pci.h> | ||
| 54 | #include <linux/interrupt.h> | ||
| 55 | #include <linux/aer.h> | ||
| 56 | #include <linux/raid_class.h> | ||
| 57 | #include <linux/slab.h> | ||
| 58 | |||
| 59 | #include <asm/unaligned.h> | ||
| 60 | |||
| 61 | #include "mpt2sas_base.h" | ||
| 62 | |||
| 63 | MODULE_AUTHOR(MPT2SAS_AUTHOR); | ||
| 64 | MODULE_DESCRIPTION(MPT2SAS_DESCRIPTION); | ||
| 65 | MODULE_LICENSE("GPL"); | ||
| 66 | MODULE_VERSION(MPT2SAS_DRIVER_VERSION); | ||
| 67 | |||
| 68 | #define RAID_CHANNEL 1 | ||
| 69 | |||
| 70 | /* forward proto's */ | ||
| 71 | static void _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc, | ||
| 72 | struct _sas_node *sas_expander); | ||
| 73 | static void _firmware_event_work(struct work_struct *work); | ||
| 74 | |||
| 75 | static u8 _scsih_check_for_pending_tm(struct MPT2SAS_ADAPTER *ioc, u16 smid); | ||
| 76 | |||
| 77 | static void _scsih_scan_start(struct Scsi_Host *shost); | ||
| 78 | static int _scsih_scan_finished(struct Scsi_Host *shost, unsigned long time); | ||
| 79 | |||
| 80 | /* global parameters */ | ||
| 81 | LIST_HEAD(mpt2sas_ioc_list); | ||
| 82 | /* global ioc lock for list operations */ | ||
| 83 | DEFINE_SPINLOCK(gioc_lock); | ||
| 84 | /* local parameters */ | ||
| 85 | static u8 scsi_io_cb_idx = -1; | ||
| 86 | static u8 tm_cb_idx = -1; | ||
| 87 | static u8 ctl_cb_idx = -1; | ||
| 88 | static u8 base_cb_idx = -1; | ||
| 89 | static u8 port_enable_cb_idx = -1; | ||
| 90 | static u8 transport_cb_idx = -1; | ||
| 91 | static u8 scsih_cb_idx = -1; | ||
| 92 | static u8 config_cb_idx = -1; | ||
| 93 | static int mpt_ids; | ||
| 94 | |||
| 95 | static u8 tm_tr_cb_idx = -1 ; | ||
| 96 | static u8 tm_tr_volume_cb_idx = -1 ; | ||
| 97 | static u8 tm_sas_control_cb_idx = -1; | ||
| 98 | |||
| 99 | /* command line options */ | ||
| 100 | static u32 logging_level; | ||
| 101 | MODULE_PARM_DESC(logging_level, " bits for enabling additional logging info " | ||
| 102 | "(default=0)"); | ||
| 103 | |||
| 104 | static ushort max_sectors = 0xFFFF; | ||
| 105 | module_param(max_sectors, ushort, 0); | ||
| 106 | MODULE_PARM_DESC(max_sectors, "max sectors, range 64 to 32767 default=32767"); | ||
| 107 | |||
| 108 | static int missing_delay[2] = {-1, -1}; | ||
| 109 | module_param_array(missing_delay, int, NULL, 0); | ||
| 110 | MODULE_PARM_DESC(missing_delay, " device missing delay , io missing delay"); | ||
| 111 | |||
| 112 | /* scsi-mid layer global parmeter is max_report_luns, which is 511 */ | ||
| 113 | #define MPT2SAS_MAX_LUN (16895) | ||
| 114 | static int max_lun = MPT2SAS_MAX_LUN; | ||
| 115 | module_param(max_lun, int, 0); | ||
| 116 | MODULE_PARM_DESC(max_lun, " max lun, default=16895 "); | ||
| 117 | |||
| 118 | /* diag_buffer_enable is bitwise | ||
| 119 | * bit 0 set = TRACE | ||
| 120 | * bit 1 set = SNAPSHOT | ||
| 121 | * bit 2 set = EXTENDED | ||
| 122 | * | ||
| 123 | * Either bit can be set, or both | ||
| 124 | */ | ||
| 125 | static int diag_buffer_enable = -1; | ||
| 126 | module_param(diag_buffer_enable, int, 0); | ||
| 127 | MODULE_PARM_DESC(diag_buffer_enable, " post diag buffers " | ||
| 128 | "(TRACE=1/SNAPSHOT=2/EXTENDED=4/default=0)"); | ||
| 129 | |||
| 130 | static int disable_discovery = -1; | ||
| 131 | module_param(disable_discovery, int, 0); | ||
| 132 | MODULE_PARM_DESC(disable_discovery, " disable discovery "); | ||
| 133 | |||
| 134 | /* permit overriding the host protection capabilities mask (EEDP/T10 PI) */ | ||
| 135 | static int prot_mask = 0; | ||
| 136 | module_param(prot_mask, int, 0); | ||
| 137 | MODULE_PARM_DESC(prot_mask, " host protection capabilities mask, def=7 "); | ||
| 138 | |||
| 139 | /** | ||
| 140 | * struct sense_info - common structure for obtaining sense keys | ||
| 141 | * @skey: sense key | ||
| 142 | * @asc: additional sense code | ||
| 143 | * @ascq: additional sense code qualifier | ||
| 144 | */ | ||
| 145 | struct sense_info { | ||
| 146 | u8 skey; | ||
| 147 | u8 asc; | ||
| 148 | u8 ascq; | ||
| 149 | }; | ||
| 150 | |||
| 151 | |||
| 152 | #define MPT2SAS_TURN_ON_PFA_LED (0xFFFC) | ||
| 153 | #define MPT2SAS_PORT_ENABLE_COMPLETE (0xFFFD) | ||
| 154 | #define MPT2SAS_REMOVE_UNRESPONDING_DEVICES (0xFFFF) | ||
| 155 | /** | ||
| 156 | * struct fw_event_work - firmware event struct | ||
| 157 | * @list: link list framework | ||
| 158 | * @work: work object (ioc->fault_reset_work_q) | ||
| 159 | * @cancel_pending_work: flag set during reset handling | ||
| 160 | * @ioc: per adapter object | ||
| 161 | * @device_handle: device handle | ||
| 162 | * @VF_ID: virtual function id | ||
| 163 | * @VP_ID: virtual port id | ||
| 164 | * @ignore: flag meaning this event has been marked to ignore | ||
| 165 | * @event: firmware event MPI2_EVENT_XXX defined in mpt2_ioc.h | ||
| 166 | * @event_data: reply event data payload follows | ||
| 167 | * | ||
| 168 | * This object stored on ioc->fw_event_list. | ||
| 169 | */ | ||
| 170 | struct fw_event_work { | ||
| 171 | struct list_head list; | ||
| 172 | u8 cancel_pending_work; | ||
| 173 | struct delayed_work delayed_work; | ||
| 174 | struct MPT2SAS_ADAPTER *ioc; | ||
| 175 | u16 device_handle; | ||
| 176 | u8 VF_ID; | ||
| 177 | u8 VP_ID; | ||
| 178 | u8 ignore; | ||
| 179 | u16 event; | ||
| 180 | struct kref refcount; | ||
| 181 | char event_data[0] __aligned(4); | ||
| 182 | }; | ||
| 183 | |||
| 184 | static void fw_event_work_free(struct kref *r) | ||
| 185 | { | ||
| 186 | kfree(container_of(r, struct fw_event_work, refcount)); | ||
| 187 | } | ||
| 188 | |||
| 189 | static void fw_event_work_get(struct fw_event_work *fw_work) | ||
| 190 | { | ||
| 191 | kref_get(&fw_work->refcount); | ||
| 192 | } | ||
| 193 | |||
| 194 | static void fw_event_work_put(struct fw_event_work *fw_work) | ||
| 195 | { | ||
| 196 | kref_put(&fw_work->refcount, fw_event_work_free); | ||
| 197 | } | ||
| 198 | |||
| 199 | static struct fw_event_work *alloc_fw_event_work(int len) | ||
| 200 | { | ||
| 201 | struct fw_event_work *fw_event; | ||
| 202 | |||
| 203 | fw_event = kzalloc(sizeof(*fw_event) + len, GFP_ATOMIC); | ||
| 204 | if (!fw_event) | ||
| 205 | return NULL; | ||
| 206 | |||
| 207 | kref_init(&fw_event->refcount); | ||
| 208 | return fw_event; | ||
| 209 | } | ||
| 210 | |||
| 211 | /* raid transport support */ | ||
| 212 | static struct raid_template *mpt2sas_raid_template; | ||
| 213 | |||
| 214 | /** | ||
| 215 | * struct _scsi_io_transfer - scsi io transfer | ||
| 216 | * @handle: sas device handle (assigned by firmware) | ||
| 217 | * @is_raid: flag set for hidden raid components | ||
| 218 | * @dir: DMA_TO_DEVICE, DMA_FROM_DEVICE, | ||
| 219 | * @data_length: data transfer length | ||
| 220 | * @data_dma: dma pointer to data | ||
| 221 | * @sense: sense data | ||
| 222 | * @lun: lun number | ||
| 223 | * @cdb_length: cdb length | ||
| 224 | * @cdb: cdb contents | ||
| 225 | * @timeout: timeout for this command | ||
| 226 | * @VF_ID: virtual function id | ||
| 227 | * @VP_ID: virtual port id | ||
| 228 | * @valid_reply: flag set for reply message | ||
| 229 | * @sense_length: sense length | ||
| 230 | * @ioc_status: ioc status | ||
| 231 | * @scsi_state: scsi state | ||
| 232 | * @scsi_status: scsi staus | ||
| 233 | * @log_info: log information | ||
| 234 | * @transfer_length: data length transfer when there is a reply message | ||
| 235 | * | ||
| 236 | * Used for sending internal scsi commands to devices within this module. | ||
| 237 | * Refer to _scsi_send_scsi_io(). | ||
| 238 | */ | ||
| 239 | struct _scsi_io_transfer { | ||
| 240 | u16 handle; | ||
| 241 | u8 is_raid; | ||
| 242 | enum dma_data_direction dir; | ||
| 243 | u32 data_length; | ||
| 244 | dma_addr_t data_dma; | ||
| 245 | u8 sense[SCSI_SENSE_BUFFERSIZE]; | ||
| 246 | u32 lun; | ||
| 247 | u8 cdb_length; | ||
| 248 | u8 cdb[32]; | ||
| 249 | u8 timeout; | ||
| 250 | u8 VF_ID; | ||
| 251 | u8 VP_ID; | ||
| 252 | u8 valid_reply; | ||
| 253 | /* the following bits are only valid when 'valid_reply = 1' */ | ||
| 254 | u32 sense_length; | ||
| 255 | u16 ioc_status; | ||
| 256 | u8 scsi_state; | ||
| 257 | u8 scsi_status; | ||
| 258 | u32 log_info; | ||
| 259 | u32 transfer_length; | ||
| 260 | }; | ||
| 261 | |||
| 262 | /* | ||
| 263 | * The pci device ids are defined in mpi/mpi2_cnfg.h. | ||
| 264 | */ | ||
| 265 | static struct pci_device_id scsih_pci_table[] = { | ||
| 266 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2004, | ||
| 267 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 268 | /* Falcon ~ 2008*/ | ||
| 269 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2008, | ||
| 270 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 271 | /* Liberator ~ 2108 */ | ||
| 272 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_1, | ||
| 273 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 274 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_2, | ||
| 275 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 276 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_3, | ||
| 277 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 278 | /* Meteor ~ 2116 */ | ||
| 279 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_1, | ||
| 280 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 281 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_2, | ||
| 282 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 283 | /* Thunderbolt ~ 2208 */ | ||
| 284 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_1, | ||
| 285 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 286 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_2, | ||
| 287 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 288 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_3, | ||
| 289 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 290 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_4, | ||
| 291 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 292 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_5, | ||
| 293 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 294 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_6, | ||
| 295 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 296 | /* Mustang ~ 2308 */ | ||
| 297 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_1, | ||
| 298 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 299 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_2, | ||
| 300 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 301 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_3, | ||
| 302 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 303 | /* SSS6200 */ | ||
| 304 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SSS6200, | ||
| 305 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 306 | {0} /* Terminating entry */ | ||
| 307 | }; | ||
| 308 | MODULE_DEVICE_TABLE(pci, scsih_pci_table); | ||
| 309 | |||
| 310 | /** | ||
| 311 | * _scsih_set_debug_level - global setting of ioc->logging_level. | ||
| 312 | * | ||
| 313 | * Note: The logging levels are defined in mpt2sas_debug.h. | ||
| 314 | */ | ||
| 315 | static int | ||
| 316 | _scsih_set_debug_level(const char *val, struct kernel_param *kp) | ||
| 317 | { | ||
| 318 | int ret = param_set_int(val, kp); | ||
| 319 | struct MPT2SAS_ADAPTER *ioc; | ||
| 320 | |||
| 321 | if (ret) | ||
| 322 | return ret; | ||
| 323 | |||
| 324 | printk(KERN_INFO "setting logging_level(0x%08x)\n", logging_level); | ||
| 325 | spin_lock(&gioc_lock); | ||
| 326 | list_for_each_entry(ioc, &mpt2sas_ioc_list, list) | ||
| 327 | ioc->logging_level = logging_level; | ||
| 328 | spin_unlock(&gioc_lock); | ||
| 329 | return 0; | ||
| 330 | } | ||
| 331 | module_param_call(logging_level, _scsih_set_debug_level, param_get_int, | ||
| 332 | &logging_level, 0644); | ||
| 333 | |||
| 334 | /** | ||
| 335 | * _scsih_srch_boot_sas_address - search based on sas_address | ||
| 336 | * @sas_address: sas address | ||
| 337 | * @boot_device: boot device object from bios page 2 | ||
| 338 | * | ||
| 339 | * Returns 1 when there's a match, 0 means no match. | ||
| 340 | */ | ||
| 341 | static inline int | ||
| 342 | _scsih_srch_boot_sas_address(u64 sas_address, | ||
| 343 | Mpi2BootDeviceSasWwid_t *boot_device) | ||
| 344 | { | ||
| 345 | return (sas_address == le64_to_cpu(boot_device->SASAddress)) ? 1 : 0; | ||
| 346 | } | ||
| 347 | |||
| 348 | /** | ||
| 349 | * _scsih_srch_boot_device_name - search based on device name | ||
| 350 | * @device_name: device name specified in INDENTIFY fram | ||
| 351 | * @boot_device: boot device object from bios page 2 | ||
| 352 | * | ||
| 353 | * Returns 1 when there's a match, 0 means no match. | ||
| 354 | */ | ||
| 355 | static inline int | ||
| 356 | _scsih_srch_boot_device_name(u64 device_name, | ||
| 357 | Mpi2BootDeviceDeviceName_t *boot_device) | ||
| 358 | { | ||
| 359 | return (device_name == le64_to_cpu(boot_device->DeviceName)) ? 1 : 0; | ||
| 360 | } | ||
| 361 | |||
| 362 | /** | ||
| 363 | * _scsih_srch_boot_encl_slot - search based on enclosure_logical_id/slot | ||
| 364 | * @enclosure_logical_id: enclosure logical id | ||
| 365 | * @slot_number: slot number | ||
| 366 | * @boot_device: boot device object from bios page 2 | ||
| 367 | * | ||
| 368 | * Returns 1 when there's a match, 0 means no match. | ||
| 369 | */ | ||
| 370 | static inline int | ||
| 371 | _scsih_srch_boot_encl_slot(u64 enclosure_logical_id, u16 slot_number, | ||
| 372 | Mpi2BootDeviceEnclosureSlot_t *boot_device) | ||
| 373 | { | ||
| 374 | return (enclosure_logical_id == le64_to_cpu(boot_device-> | ||
| 375 | EnclosureLogicalID) && slot_number == le16_to_cpu(boot_device-> | ||
| 376 | SlotNumber)) ? 1 : 0; | ||
| 377 | } | ||
| 378 | |||
| 379 | /** | ||
| 380 | * _scsih_is_boot_device - search for matching boot device. | ||
| 381 | * @sas_address: sas address | ||
| 382 | * @device_name: device name specified in INDENTIFY fram | ||
| 383 | * @enclosure_logical_id: enclosure logical id | ||
| 384 | * @slot_number: slot number | ||
| 385 | * @form: specifies boot device form | ||
| 386 | * @boot_device: boot device object from bios page 2 | ||
| 387 | * | ||
| 388 | * Returns 1 when there's a match, 0 means no match. | ||
| 389 | */ | ||
| 390 | static int | ||
| 391 | _scsih_is_boot_device(u64 sas_address, u64 device_name, | ||
| 392 | u64 enclosure_logical_id, u16 slot, u8 form, | ||
| 393 | Mpi2BiosPage2BootDevice_t *boot_device) | ||
| 394 | { | ||
| 395 | int rc = 0; | ||
| 396 | |||
| 397 | switch (form) { | ||
| 398 | case MPI2_BIOSPAGE2_FORM_SAS_WWID: | ||
| 399 | if (!sas_address) | ||
| 400 | break; | ||
| 401 | rc = _scsih_srch_boot_sas_address( | ||
| 402 | sas_address, &boot_device->SasWwid); | ||
| 403 | break; | ||
| 404 | case MPI2_BIOSPAGE2_FORM_ENCLOSURE_SLOT: | ||
| 405 | if (!enclosure_logical_id) | ||
| 406 | break; | ||
| 407 | rc = _scsih_srch_boot_encl_slot( | ||
| 408 | enclosure_logical_id, | ||
| 409 | slot, &boot_device->EnclosureSlot); | ||
| 410 | break; | ||
| 411 | case MPI2_BIOSPAGE2_FORM_DEVICE_NAME: | ||
| 412 | if (!device_name) | ||
| 413 | break; | ||
| 414 | rc = _scsih_srch_boot_device_name( | ||
| 415 | device_name, &boot_device->DeviceName); | ||
| 416 | break; | ||
| 417 | case MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED: | ||
| 418 | break; | ||
| 419 | } | ||
| 420 | |||
| 421 | return rc; | ||
| 422 | } | ||
| 423 | |||
| 424 | /** | ||
| 425 | * _scsih_get_sas_address - set the sas_address for given device handle | ||
| 426 | * @handle: device handle | ||
| 427 | * @sas_address: sas address | ||
| 428 | * | ||
| 429 | * Returns 0 success, non-zero when failure | ||
| 430 | */ | ||
| 431 | static int | ||
| 432 | _scsih_get_sas_address(struct MPT2SAS_ADAPTER *ioc, u16 handle, | ||
| 433 | u64 *sas_address) | ||
| 434 | { | ||
| 435 | Mpi2SasDevicePage0_t sas_device_pg0; | ||
| 436 | Mpi2ConfigReply_t mpi_reply; | ||
| 437 | u32 ioc_status; | ||
| 438 | *sas_address = 0; | ||
| 439 | |||
| 440 | if (handle <= ioc->sas_hba.num_phys) { | ||
| 441 | *sas_address = ioc->sas_hba.sas_address; | ||
| 442 | return 0; | ||
| 443 | } | ||
| 444 | |||
| 445 | if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, | ||
| 446 | MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { | ||
| 447 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", ioc->name, | ||
| 448 | __FILE__, __LINE__, __func__); | ||
| 449 | return -ENXIO; | ||
| 450 | } | ||
| 451 | |||
| 452 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; | ||
| 453 | if (ioc_status == MPI2_IOCSTATUS_SUCCESS) { | ||
| 454 | *sas_address = le64_to_cpu(sas_device_pg0.SASAddress); | ||
| 455 | return 0; | ||
| 456 | } | ||
| 457 | |||
| 458 | /* we hit this becuase the given parent handle doesn't exist */ | ||
| 459 | if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) | ||
| 460 | return -ENXIO; | ||
| 461 | /* else error case */ | ||
| 462 | printk(MPT2SAS_ERR_FMT "handle(0x%04x), ioc_status(0x%04x), " | ||
| 463 | "failure at %s:%d/%s()!\n", ioc->name, handle, ioc_status, | ||
| 464 | __FILE__, __LINE__, __func__); | ||
| 465 | return -EIO; | ||
| 466 | } | ||
| 467 | |||
| 468 | /** | ||
| 469 | * _scsih_determine_boot_device - determine boot device. | ||
| 470 | * @ioc: per adapter object | ||
| 471 | * @device: either sas_device or raid_device object | ||
| 472 | * @is_raid: [flag] 1 = raid object, 0 = sas object | ||
| 473 | * | ||
| 474 | * Determines whether this device should be first reported device to | ||
| 475 | * to scsi-ml or sas transport, this purpose is for persistent boot device. | ||
| 476 | * There are primary, alternate, and current entries in bios page 2. The order | ||
| 477 | * priority is primary, alternate, then current. This routine saves | ||
| 478 | * the corresponding device object and is_raid flag in the ioc object. | ||
| 479 | * The saved data to be used later in _scsih_probe_boot_devices(). | ||
| 480 | */ | ||
| 481 | static void | ||
| 482 | _scsih_determine_boot_device(struct MPT2SAS_ADAPTER *ioc, | ||
| 483 | void *device, u8 is_raid) | ||
| 484 | { | ||
| 485 | struct _sas_device *sas_device; | ||
| 486 | struct _raid_device *raid_device; | ||
| 487 | u64 sas_address; | ||
| 488 | u64 device_name; | ||
| 489 | u64 enclosure_logical_id; | ||
| 490 | u16 slot; | ||
| 491 | |||
| 492 | /* only process this function when driver loads */ | ||
| 493 | if (!ioc->is_driver_loading) | ||
| 494 | return; | ||
| 495 | |||
| 496 | /* no Bios, return immediately */ | ||
| 497 | if (!ioc->bios_pg3.BiosVersion) | ||
| 498 | return; | ||
| 499 | |||
| 500 | if (!is_raid) { | ||
| 501 | sas_device = device; | ||
| 502 | sas_address = sas_device->sas_address; | ||
| 503 | device_name = sas_device->device_name; | ||
| 504 | enclosure_logical_id = sas_device->enclosure_logical_id; | ||
| 505 | slot = sas_device->slot; | ||
| 506 | } else { | ||
| 507 | raid_device = device; | ||
| 508 | sas_address = raid_device->wwid; | ||
| 509 | device_name = 0; | ||
| 510 | enclosure_logical_id = 0; | ||
| 511 | slot = 0; | ||
| 512 | } | ||
| 513 | |||
| 514 | if (!ioc->req_boot_device.device) { | ||
| 515 | if (_scsih_is_boot_device(sas_address, device_name, | ||
| 516 | enclosure_logical_id, slot, | ||
| 517 | (ioc->bios_pg2.ReqBootDeviceForm & | ||
| 518 | MPI2_BIOSPAGE2_FORM_MASK), | ||
| 519 | &ioc->bios_pg2.RequestedBootDevice)) { | ||
| 520 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 521 | "%s: req_boot_device(0x%016llx)\n", | ||
| 522 | ioc->name, __func__, | ||
| 523 | (unsigned long long)sas_address)); | ||
| 524 | ioc->req_boot_device.device = device; | ||
| 525 | ioc->req_boot_device.is_raid = is_raid; | ||
| 526 | } | ||
| 527 | } | ||
| 528 | |||
| 529 | if (!ioc->req_alt_boot_device.device) { | ||
| 530 | if (_scsih_is_boot_device(sas_address, device_name, | ||
| 531 | enclosure_logical_id, slot, | ||
| 532 | (ioc->bios_pg2.ReqAltBootDeviceForm & | ||
| 533 | MPI2_BIOSPAGE2_FORM_MASK), | ||
| 534 | &ioc->bios_pg2.RequestedAltBootDevice)) { | ||
| 535 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 536 | "%s: req_alt_boot_device(0x%016llx)\n", | ||
| 537 | ioc->name, __func__, | ||
| 538 | (unsigned long long)sas_address)); | ||
| 539 | ioc->req_alt_boot_device.device = device; | ||
| 540 | ioc->req_alt_boot_device.is_raid = is_raid; | ||
| 541 | } | ||
| 542 | } | ||
| 543 | |||
| 544 | if (!ioc->current_boot_device.device) { | ||
| 545 | if (_scsih_is_boot_device(sas_address, device_name, | ||
| 546 | enclosure_logical_id, slot, | ||
| 547 | (ioc->bios_pg2.CurrentBootDeviceForm & | ||
| 548 | MPI2_BIOSPAGE2_FORM_MASK), | ||
| 549 | &ioc->bios_pg2.CurrentBootDevice)) { | ||
| 550 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 551 | "%s: current_boot_device(0x%016llx)\n", | ||
| 552 | ioc->name, __func__, | ||
| 553 | (unsigned long long)sas_address)); | ||
| 554 | ioc->current_boot_device.device = device; | ||
| 555 | ioc->current_boot_device.is_raid = is_raid; | ||
| 556 | } | ||
| 557 | } | ||
| 558 | } | ||
| 559 | |||
| 560 | static struct _sas_device * | ||
| 561 | __mpt2sas_get_sdev_from_target(struct MPT2SAS_ADAPTER *ioc, | ||
| 562 | struct MPT2SAS_TARGET *tgt_priv) | ||
| 563 | { | ||
| 564 | struct _sas_device *ret; | ||
| 565 | |||
| 566 | assert_spin_locked(&ioc->sas_device_lock); | ||
| 567 | |||
| 568 | ret = tgt_priv->sdev; | ||
| 569 | if (ret) | ||
| 570 | sas_device_get(ret); | ||
| 571 | |||
| 572 | return ret; | ||
| 573 | } | ||
| 574 | |||
| 575 | static struct _sas_device * | ||
| 576 | mpt2sas_get_sdev_from_target(struct MPT2SAS_ADAPTER *ioc, | ||
| 577 | struct MPT2SAS_TARGET *tgt_priv) | ||
| 578 | { | ||
| 579 | struct _sas_device *ret; | ||
| 580 | unsigned long flags; | ||
| 581 | |||
| 582 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 583 | ret = __mpt2sas_get_sdev_from_target(ioc, tgt_priv); | ||
| 584 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 585 | |||
| 586 | return ret; | ||
| 587 | } | ||
| 588 | |||
| 589 | |||
| 590 | struct _sas_device * | ||
| 591 | __mpt2sas_get_sdev_by_addr(struct MPT2SAS_ADAPTER *ioc, | ||
| 592 | u64 sas_address) | ||
| 593 | { | ||
| 594 | struct _sas_device *sas_device; | ||
| 595 | |||
| 596 | assert_spin_locked(&ioc->sas_device_lock); | ||
| 597 | |||
| 598 | list_for_each_entry(sas_device, &ioc->sas_device_list, list) | ||
| 599 | if (sas_device->sas_address == sas_address) | ||
| 600 | goto found_device; | ||
| 601 | |||
| 602 | list_for_each_entry(sas_device, &ioc->sas_device_init_list, list) | ||
| 603 | if (sas_device->sas_address == sas_address) | ||
| 604 | goto found_device; | ||
| 605 | |||
| 606 | return NULL; | ||
| 607 | |||
| 608 | found_device: | ||
| 609 | sas_device_get(sas_device); | ||
| 610 | return sas_device; | ||
| 611 | } | ||
| 612 | |||
| 613 | /** | ||
| 614 | * mpt2sas_get_sdev_by_addr - sas device search | ||
| 615 | * @ioc: per adapter object | ||
| 616 | * @sas_address: sas address | ||
| 617 | * Context: Calling function should acquire ioc->sas_device_lock | ||
| 618 | * | ||
| 619 | * This searches for sas_device based on sas_address, then return sas_device | ||
| 620 | * object. | ||
| 621 | */ | ||
| 622 | struct _sas_device * | ||
| 623 | mpt2sas_get_sdev_by_addr(struct MPT2SAS_ADAPTER *ioc, | ||
| 624 | u64 sas_address) | ||
| 625 | { | ||
| 626 | struct _sas_device *sas_device; | ||
| 627 | unsigned long flags; | ||
| 628 | |||
| 629 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 630 | sas_device = __mpt2sas_get_sdev_by_addr(ioc, | ||
| 631 | sas_address); | ||
| 632 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 633 | |||
| 634 | return sas_device; | ||
| 635 | } | ||
| 636 | |||
| 637 | static struct _sas_device * | ||
| 638 | __mpt2sas_get_sdev_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle) | ||
| 639 | { | ||
| 640 | struct _sas_device *sas_device; | ||
| 641 | |||
| 642 | assert_spin_locked(&ioc->sas_device_lock); | ||
| 643 | |||
| 644 | list_for_each_entry(sas_device, &ioc->sas_device_list, list) | ||
| 645 | if (sas_device->handle == handle) | ||
| 646 | goto found_device; | ||
| 647 | |||
| 648 | list_for_each_entry(sas_device, &ioc->sas_device_init_list, list) | ||
| 649 | if (sas_device->handle == handle) | ||
| 650 | goto found_device; | ||
| 651 | |||
| 652 | return NULL; | ||
| 653 | |||
| 654 | found_device: | ||
| 655 | sas_device_get(sas_device); | ||
| 656 | return sas_device; | ||
| 657 | } | ||
| 658 | |||
| 659 | /** | ||
| 660 | * mpt2sas_get_sdev_by_handle - sas device search | ||
| 661 | * @ioc: per adapter object | ||
| 662 | * @handle: sas device handle (assigned by firmware) | ||
| 663 | * Context: Calling function should acquire ioc->sas_device_lock | ||
| 664 | * | ||
| 665 | * This searches for sas_device based on sas_address, then return sas_device | ||
| 666 | * object. | ||
| 667 | */ | ||
| 668 | static struct _sas_device * | ||
| 669 | mpt2sas_get_sdev_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle) | ||
| 670 | { | ||
| 671 | struct _sas_device *sas_device; | ||
| 672 | unsigned long flags; | ||
| 673 | |||
| 674 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 675 | sas_device = __mpt2sas_get_sdev_by_handle(ioc, handle); | ||
| 676 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 677 | |||
| 678 | return sas_device; | ||
| 679 | } | ||
| 680 | |||
| 681 | /** | ||
| 682 | * _scsih_sas_device_remove - remove sas_device from list. | ||
| 683 | * @ioc: per adapter object | ||
| 684 | * @sas_device: the sas_device object | ||
| 685 | * Context: This function will acquire ioc->sas_device_lock. | ||
| 686 | * | ||
| 687 | * If sas_device is on the list, remove it and decrement its reference count. | ||
| 688 | */ | ||
| 689 | static void | ||
| 690 | _scsih_sas_device_remove(struct MPT2SAS_ADAPTER *ioc, | ||
| 691 | struct _sas_device *sas_device) | ||
| 692 | { | ||
| 693 | unsigned long flags; | ||
| 694 | |||
| 695 | if (!sas_device) | ||
| 696 | return; | ||
| 697 | |||
| 698 | /* | ||
| 699 | * The lock serializes access to the list, but we still need to verify | ||
| 700 | * that nobody removed the entry while we were waiting on the lock. | ||
| 701 | */ | ||
| 702 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 703 | if (!list_empty(&sas_device->list)) { | ||
| 704 | list_del_init(&sas_device->list); | ||
| 705 | sas_device_put(sas_device); | ||
| 706 | } | ||
| 707 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 708 | } | ||
| 709 | |||
| 710 | |||
| 711 | /** | ||
| 712 | * _scsih_sas_device_add - insert sas_device to the list. | ||
| 713 | * @ioc: per adapter object | ||
| 714 | * @sas_device: the sas_device object | ||
| 715 | * Context: This function will acquire ioc->sas_device_lock. | ||
| 716 | * | ||
| 717 | * Adding new object to the ioc->sas_device_list. | ||
| 718 | */ | ||
| 719 | static void | ||
| 720 | _scsih_sas_device_add(struct MPT2SAS_ADAPTER *ioc, | ||
| 721 | struct _sas_device *sas_device) | ||
| 722 | { | ||
| 723 | unsigned long flags; | ||
| 724 | |||
| 725 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: handle" | ||
| 726 | "(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__, | ||
| 727 | sas_device->handle, (unsigned long long)sas_device->sas_address)); | ||
| 728 | |||
| 729 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 730 | sas_device_get(sas_device); | ||
| 731 | list_add_tail(&sas_device->list, &ioc->sas_device_list); | ||
| 732 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 733 | |||
| 734 | if (!mpt2sas_transport_port_add(ioc, sas_device->handle, | ||
| 735 | sas_device->sas_address_parent)) { | ||
| 736 | _scsih_sas_device_remove(ioc, sas_device); | ||
| 737 | } else if (!sas_device->starget) { | ||
| 738 | /* When asyn scanning is enabled, its not possible to remove | ||
| 739 | * devices while scanning is turned on due to an oops in | ||
| 740 | * scsi_sysfs_add_sdev()->add_device()->sysfs_addrm_start() | ||
| 741 | */ | ||
| 742 | if (!ioc->is_driver_loading) { | ||
| 743 | mpt2sas_transport_port_remove(ioc, | ||
| 744 | sas_device->sas_address, | ||
| 745 | sas_device->sas_address_parent); | ||
| 746 | _scsih_sas_device_remove(ioc, sas_device); | ||
| 747 | } | ||
| 748 | } | ||
| 749 | } | ||
| 750 | |||
| 751 | /** | ||
| 752 | * _scsih_sas_device_init_add - insert sas_device to the list. | ||
| 753 | * @ioc: per adapter object | ||
| 754 | * @sas_device: the sas_device object | ||
| 755 | * Context: This function will acquire ioc->sas_device_lock. | ||
| 756 | * | ||
| 757 | * Adding new object at driver load time to the ioc->sas_device_init_list. | ||
| 758 | */ | ||
| 759 | static void | ||
| 760 | _scsih_sas_device_init_add(struct MPT2SAS_ADAPTER *ioc, | ||
| 761 | struct _sas_device *sas_device) | ||
| 762 | { | ||
| 763 | unsigned long flags; | ||
| 764 | |||
| 765 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: handle" | ||
| 766 | "(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__, | ||
| 767 | sas_device->handle, (unsigned long long)sas_device->sas_address)); | ||
| 768 | |||
| 769 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 770 | sas_device_get(sas_device); | ||
| 771 | list_add_tail(&sas_device->list, &ioc->sas_device_init_list); | ||
| 772 | _scsih_determine_boot_device(ioc, sas_device, 0); | ||
| 773 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 774 | } | ||
| 775 | |||
| 776 | /** | ||
| 777 | * _scsih_raid_device_find_by_id - raid device search | ||
| 778 | * @ioc: per adapter object | ||
| 779 | * @id: sas device target id | ||
| 780 | * @channel: sas device channel | ||
| 781 | * Context: Calling function should acquire ioc->raid_device_lock | ||
| 782 | * | ||
| 783 | * This searches for raid_device based on target id, then return raid_device | ||
| 784 | * object. | ||
| 785 | */ | ||
| 786 | static struct _raid_device * | ||
| 787 | _scsih_raid_device_find_by_id(struct MPT2SAS_ADAPTER *ioc, int id, int channel) | ||
| 788 | { | ||
| 789 | struct _raid_device *raid_device, *r; | ||
| 790 | |||
| 791 | r = NULL; | ||
| 792 | list_for_each_entry(raid_device, &ioc->raid_device_list, list) { | ||
| 793 | if (raid_device->id == id && raid_device->channel == channel) { | ||
| 794 | r = raid_device; | ||
| 795 | goto out; | ||
| 796 | } | ||
| 797 | } | ||
| 798 | |||
| 799 | out: | ||
| 800 | return r; | ||
| 801 | } | ||
| 802 | |||
| 803 | /** | ||
| 804 | * _scsih_raid_device_find_by_handle - raid device search | ||
| 805 | * @ioc: per adapter object | ||
| 806 | * @handle: sas device handle (assigned by firmware) | ||
| 807 | * Context: Calling function should acquire ioc->raid_device_lock | ||
| 808 | * | ||
| 809 | * This searches for raid_device based on handle, then return raid_device | ||
| 810 | * object. | ||
| 811 | */ | ||
| 812 | static struct _raid_device * | ||
| 813 | _scsih_raid_device_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle) | ||
| 814 | { | ||
| 815 | struct _raid_device *raid_device, *r; | ||
| 816 | |||
| 817 | r = NULL; | ||
| 818 | list_for_each_entry(raid_device, &ioc->raid_device_list, list) { | ||
| 819 | if (raid_device->handle != handle) | ||
| 820 | continue; | ||
| 821 | r = raid_device; | ||
| 822 | goto out; | ||
| 823 | } | ||
| 824 | |||
| 825 | out: | ||
| 826 | return r; | ||
| 827 | } | ||
| 828 | |||
| 829 | /** | ||
| 830 | * _scsih_raid_device_find_by_wwid - raid device search | ||
| 831 | * @ioc: per adapter object | ||
| 832 | * @handle: sas device handle (assigned by firmware) | ||
| 833 | * Context: Calling function should acquire ioc->raid_device_lock | ||
| 834 | * | ||
| 835 | * This searches for raid_device based on wwid, then return raid_device | ||
| 836 | * object. | ||
| 837 | */ | ||
| 838 | static struct _raid_device * | ||
| 839 | _scsih_raid_device_find_by_wwid(struct MPT2SAS_ADAPTER *ioc, u64 wwid) | ||
| 840 | { | ||
| 841 | struct _raid_device *raid_device, *r; | ||
| 842 | |||
| 843 | r = NULL; | ||
| 844 | list_for_each_entry(raid_device, &ioc->raid_device_list, list) { | ||
| 845 | if (raid_device->wwid != wwid) | ||
| 846 | continue; | ||
| 847 | r = raid_device; | ||
| 848 | goto out; | ||
| 849 | } | ||
| 850 | |||
| 851 | out: | ||
| 852 | return r; | ||
| 853 | } | ||
| 854 | |||
| 855 | /** | ||
| 856 | * _scsih_raid_device_add - add raid_device object | ||
| 857 | * @ioc: per adapter object | ||
| 858 | * @raid_device: raid_device object | ||
| 859 | * | ||
| 860 | * This is added to the raid_device_list link list. | ||
| 861 | */ | ||
| 862 | static void | ||
| 863 | _scsih_raid_device_add(struct MPT2SAS_ADAPTER *ioc, | ||
| 864 | struct _raid_device *raid_device) | ||
| 865 | { | ||
| 866 | unsigned long flags; | ||
| 867 | |||
| 868 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: handle" | ||
| 869 | "(0x%04x), wwid(0x%016llx)\n", ioc->name, __func__, | ||
| 870 | raid_device->handle, (unsigned long long)raid_device->wwid)); | ||
| 871 | |||
| 872 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | ||
| 873 | list_add_tail(&raid_device->list, &ioc->raid_device_list); | ||
| 874 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); | ||
| 875 | } | ||
| 876 | |||
| 877 | /** | ||
| 878 | * _scsih_raid_device_remove - delete raid_device object | ||
| 879 | * @ioc: per adapter object | ||
| 880 | * @raid_device: raid_device object | ||
| 881 | * | ||
| 882 | */ | ||
| 883 | static void | ||
| 884 | _scsih_raid_device_remove(struct MPT2SAS_ADAPTER *ioc, | ||
| 885 | struct _raid_device *raid_device) | ||
| 886 | { | ||
| 887 | unsigned long flags; | ||
| 888 | |||
| 889 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | ||
| 890 | list_del(&raid_device->list); | ||
| 891 | kfree(raid_device); | ||
| 892 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); | ||
| 893 | } | ||
| 894 | |||
| 895 | /** | ||
| 896 | * mpt2sas_scsih_expander_find_by_handle - expander device search | ||
| 897 | * @ioc: per adapter object | ||
| 898 | * @handle: expander handle (assigned by firmware) | ||
| 899 | * Context: Calling function should acquire ioc->sas_device_lock | ||
| 900 | * | ||
| 901 | * This searches for expander device based on handle, then returns the | ||
| 902 | * sas_node object. | ||
| 903 | */ | ||
| 904 | struct _sas_node * | ||
| 905 | mpt2sas_scsih_expander_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle) | ||
| 906 | { | ||
| 907 | struct _sas_node *sas_expander, *r; | ||
| 908 | |||
| 909 | r = NULL; | ||
| 910 | list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) { | ||
| 911 | if (sas_expander->handle != handle) | ||
| 912 | continue; | ||
| 913 | r = sas_expander; | ||
| 914 | goto out; | ||
| 915 | } | ||
| 916 | out: | ||
| 917 | return r; | ||
| 918 | } | ||
| 919 | |||
| 920 | /** | ||
| 921 | * mpt2sas_scsih_expander_find_by_sas_address - expander device search | ||
| 922 | * @ioc: per adapter object | ||
| 923 | * @sas_address: sas address | ||
| 924 | * Context: Calling function should acquire ioc->sas_node_lock. | ||
| 925 | * | ||
| 926 | * This searches for expander device based on sas_address, then returns the | ||
| 927 | * sas_node object. | ||
| 928 | */ | ||
| 929 | struct _sas_node * | ||
| 930 | mpt2sas_scsih_expander_find_by_sas_address(struct MPT2SAS_ADAPTER *ioc, | ||
| 931 | u64 sas_address) | ||
| 932 | { | ||
| 933 | struct _sas_node *sas_expander, *r; | ||
| 934 | |||
| 935 | r = NULL; | ||
| 936 | list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) { | ||
| 937 | if (sas_expander->sas_address != sas_address) | ||
| 938 | continue; | ||
| 939 | r = sas_expander; | ||
| 940 | goto out; | ||
| 941 | } | ||
| 942 | out: | ||
| 943 | return r; | ||
| 944 | } | ||
| 945 | |||
| 946 | /** | ||
| 947 | * _scsih_expander_node_add - insert expander device to the list. | ||
| 948 | * @ioc: per adapter object | ||
| 949 | * @sas_expander: the sas_device object | ||
| 950 | * Context: This function will acquire ioc->sas_node_lock. | ||
| 951 | * | ||
| 952 | * Adding new object to the ioc->sas_expander_list. | ||
| 953 | * | ||
| 954 | * Return nothing. | ||
| 955 | */ | ||
| 956 | static void | ||
| 957 | _scsih_expander_node_add(struct MPT2SAS_ADAPTER *ioc, | ||
| 958 | struct _sas_node *sas_expander) | ||
| 959 | { | ||
| 960 | unsigned long flags; | ||
| 961 | |||
| 962 | spin_lock_irqsave(&ioc->sas_node_lock, flags); | ||
| 963 | list_add_tail(&sas_expander->list, &ioc->sas_expander_list); | ||
| 964 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | ||
| 965 | } | ||
| 966 | |||
| 967 | /** | ||
| 968 | * _scsih_is_end_device - determines if device is an end device | ||
| 969 | * @device_info: bitfield providing information about the device. | ||
| 970 | * Context: none | ||
| 971 | * | ||
| 972 | * Returns 1 if end device. | ||
| 973 | */ | ||
| 974 | static int | ||
| 975 | _scsih_is_end_device(u32 device_info) | ||
| 976 | { | ||
| 977 | if (device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE && | ||
| 978 | ((device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) | | ||
| 979 | (device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET) | | ||
| 980 | (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE))) | ||
| 981 | return 1; | ||
| 982 | else | ||
| 983 | return 0; | ||
| 984 | } | ||
| 985 | |||
| 986 | /** | ||
| 987 | * _scsih_scsi_lookup_get - returns scmd entry | ||
| 988 | * @ioc: per adapter object | ||
| 989 | * @smid: system request message index | ||
| 990 | * | ||
| 991 | * Returns the smid stored scmd pointer. | ||
| 992 | */ | ||
| 993 | static struct scsi_cmnd * | ||
| 994 | _scsih_scsi_lookup_get(struct MPT2SAS_ADAPTER *ioc, u16 smid) | ||
| 995 | { | ||
| 996 | return ioc->scsi_lookup[smid - 1].scmd; | ||
| 997 | } | ||
| 998 | |||
| 999 | /** | ||
| 1000 | * _scsih_scsi_lookup_get_clear - returns scmd entry | ||
| 1001 | * @ioc: per adapter object | ||
| 1002 | * @smid: system request message index | ||
| 1003 | * | ||
| 1004 | * Returns the smid stored scmd pointer. | ||
| 1005 | * Then will derefrence the stored scmd pointer. | ||
| 1006 | */ | ||
| 1007 | static inline struct scsi_cmnd * | ||
| 1008 | _scsih_scsi_lookup_get_clear(struct MPT2SAS_ADAPTER *ioc, u16 smid) | ||
| 1009 | { | ||
| 1010 | unsigned long flags; | ||
| 1011 | struct scsi_cmnd *scmd; | ||
| 1012 | |||
| 1013 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | ||
| 1014 | scmd = ioc->scsi_lookup[smid - 1].scmd; | ||
| 1015 | ioc->scsi_lookup[smid - 1].scmd = NULL; | ||
| 1016 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | ||
| 1017 | |||
| 1018 | return scmd; | ||
| 1019 | } | ||
| 1020 | |||
| 1021 | /** | ||
| 1022 | * _scsih_scsi_lookup_find_by_scmd - scmd lookup | ||
| 1023 | * @ioc: per adapter object | ||
| 1024 | * @smid: system request message index | ||
| 1025 | * @scmd: pointer to scsi command object | ||
| 1026 | * Context: This function will acquire ioc->scsi_lookup_lock. | ||
| 1027 | * | ||
| 1028 | * This will search for a scmd pointer in the scsi_lookup array, | ||
| 1029 | * returning the revelent smid. A returned value of zero means invalid. | ||
| 1030 | */ | ||
| 1031 | static u16 | ||
| 1032 | _scsih_scsi_lookup_find_by_scmd(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd | ||
| 1033 | *scmd) | ||
| 1034 | { | ||
| 1035 | u16 smid; | ||
| 1036 | unsigned long flags; | ||
| 1037 | int i; | ||
| 1038 | |||
| 1039 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | ||
| 1040 | smid = 0; | ||
| 1041 | for (i = 0; i < ioc->scsiio_depth; i++) { | ||
| 1042 | if (ioc->scsi_lookup[i].scmd == scmd) { | ||
| 1043 | smid = ioc->scsi_lookup[i].smid; | ||
| 1044 | goto out; | ||
| 1045 | } | ||
| 1046 | } | ||
| 1047 | out: | ||
| 1048 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | ||
| 1049 | return smid; | ||
| 1050 | } | ||
| 1051 | |||
| 1052 | /** | ||
| 1053 | * _scsih_scsi_lookup_find_by_target - search for matching channel:id | ||
| 1054 | * @ioc: per adapter object | ||
| 1055 | * @id: target id | ||
| 1056 | * @channel: channel | ||
| 1057 | * Context: This function will acquire ioc->scsi_lookup_lock. | ||
| 1058 | * | ||
| 1059 | * This will search for a matching channel:id in the scsi_lookup array, | ||
| 1060 | * returning 1 if found. | ||
| 1061 | */ | ||
| 1062 | static u8 | ||
| 1063 | _scsih_scsi_lookup_find_by_target(struct MPT2SAS_ADAPTER *ioc, int id, | ||
| 1064 | int channel) | ||
| 1065 | { | ||
| 1066 | u8 found; | ||
| 1067 | unsigned long flags; | ||
| 1068 | int i; | ||
| 1069 | |||
| 1070 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | ||
| 1071 | found = 0; | ||
| 1072 | for (i = 0 ; i < ioc->scsiio_depth; i++) { | ||
| 1073 | if (ioc->scsi_lookup[i].scmd && | ||
| 1074 | (ioc->scsi_lookup[i].scmd->device->id == id && | ||
| 1075 | ioc->scsi_lookup[i].scmd->device->channel == channel)) { | ||
| 1076 | found = 1; | ||
| 1077 | goto out; | ||
| 1078 | } | ||
| 1079 | } | ||
| 1080 | out: | ||
| 1081 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | ||
| 1082 | return found; | ||
| 1083 | } | ||
| 1084 | |||
| 1085 | /** | ||
| 1086 | * _scsih_scsi_lookup_find_by_lun - search for matching channel:id:lun | ||
| 1087 | * @ioc: per adapter object | ||
| 1088 | * @id: target id | ||
| 1089 | * @lun: lun number | ||
| 1090 | * @channel: channel | ||
| 1091 | * Context: This function will acquire ioc->scsi_lookup_lock. | ||
| 1092 | * | ||
| 1093 | * This will search for a matching channel:id:lun in the scsi_lookup array, | ||
| 1094 | * returning 1 if found. | ||
| 1095 | */ | ||
| 1096 | static u8 | ||
| 1097 | _scsih_scsi_lookup_find_by_lun(struct MPT2SAS_ADAPTER *ioc, int id, | ||
| 1098 | unsigned int lun, int channel) | ||
| 1099 | { | ||
| 1100 | u8 found; | ||
| 1101 | unsigned long flags; | ||
| 1102 | int i; | ||
| 1103 | |||
| 1104 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | ||
| 1105 | found = 0; | ||
| 1106 | for (i = 0 ; i < ioc->scsiio_depth; i++) { | ||
| 1107 | if (ioc->scsi_lookup[i].scmd && | ||
| 1108 | (ioc->scsi_lookup[i].scmd->device->id == id && | ||
| 1109 | ioc->scsi_lookup[i].scmd->device->channel == channel && | ||
| 1110 | ioc->scsi_lookup[i].scmd->device->lun == lun)) { | ||
| 1111 | found = 1; | ||
| 1112 | goto out; | ||
| 1113 | } | ||
| 1114 | } | ||
| 1115 | out: | ||
| 1116 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | ||
| 1117 | return found; | ||
| 1118 | } | ||
| 1119 | |||
| 1120 | /** | ||
| 1121 | * _scsih_get_chain_buffer_tracker - obtain chain tracker | ||
| 1122 | * @ioc: per adapter object | ||
| 1123 | * @smid: smid associated to an IO request | ||
| 1124 | * | ||
| 1125 | * Returns chain tracker(from ioc->free_chain_list) | ||
| 1126 | */ | ||
| 1127 | static struct chain_tracker * | ||
| 1128 | _scsih_get_chain_buffer_tracker(struct MPT2SAS_ADAPTER *ioc, u16 smid) | ||
| 1129 | { | ||
| 1130 | struct chain_tracker *chain_req; | ||
| 1131 | unsigned long flags; | ||
| 1132 | |||
| 1133 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | ||
| 1134 | if (list_empty(&ioc->free_chain_list)) { | ||
| 1135 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | ||
| 1136 | dfailprintk(ioc, printk(MPT2SAS_WARN_FMT "chain buffers not " | ||
| 1137 | "available\n", ioc->name)); | ||
| 1138 | return NULL; | ||
| 1139 | } | ||
| 1140 | chain_req = list_entry(ioc->free_chain_list.next, | ||
| 1141 | struct chain_tracker, tracker_list); | ||
| 1142 | list_del_init(&chain_req->tracker_list); | ||
| 1143 | list_add_tail(&chain_req->tracker_list, | ||
| 1144 | &ioc->scsi_lookup[smid - 1].chain_list); | ||
| 1145 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | ||
| 1146 | return chain_req; | ||
| 1147 | } | ||
| 1148 | |||
| 1149 | /** | ||
| 1150 | * _scsih_build_scatter_gather - main sg creation routine | ||
| 1151 | * @ioc: per adapter object | ||
| 1152 | * @scmd: scsi command | ||
| 1153 | * @smid: system request message index | ||
| 1154 | * Context: none. | ||
| 1155 | * | ||
| 1156 | * The main routine that builds scatter gather table from a given | ||
| 1157 | * scsi request sent via the .queuecommand main handler. | ||
| 1158 | * | ||
| 1159 | * Returns 0 success, anything else error | ||
| 1160 | */ | ||
| 1161 | static int | ||
| 1162 | _scsih_build_scatter_gather(struct MPT2SAS_ADAPTER *ioc, | ||
| 1163 | struct scsi_cmnd *scmd, u16 smid) | ||
| 1164 | { | ||
| 1165 | Mpi2SCSIIORequest_t *mpi_request; | ||
| 1166 | dma_addr_t chain_dma; | ||
| 1167 | struct scatterlist *sg_scmd; | ||
| 1168 | void *sg_local, *chain; | ||
| 1169 | u32 chain_offset; | ||
| 1170 | u32 chain_length; | ||
| 1171 | u32 chain_flags; | ||
| 1172 | int sges_left; | ||
| 1173 | u32 sges_in_segment; | ||
| 1174 | u32 sgl_flags; | ||
| 1175 | u32 sgl_flags_last_element; | ||
| 1176 | u32 sgl_flags_end_buffer; | ||
| 1177 | struct chain_tracker *chain_req; | ||
| 1178 | |||
| 1179 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); | ||
| 1180 | |||
| 1181 | /* init scatter gather flags */ | ||
| 1182 | sgl_flags = MPI2_SGE_FLAGS_SIMPLE_ELEMENT; | ||
| 1183 | if (scmd->sc_data_direction == DMA_TO_DEVICE) | ||
| 1184 | sgl_flags |= MPI2_SGE_FLAGS_HOST_TO_IOC; | ||
| 1185 | sgl_flags_last_element = (sgl_flags | MPI2_SGE_FLAGS_LAST_ELEMENT) | ||
| 1186 | << MPI2_SGE_FLAGS_SHIFT; | ||
| 1187 | sgl_flags_end_buffer = (sgl_flags | MPI2_SGE_FLAGS_LAST_ELEMENT | | ||
| 1188 | MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_END_OF_LIST) | ||
| 1189 | << MPI2_SGE_FLAGS_SHIFT; | ||
| 1190 | sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; | ||
| 1191 | |||
| 1192 | sg_scmd = scsi_sglist(scmd); | ||
| 1193 | sges_left = scsi_dma_map(scmd); | ||
| 1194 | if (sges_left < 0) { | ||
| 1195 | sdev_printk(KERN_ERR, scmd->device, "pci_map_sg" | ||
| 1196 | " failed: request for %d bytes!\n", scsi_bufflen(scmd)); | ||
| 1197 | return -ENOMEM; | ||
| 1198 | } | ||
| 1199 | |||
| 1200 | sg_local = &mpi_request->SGL; | ||
| 1201 | sges_in_segment = ioc->max_sges_in_main_message; | ||
| 1202 | if (sges_left <= sges_in_segment) | ||
| 1203 | goto fill_in_last_segment; | ||
| 1204 | |||
| 1205 | mpi_request->ChainOffset = (offsetof(Mpi2SCSIIORequest_t, SGL) + | ||
| 1206 | (sges_in_segment * ioc->sge_size))/4; | ||
| 1207 | |||
| 1208 | /* fill in main message segment when there is a chain following */ | ||
| 1209 | while (sges_in_segment) { | ||
| 1210 | if (sges_in_segment == 1) | ||
| 1211 | ioc->base_add_sg_single(sg_local, | ||
| 1212 | sgl_flags_last_element | sg_dma_len(sg_scmd), | ||
| 1213 | sg_dma_address(sg_scmd)); | ||
| 1214 | else | ||
| 1215 | ioc->base_add_sg_single(sg_local, sgl_flags | | ||
| 1216 | sg_dma_len(sg_scmd), sg_dma_address(sg_scmd)); | ||
| 1217 | sg_scmd = sg_next(sg_scmd); | ||
| 1218 | sg_local += ioc->sge_size; | ||
| 1219 | sges_left--; | ||
| 1220 | sges_in_segment--; | ||
| 1221 | } | ||
| 1222 | |||
| 1223 | /* initializing the chain flags and pointers */ | ||
| 1224 | chain_flags = MPI2_SGE_FLAGS_CHAIN_ELEMENT << MPI2_SGE_FLAGS_SHIFT; | ||
| 1225 | chain_req = _scsih_get_chain_buffer_tracker(ioc, smid); | ||
| 1226 | if (!chain_req) | ||
| 1227 | return -1; | ||
| 1228 | chain = chain_req->chain_buffer; | ||
| 1229 | chain_dma = chain_req->chain_buffer_dma; | ||
| 1230 | do { | ||
| 1231 | sges_in_segment = (sges_left <= | ||
| 1232 | ioc->max_sges_in_chain_message) ? sges_left : | ||
| 1233 | ioc->max_sges_in_chain_message; | ||
| 1234 | chain_offset = (sges_left == sges_in_segment) ? | ||
| 1235 | 0 : (sges_in_segment * ioc->sge_size)/4; | ||
| 1236 | chain_length = sges_in_segment * ioc->sge_size; | ||
| 1237 | if (chain_offset) { | ||
| 1238 | chain_offset = chain_offset << | ||
| 1239 | MPI2_SGE_CHAIN_OFFSET_SHIFT; | ||
| 1240 | chain_length += ioc->sge_size; | ||
| 1241 | } | ||
| 1242 | ioc->base_add_sg_single(sg_local, chain_flags | chain_offset | | ||
| 1243 | chain_length, chain_dma); | ||
| 1244 | sg_local = chain; | ||
| 1245 | if (!chain_offset) | ||
| 1246 | goto fill_in_last_segment; | ||
| 1247 | |||
| 1248 | /* fill in chain segments */ | ||
| 1249 | while (sges_in_segment) { | ||
| 1250 | if (sges_in_segment == 1) | ||
| 1251 | ioc->base_add_sg_single(sg_local, | ||
| 1252 | sgl_flags_last_element | | ||
| 1253 | sg_dma_len(sg_scmd), | ||
| 1254 | sg_dma_address(sg_scmd)); | ||
| 1255 | else | ||
| 1256 | ioc->base_add_sg_single(sg_local, sgl_flags | | ||
| 1257 | sg_dma_len(sg_scmd), | ||
| 1258 | sg_dma_address(sg_scmd)); | ||
| 1259 | sg_scmd = sg_next(sg_scmd); | ||
| 1260 | sg_local += ioc->sge_size; | ||
| 1261 | sges_left--; | ||
| 1262 | sges_in_segment--; | ||
| 1263 | } | ||
| 1264 | |||
| 1265 | chain_req = _scsih_get_chain_buffer_tracker(ioc, smid); | ||
| 1266 | if (!chain_req) | ||
| 1267 | return -1; | ||
| 1268 | chain = chain_req->chain_buffer; | ||
| 1269 | chain_dma = chain_req->chain_buffer_dma; | ||
| 1270 | } while (1); | ||
| 1271 | |||
| 1272 | |||
| 1273 | fill_in_last_segment: | ||
| 1274 | |||
| 1275 | /* fill the last segment */ | ||
| 1276 | while (sges_left) { | ||
| 1277 | if (sges_left == 1) | ||
| 1278 | ioc->base_add_sg_single(sg_local, sgl_flags_end_buffer | | ||
| 1279 | sg_dma_len(sg_scmd), sg_dma_address(sg_scmd)); | ||
| 1280 | else | ||
| 1281 | ioc->base_add_sg_single(sg_local, sgl_flags | | ||
| 1282 | sg_dma_len(sg_scmd), sg_dma_address(sg_scmd)); | ||
| 1283 | sg_scmd = sg_next(sg_scmd); | ||
| 1284 | sg_local += ioc->sge_size; | ||
| 1285 | sges_left--; | ||
| 1286 | } | ||
| 1287 | |||
| 1288 | return 0; | ||
| 1289 | } | ||
| 1290 | |||
| 1291 | /** | ||
| 1292 | * _scsih_change_queue_depth - setting device queue depth | ||
| 1293 | * @sdev: scsi device struct | ||
| 1294 | * @qdepth: requested queue depth | ||
| 1295 | * | ||
| 1296 | * Returns queue depth. | ||
| 1297 | */ | ||
| 1298 | static int | ||
| 1299 | _scsih_change_queue_depth(struct scsi_device *sdev, int qdepth) | ||
| 1300 | { | ||
| 1301 | struct Scsi_Host *shost = sdev->host; | ||
| 1302 | int max_depth; | ||
| 1303 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 1304 | struct MPT2SAS_DEVICE *sas_device_priv_data; | ||
| 1305 | struct MPT2SAS_TARGET *sas_target_priv_data; | ||
| 1306 | struct _sas_device *sas_device; | ||
| 1307 | unsigned long flags; | ||
| 1308 | |||
| 1309 | max_depth = shost->can_queue; | ||
| 1310 | |||
| 1311 | /* limit max device queue for SATA to 32 */ | ||
| 1312 | sas_device_priv_data = sdev->hostdata; | ||
| 1313 | if (!sas_device_priv_data) | ||
| 1314 | goto not_sata; | ||
| 1315 | sas_target_priv_data = sas_device_priv_data->sas_target; | ||
| 1316 | if (!sas_target_priv_data) | ||
| 1317 | goto not_sata; | ||
| 1318 | if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) | ||
| 1319 | goto not_sata; | ||
| 1320 | |||
| 1321 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 1322 | sas_device = __mpt2sas_get_sdev_from_target(ioc, sas_target_priv_data); | ||
| 1323 | if (sas_device) { | ||
| 1324 | if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) | ||
| 1325 | max_depth = MPT2SAS_SATA_QUEUE_DEPTH; | ||
| 1326 | |||
| 1327 | sas_device_put(sas_device); | ||
| 1328 | } | ||
| 1329 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 1330 | |||
| 1331 | not_sata: | ||
| 1332 | if (!sdev->tagged_supported) | ||
| 1333 | max_depth = 1; | ||
| 1334 | if (qdepth > max_depth) | ||
| 1335 | qdepth = max_depth; | ||
| 1336 | return scsi_change_queue_depth(sdev, qdepth); | ||
| 1337 | } | ||
| 1338 | |||
| 1339 | /** | ||
| 1340 | * _scsih_target_alloc - target add routine | ||
| 1341 | * @starget: scsi target struct | ||
| 1342 | * | ||
| 1343 | * Returns 0 if ok. Any other return is assumed to be an error and | ||
| 1344 | * the device is ignored. | ||
| 1345 | */ | ||
| 1346 | static int | ||
| 1347 | _scsih_target_alloc(struct scsi_target *starget) | ||
| 1348 | { | ||
| 1349 | struct Scsi_Host *shost = dev_to_shost(&starget->dev); | ||
| 1350 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 1351 | struct MPT2SAS_TARGET *sas_target_priv_data; | ||
| 1352 | struct _sas_device *sas_device; | ||
| 1353 | struct _raid_device *raid_device; | ||
| 1354 | unsigned long flags; | ||
| 1355 | struct sas_rphy *rphy; | ||
| 1356 | |||
| 1357 | sas_target_priv_data = kzalloc(sizeof(*sas_target_priv_data), | ||
| 1358 | GFP_KERNEL); | ||
| 1359 | if (!sas_target_priv_data) | ||
| 1360 | return -ENOMEM; | ||
| 1361 | |||
| 1362 | starget->hostdata = sas_target_priv_data; | ||
| 1363 | sas_target_priv_data->starget = starget; | ||
| 1364 | sas_target_priv_data->handle = MPT2SAS_INVALID_DEVICE_HANDLE; | ||
| 1365 | |||
| 1366 | /* RAID volumes */ | ||
| 1367 | if (starget->channel == RAID_CHANNEL) { | ||
| 1368 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | ||
| 1369 | raid_device = _scsih_raid_device_find_by_id(ioc, starget->id, | ||
| 1370 | starget->channel); | ||
| 1371 | if (raid_device) { | ||
| 1372 | sas_target_priv_data->handle = raid_device->handle; | ||
| 1373 | sas_target_priv_data->sas_address = raid_device->wwid; | ||
| 1374 | sas_target_priv_data->flags |= MPT_TARGET_FLAGS_VOLUME; | ||
| 1375 | if (ioc->is_warpdrive) | ||
| 1376 | sas_target_priv_data->raid_device = raid_device; | ||
| 1377 | raid_device->starget = starget; | ||
| 1378 | } | ||
| 1379 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); | ||
| 1380 | return 0; | ||
| 1381 | } | ||
| 1382 | |||
| 1383 | /* sas/sata devices */ | ||
| 1384 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 1385 | rphy = dev_to_rphy(starget->dev.parent); | ||
| 1386 | sas_device = __mpt2sas_get_sdev_by_addr(ioc, | ||
| 1387 | rphy->identify.sas_address); | ||
| 1388 | |||
| 1389 | if (sas_device) { | ||
| 1390 | sas_target_priv_data->handle = sas_device->handle; | ||
| 1391 | sas_target_priv_data->sas_address = sas_device->sas_address; | ||
| 1392 | sas_target_priv_data->sdev = sas_device; | ||
| 1393 | sas_device->starget = starget; | ||
| 1394 | sas_device->id = starget->id; | ||
| 1395 | sas_device->channel = starget->channel; | ||
| 1396 | if (test_bit(sas_device->handle, ioc->pd_handles)) | ||
| 1397 | sas_target_priv_data->flags |= | ||
| 1398 | MPT_TARGET_FLAGS_RAID_COMPONENT; | ||
| 1399 | |||
| 1400 | } | ||
| 1401 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 1402 | |||
| 1403 | return 0; | ||
| 1404 | } | ||
| 1405 | |||
| 1406 | /** | ||
| 1407 | * _scsih_target_destroy - target destroy routine | ||
| 1408 | * @starget: scsi target struct | ||
| 1409 | * | ||
| 1410 | * Returns nothing. | ||
| 1411 | */ | ||
| 1412 | static void | ||
| 1413 | _scsih_target_destroy(struct scsi_target *starget) | ||
| 1414 | { | ||
| 1415 | struct Scsi_Host *shost = dev_to_shost(&starget->dev); | ||
| 1416 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 1417 | struct MPT2SAS_TARGET *sas_target_priv_data; | ||
| 1418 | struct _sas_device *sas_device; | ||
| 1419 | struct _raid_device *raid_device; | ||
| 1420 | unsigned long flags; | ||
| 1421 | struct sas_rphy *rphy; | ||
| 1422 | |||
| 1423 | sas_target_priv_data = starget->hostdata; | ||
| 1424 | if (!sas_target_priv_data) | ||
| 1425 | return; | ||
| 1426 | |||
| 1427 | if (starget->channel == RAID_CHANNEL) { | ||
| 1428 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | ||
| 1429 | raid_device = _scsih_raid_device_find_by_id(ioc, starget->id, | ||
| 1430 | starget->channel); | ||
| 1431 | if (raid_device) { | ||
| 1432 | raid_device->starget = NULL; | ||
| 1433 | raid_device->sdev = NULL; | ||
| 1434 | } | ||
| 1435 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); | ||
| 1436 | goto out; | ||
| 1437 | } | ||
| 1438 | |||
| 1439 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 1440 | rphy = dev_to_rphy(starget->dev.parent); | ||
| 1441 | sas_device = __mpt2sas_get_sdev_from_target(ioc, sas_target_priv_data); | ||
| 1442 | if (sas_device && (sas_device->starget == starget) && | ||
| 1443 | (sas_device->id == starget->id) && | ||
| 1444 | (sas_device->channel == starget->channel)) | ||
| 1445 | sas_device->starget = NULL; | ||
| 1446 | |||
| 1447 | if (sas_device) { | ||
| 1448 | /* | ||
| 1449 | * Corresponding get() is in _scsih_target_alloc() | ||
| 1450 | */ | ||
| 1451 | sas_target_priv_data->sdev = NULL; | ||
| 1452 | sas_device_put(sas_device); | ||
| 1453 | |||
| 1454 | sas_device_put(sas_device); | ||
| 1455 | } | ||
| 1456 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 1457 | |||
| 1458 | out: | ||
| 1459 | kfree(sas_target_priv_data); | ||
| 1460 | starget->hostdata = NULL; | ||
| 1461 | } | ||
| 1462 | |||
| 1463 | /** | ||
| 1464 | * _scsih_slave_alloc - device add routine | ||
| 1465 | * @sdev: scsi device struct | ||
| 1466 | * | ||
| 1467 | * Returns 0 if ok. Any other return is assumed to be an error and | ||
| 1468 | * the device is ignored. | ||
| 1469 | */ | ||
| 1470 | static int | ||
| 1471 | _scsih_slave_alloc(struct scsi_device *sdev) | ||
| 1472 | { | ||
| 1473 | struct Scsi_Host *shost; | ||
| 1474 | struct MPT2SAS_ADAPTER *ioc; | ||
| 1475 | struct MPT2SAS_TARGET *sas_target_priv_data; | ||
| 1476 | struct MPT2SAS_DEVICE *sas_device_priv_data; | ||
| 1477 | struct scsi_target *starget; | ||
| 1478 | struct _raid_device *raid_device; | ||
| 1479 | struct _sas_device *sas_device; | ||
| 1480 | unsigned long flags; | ||
| 1481 | |||
| 1482 | sas_device_priv_data = kzalloc(sizeof(*sas_device_priv_data), | ||
| 1483 | GFP_KERNEL); | ||
| 1484 | if (!sas_device_priv_data) | ||
| 1485 | return -ENOMEM; | ||
| 1486 | |||
| 1487 | sas_device_priv_data->lun = sdev->lun; | ||
| 1488 | sas_device_priv_data->flags = MPT_DEVICE_FLAGS_INIT; | ||
| 1489 | |||
| 1490 | starget = scsi_target(sdev); | ||
| 1491 | sas_target_priv_data = starget->hostdata; | ||
| 1492 | sas_target_priv_data->num_luns++; | ||
| 1493 | sas_device_priv_data->sas_target = sas_target_priv_data; | ||
| 1494 | sdev->hostdata = sas_device_priv_data; | ||
| 1495 | if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT)) | ||
| 1496 | sdev->no_uld_attach = 1; | ||
| 1497 | |||
| 1498 | shost = dev_to_shost(&starget->dev); | ||
| 1499 | ioc = shost_priv(shost); | ||
| 1500 | if (starget->channel == RAID_CHANNEL) { | ||
| 1501 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | ||
| 1502 | raid_device = _scsih_raid_device_find_by_id(ioc, | ||
| 1503 | starget->id, starget->channel); | ||
| 1504 | if (raid_device) | ||
| 1505 | raid_device->sdev = sdev; /* raid is single lun */ | ||
| 1506 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); | ||
| 1507 | } | ||
| 1508 | |||
| 1509 | if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) { | ||
| 1510 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 1511 | sas_device = __mpt2sas_get_sdev_by_addr(ioc, | ||
| 1512 | sas_target_priv_data->sas_address); | ||
| 1513 | if (sas_device && (sas_device->starget == NULL)) { | ||
| 1514 | sdev_printk(KERN_INFO, sdev, | ||
| 1515 | "%s : sas_device->starget set to starget @ %d\n", | ||
| 1516 | __func__, __LINE__); | ||
| 1517 | sas_device->starget = starget; | ||
| 1518 | } | ||
| 1519 | |||
| 1520 | if (sas_device) | ||
| 1521 | sas_device_put(sas_device); | ||
| 1522 | |||
| 1523 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 1524 | } | ||
| 1525 | |||
| 1526 | return 0; | ||
| 1527 | } | ||
| 1528 | |||
| 1529 | /** | ||
| 1530 | * _scsih_slave_destroy - device destroy routine | ||
| 1531 | * @sdev: scsi device struct | ||
| 1532 | * | ||
| 1533 | * Returns nothing. | ||
| 1534 | */ | ||
| 1535 | static void | ||
| 1536 | _scsih_slave_destroy(struct scsi_device *sdev) | ||
| 1537 | { | ||
| 1538 | struct MPT2SAS_TARGET *sas_target_priv_data; | ||
| 1539 | struct scsi_target *starget; | ||
| 1540 | struct Scsi_Host *shost; | ||
| 1541 | struct MPT2SAS_ADAPTER *ioc; | ||
| 1542 | struct _sas_device *sas_device; | ||
| 1543 | unsigned long flags; | ||
| 1544 | |||
| 1545 | if (!sdev->hostdata) | ||
| 1546 | return; | ||
| 1547 | |||
| 1548 | starget = scsi_target(sdev); | ||
| 1549 | sas_target_priv_data = starget->hostdata; | ||
| 1550 | sas_target_priv_data->num_luns--; | ||
| 1551 | |||
| 1552 | shost = dev_to_shost(&starget->dev); | ||
| 1553 | ioc = shost_priv(shost); | ||
| 1554 | |||
| 1555 | if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) { | ||
| 1556 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 1557 | sas_device = __mpt2sas_get_sdev_from_target(ioc, | ||
| 1558 | sas_target_priv_data); | ||
| 1559 | if (sas_device && !sas_target_priv_data->num_luns) | ||
| 1560 | sas_device->starget = NULL; | ||
| 1561 | |||
| 1562 | if (sas_device) | ||
| 1563 | sas_device_put(sas_device); | ||
| 1564 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 1565 | } | ||
| 1566 | |||
| 1567 | kfree(sdev->hostdata); | ||
| 1568 | sdev->hostdata = NULL; | ||
| 1569 | } | ||
| 1570 | |||
| 1571 | /** | ||
| 1572 | * _scsih_display_sata_capabilities - sata capabilities | ||
| 1573 | * @ioc: per adapter object | ||
| 1574 | * @handle: device handle | ||
| 1575 | * @sdev: scsi device struct | ||
| 1576 | */ | ||
| 1577 | static void | ||
| 1578 | _scsih_display_sata_capabilities(struct MPT2SAS_ADAPTER *ioc, | ||
| 1579 | u16 handle, struct scsi_device *sdev) | ||
| 1580 | { | ||
| 1581 | Mpi2ConfigReply_t mpi_reply; | ||
| 1582 | Mpi2SasDevicePage0_t sas_device_pg0; | ||
| 1583 | u32 ioc_status; | ||
| 1584 | u16 flags; | ||
| 1585 | u32 device_info; | ||
| 1586 | |||
| 1587 | if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, | ||
| 1588 | MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { | ||
| 1589 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 1590 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 1591 | return; | ||
| 1592 | } | ||
| 1593 | |||
| 1594 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
| 1595 | MPI2_IOCSTATUS_MASK; | ||
| 1596 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { | ||
| 1597 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 1598 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 1599 | return; | ||
| 1600 | } | ||
| 1601 | |||
| 1602 | flags = le16_to_cpu(sas_device_pg0.Flags); | ||
| 1603 | device_info = le32_to_cpu(sas_device_pg0.DeviceInfo); | ||
| 1604 | |||
| 1605 | sdev_printk(KERN_INFO, sdev, | ||
| 1606 | "atapi(%s), ncq(%s), asyn_notify(%s), smart(%s), fua(%s), " | ||
| 1607 | "sw_preserve(%s)\n", | ||
| 1608 | (device_info & MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE) ? "y" : "n", | ||
| 1609 | (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED) ? "y" : "n", | ||
| 1610 | (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_ASYNCHRONOUS_NOTIFY) ? "y" : | ||
| 1611 | "n", | ||
| 1612 | (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED) ? "y" : "n", | ||
| 1613 | (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED) ? "y" : "n", | ||
| 1614 | (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE) ? "y" : "n"); | ||
| 1615 | } | ||
| 1616 | |||
| 1617 | /** | ||
| 1618 | * _scsih_is_raid - return boolean indicating device is raid volume | ||
| 1619 | * @dev the device struct object | ||
| 1620 | */ | ||
| 1621 | static int | ||
| 1622 | _scsih_is_raid(struct device *dev) | ||
| 1623 | { | ||
| 1624 | struct scsi_device *sdev = to_scsi_device(dev); | ||
| 1625 | struct MPT2SAS_ADAPTER *ioc = shost_priv(sdev->host); | ||
| 1626 | |||
| 1627 | if (ioc->is_warpdrive) | ||
| 1628 | return 0; | ||
| 1629 | return (sdev->channel == RAID_CHANNEL) ? 1 : 0; | ||
| 1630 | } | ||
| 1631 | |||
| 1632 | /** | ||
| 1633 | * _scsih_get_resync - get raid volume resync percent complete | ||
| 1634 | * @dev the device struct object | ||
| 1635 | */ | ||
| 1636 | static void | ||
| 1637 | _scsih_get_resync(struct device *dev) | ||
| 1638 | { | ||
| 1639 | struct scsi_device *sdev = to_scsi_device(dev); | ||
| 1640 | struct MPT2SAS_ADAPTER *ioc = shost_priv(sdev->host); | ||
| 1641 | static struct _raid_device *raid_device; | ||
| 1642 | unsigned long flags; | ||
| 1643 | Mpi2RaidVolPage0_t vol_pg0; | ||
| 1644 | Mpi2ConfigReply_t mpi_reply; | ||
| 1645 | u32 volume_status_flags; | ||
| 1646 | u8 percent_complete; | ||
| 1647 | u16 handle; | ||
| 1648 | |||
| 1649 | percent_complete = 0; | ||
| 1650 | handle = 0; | ||
| 1651 | if (ioc->is_warpdrive) | ||
| 1652 | goto out; | ||
| 1653 | |||
| 1654 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | ||
| 1655 | raid_device = _scsih_raid_device_find_by_id(ioc, sdev->id, | ||
| 1656 | sdev->channel); | ||
| 1657 | if (raid_device) { | ||
| 1658 | handle = raid_device->handle; | ||
| 1659 | percent_complete = raid_device->percent_complete; | ||
| 1660 | } | ||
| 1661 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); | ||
| 1662 | |||
| 1663 | if (!handle) | ||
| 1664 | goto out; | ||
| 1665 | |||
| 1666 | if (mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, &vol_pg0, | ||
| 1667 | MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle, | ||
| 1668 | sizeof(Mpi2RaidVolPage0_t))) { | ||
| 1669 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 1670 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 1671 | percent_complete = 0; | ||
| 1672 | goto out; | ||
| 1673 | } | ||
| 1674 | |||
| 1675 | volume_status_flags = le32_to_cpu(vol_pg0.VolumeStatusFlags); | ||
| 1676 | if (!(volume_status_flags & | ||
| 1677 | MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS)) | ||
| 1678 | percent_complete = 0; | ||
| 1679 | |||
| 1680 | out: | ||
| 1681 | raid_set_resync(mpt2sas_raid_template, dev, percent_complete); | ||
| 1682 | } | ||
| 1683 | |||
| 1684 | /** | ||
| 1685 | * _scsih_get_state - get raid volume level | ||
| 1686 | * @dev the device struct object | ||
| 1687 | */ | ||
| 1688 | static void | ||
| 1689 | _scsih_get_state(struct device *dev) | ||
| 1690 | { | ||
| 1691 | struct scsi_device *sdev = to_scsi_device(dev); | ||
| 1692 | struct MPT2SAS_ADAPTER *ioc = shost_priv(sdev->host); | ||
| 1693 | static struct _raid_device *raid_device; | ||
| 1694 | unsigned long flags; | ||
| 1695 | Mpi2RaidVolPage0_t vol_pg0; | ||
| 1696 | Mpi2ConfigReply_t mpi_reply; | ||
| 1697 | u32 volstate; | ||
| 1698 | enum raid_state state = RAID_STATE_UNKNOWN; | ||
| 1699 | u16 handle = 0; | ||
| 1700 | |||
| 1701 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | ||
| 1702 | raid_device = _scsih_raid_device_find_by_id(ioc, sdev->id, | ||
| 1703 | sdev->channel); | ||
| 1704 | if (raid_device) | ||
| 1705 | handle = raid_device->handle; | ||
| 1706 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); | ||
| 1707 | |||
| 1708 | if (!raid_device) | ||
| 1709 | goto out; | ||
| 1710 | |||
| 1711 | if (mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, &vol_pg0, | ||
| 1712 | MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle, | ||
| 1713 | sizeof(Mpi2RaidVolPage0_t))) { | ||
| 1714 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 1715 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 1716 | goto out; | ||
| 1717 | } | ||
| 1718 | |||
| 1719 | volstate = le32_to_cpu(vol_pg0.VolumeStatusFlags); | ||
| 1720 | if (volstate & MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) { | ||
| 1721 | state = RAID_STATE_RESYNCING; | ||
| 1722 | goto out; | ||
| 1723 | } | ||
| 1724 | |||
| 1725 | switch (vol_pg0.VolumeState) { | ||
| 1726 | case MPI2_RAID_VOL_STATE_OPTIMAL: | ||
| 1727 | case MPI2_RAID_VOL_STATE_ONLINE: | ||
| 1728 | state = RAID_STATE_ACTIVE; | ||
| 1729 | break; | ||
| 1730 | case MPI2_RAID_VOL_STATE_DEGRADED: | ||
| 1731 | state = RAID_STATE_DEGRADED; | ||
| 1732 | break; | ||
| 1733 | case MPI2_RAID_VOL_STATE_FAILED: | ||
| 1734 | case MPI2_RAID_VOL_STATE_MISSING: | ||
| 1735 | state = RAID_STATE_OFFLINE; | ||
| 1736 | break; | ||
| 1737 | } | ||
| 1738 | out: | ||
| 1739 | raid_set_state(mpt2sas_raid_template, dev, state); | ||
| 1740 | } | ||
| 1741 | |||
| 1742 | /** | ||
| 1743 | * _scsih_set_level - set raid level | ||
| 1744 | * @sdev: scsi device struct | ||
| 1745 | * @volume_type: volume type | ||
| 1746 | */ | ||
| 1747 | static void | ||
| 1748 | _scsih_set_level(struct scsi_device *sdev, u8 volume_type) | ||
| 1749 | { | ||
| 1750 | enum raid_level level = RAID_LEVEL_UNKNOWN; | ||
| 1751 | |||
| 1752 | switch (volume_type) { | ||
| 1753 | case MPI2_RAID_VOL_TYPE_RAID0: | ||
| 1754 | level = RAID_LEVEL_0; | ||
| 1755 | break; | ||
| 1756 | case MPI2_RAID_VOL_TYPE_RAID10: | ||
| 1757 | level = RAID_LEVEL_10; | ||
| 1758 | break; | ||
| 1759 | case MPI2_RAID_VOL_TYPE_RAID1E: | ||
| 1760 | level = RAID_LEVEL_1E; | ||
| 1761 | break; | ||
| 1762 | case MPI2_RAID_VOL_TYPE_RAID1: | ||
| 1763 | level = RAID_LEVEL_1; | ||
| 1764 | break; | ||
| 1765 | } | ||
| 1766 | |||
| 1767 | raid_set_level(mpt2sas_raid_template, &sdev->sdev_gendev, level); | ||
| 1768 | } | ||
| 1769 | |||
| 1770 | /** | ||
| 1771 | * _scsih_get_volume_capabilities - volume capabilities | ||
| 1772 | * @ioc: per adapter object | ||
| 1773 | * @sas_device: the raid_device object | ||
| 1774 | * | ||
| 1775 | * Returns 0 for success, else 1 | ||
| 1776 | */ | ||
| 1777 | static int | ||
| 1778 | _scsih_get_volume_capabilities(struct MPT2SAS_ADAPTER *ioc, | ||
| 1779 | struct _raid_device *raid_device) | ||
| 1780 | { | ||
| 1781 | Mpi2RaidVolPage0_t *vol_pg0; | ||
| 1782 | Mpi2RaidPhysDiskPage0_t pd_pg0; | ||
| 1783 | Mpi2SasDevicePage0_t sas_device_pg0; | ||
| 1784 | Mpi2ConfigReply_t mpi_reply; | ||
| 1785 | u16 sz; | ||
| 1786 | u8 num_pds; | ||
| 1787 | |||
| 1788 | if ((mpt2sas_config_get_number_pds(ioc, raid_device->handle, | ||
| 1789 | &num_pds)) || !num_pds) { | ||
| 1790 | dfailprintk(ioc, printk(MPT2SAS_WARN_FMT | ||
| 1791 | "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__, | ||
| 1792 | __func__)); | ||
| 1793 | return 1; | ||
| 1794 | } | ||
| 1795 | |||
| 1796 | raid_device->num_pds = num_pds; | ||
| 1797 | sz = offsetof(Mpi2RaidVolPage0_t, PhysDisk) + (num_pds * | ||
| 1798 | sizeof(Mpi2RaidVol0PhysDisk_t)); | ||
| 1799 | vol_pg0 = kzalloc(sz, GFP_KERNEL); | ||
| 1800 | if (!vol_pg0) { | ||
| 1801 | dfailprintk(ioc, printk(MPT2SAS_WARN_FMT | ||
| 1802 | "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__, | ||
| 1803 | __func__)); | ||
| 1804 | return 1; | ||
| 1805 | } | ||
| 1806 | |||
| 1807 | if ((mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, vol_pg0, | ||
| 1808 | MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle, sz))) { | ||
| 1809 | dfailprintk(ioc, printk(MPT2SAS_WARN_FMT | ||
| 1810 | "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__, | ||
| 1811 | __func__)); | ||
| 1812 | kfree(vol_pg0); | ||
| 1813 | return 1; | ||
| 1814 | } | ||
| 1815 | |||
| 1816 | raid_device->volume_type = vol_pg0->VolumeType; | ||
| 1817 | |||
| 1818 | /* figure out what the underlying devices are by | ||
| 1819 | * obtaining the device_info bits for the 1st device | ||
| 1820 | */ | ||
| 1821 | if (!(mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply, | ||
| 1822 | &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM, | ||
| 1823 | vol_pg0->PhysDisk[0].PhysDiskNum))) { | ||
| 1824 | if (!(mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, | ||
| 1825 | &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, | ||
| 1826 | le16_to_cpu(pd_pg0.DevHandle)))) { | ||
| 1827 | raid_device->device_info = | ||
| 1828 | le32_to_cpu(sas_device_pg0.DeviceInfo); | ||
| 1829 | } | ||
| 1830 | } | ||
| 1831 | |||
| 1832 | kfree(vol_pg0); | ||
| 1833 | return 0; | ||
| 1834 | } | ||
| 1835 | /** | ||
| 1836 | * _scsih_disable_ddio - Disable direct I/O for all the volumes | ||
| 1837 | * @ioc: per adapter object | ||
| 1838 | */ | ||
| 1839 | static void | ||
| 1840 | _scsih_disable_ddio(struct MPT2SAS_ADAPTER *ioc) | ||
| 1841 | { | ||
| 1842 | Mpi2RaidVolPage1_t vol_pg1; | ||
| 1843 | Mpi2ConfigReply_t mpi_reply; | ||
| 1844 | struct _raid_device *raid_device; | ||
| 1845 | u16 handle; | ||
| 1846 | u16 ioc_status; | ||
| 1847 | unsigned long flags; | ||
| 1848 | |||
| 1849 | handle = 0xFFFF; | ||
| 1850 | while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply, | ||
| 1851 | &vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) { | ||
| 1852 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
| 1853 | MPI2_IOCSTATUS_MASK; | ||
| 1854 | if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) | ||
| 1855 | break; | ||
| 1856 | handle = le16_to_cpu(vol_pg1.DevHandle); | ||
| 1857 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | ||
| 1858 | raid_device = _scsih_raid_device_find_by_handle(ioc, handle); | ||
| 1859 | if (raid_device) | ||
| 1860 | raid_device->direct_io_enabled = 0; | ||
| 1861 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); | ||
| 1862 | } | ||
| 1863 | return; | ||
| 1864 | } | ||
| 1865 | |||
| 1866 | |||
| 1867 | /** | ||
| 1868 | * _scsih_get_num_volumes - Get number of volumes in the ioc | ||
| 1869 | * @ioc: per adapter object | ||
| 1870 | */ | ||
| 1871 | static u8 | ||
| 1872 | _scsih_get_num_volumes(struct MPT2SAS_ADAPTER *ioc) | ||
| 1873 | { | ||
| 1874 | Mpi2RaidVolPage1_t vol_pg1; | ||
| 1875 | Mpi2ConfigReply_t mpi_reply; | ||
| 1876 | u16 handle; | ||
| 1877 | u8 vol_cnt = 0; | ||
| 1878 | u16 ioc_status; | ||
| 1879 | |||
| 1880 | handle = 0xFFFF; | ||
| 1881 | while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply, | ||
| 1882 | &vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) { | ||
| 1883 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
| 1884 | MPI2_IOCSTATUS_MASK; | ||
| 1885 | if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) | ||
| 1886 | break; | ||
| 1887 | vol_cnt++; | ||
| 1888 | handle = le16_to_cpu(vol_pg1.DevHandle); | ||
| 1889 | } | ||
| 1890 | return vol_cnt; | ||
| 1891 | } | ||
| 1892 | |||
| 1893 | |||
| 1894 | /** | ||
| 1895 | * _scsih_init_warpdrive_properties - Set properties for warpdrive direct I/O. | ||
| 1896 | * @ioc: per adapter object | ||
| 1897 | * @raid_device: the raid_device object | ||
| 1898 | */ | ||
| 1899 | static void | ||
| 1900 | _scsih_init_warpdrive_properties(struct MPT2SAS_ADAPTER *ioc, | ||
| 1901 | struct _raid_device *raid_device) | ||
| 1902 | { | ||
| 1903 | Mpi2RaidVolPage0_t *vol_pg0; | ||
| 1904 | Mpi2RaidPhysDiskPage0_t pd_pg0; | ||
| 1905 | Mpi2ConfigReply_t mpi_reply; | ||
| 1906 | u16 sz; | ||
| 1907 | u8 num_pds, count; | ||
| 1908 | unsigned long stripe_sz, block_sz; | ||
| 1909 | u8 stripe_exp, block_exp; | ||
| 1910 | u64 dev_max_lba; | ||
| 1911 | |||
| 1912 | if (!ioc->is_warpdrive) | ||
| 1913 | return; | ||
| 1914 | |||
| 1915 | if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_EXPOSE_ALL_DISKS) { | ||
| 1916 | printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled " | ||
| 1917 | "globally as drives are exposed\n", ioc->name); | ||
| 1918 | return; | ||
| 1919 | } | ||
| 1920 | if (_scsih_get_num_volumes(ioc) > 1) { | ||
| 1921 | _scsih_disable_ddio(ioc); | ||
| 1922 | printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled " | ||
| 1923 | "globally as number of drives > 1\n", ioc->name); | ||
| 1924 | return; | ||
| 1925 | } | ||
| 1926 | if ((mpt2sas_config_get_number_pds(ioc, raid_device->handle, | ||
| 1927 | &num_pds)) || !num_pds) { | ||
| 1928 | printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled " | ||
| 1929 | "Failure in computing number of drives\n", ioc->name); | ||
| 1930 | return; | ||
| 1931 | } | ||
| 1932 | |||
| 1933 | sz = offsetof(Mpi2RaidVolPage0_t, PhysDisk) + (num_pds * | ||
| 1934 | sizeof(Mpi2RaidVol0PhysDisk_t)); | ||
| 1935 | vol_pg0 = kzalloc(sz, GFP_KERNEL); | ||
| 1936 | if (!vol_pg0) { | ||
| 1937 | printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled " | ||
| 1938 | "Memory allocation failure for RVPG0\n", ioc->name); | ||
| 1939 | return; | ||
| 1940 | } | ||
| 1941 | |||
| 1942 | if ((mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, vol_pg0, | ||
| 1943 | MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle, sz))) { | ||
| 1944 | printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled " | ||
| 1945 | "Failure in retrieving RVPG0\n", ioc->name); | ||
| 1946 | kfree(vol_pg0); | ||
| 1947 | return; | ||
| 1948 | } | ||
| 1949 | |||
| 1950 | /* | ||
| 1951 | * WARPDRIVE:If number of physical disks in a volume exceeds the max pds | ||
| 1952 | * assumed for WARPDRIVE, disable direct I/O | ||
| 1953 | */ | ||
| 1954 | if (num_pds > MPT_MAX_WARPDRIVE_PDS) { | ||
| 1955 | printk(MPT2SAS_WARN_FMT "WarpDrive : Direct IO is disabled " | ||
| 1956 | "for the drive with handle(0x%04x): num_mem=%d, " | ||
| 1957 | "max_mem_allowed=%d\n", ioc->name, raid_device->handle, | ||
| 1958 | num_pds, MPT_MAX_WARPDRIVE_PDS); | ||
| 1959 | kfree(vol_pg0); | ||
| 1960 | return; | ||
| 1961 | } | ||
| 1962 | for (count = 0; count < num_pds; count++) { | ||
| 1963 | if (mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply, | ||
| 1964 | &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM, | ||
| 1965 | vol_pg0->PhysDisk[count].PhysDiskNum) || | ||
| 1966 | le16_to_cpu(pd_pg0.DevHandle) == | ||
| 1967 | MPT2SAS_INVALID_DEVICE_HANDLE) { | ||
| 1968 | printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is " | ||
| 1969 | "disabled for the drive with handle(0x%04x) member" | ||
| 1970 | "handle retrieval failed for member number=%d\n", | ||
| 1971 | ioc->name, raid_device->handle, | ||
| 1972 | vol_pg0->PhysDisk[count].PhysDiskNum); | ||
| 1973 | goto out_error; | ||
| 1974 | } | ||
| 1975 | /* Disable direct I/O if member drive lba exceeds 4 bytes */ | ||
| 1976 | dev_max_lba = le64_to_cpu(pd_pg0.DeviceMaxLBA); | ||
| 1977 | if (dev_max_lba >> 32) { | ||
| 1978 | printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is " | ||
| 1979 | "disabled for the drive with handle(0x%04x) member" | ||
| 1980 | "handle (0x%04x) unsupported max lba 0x%016llx\n", | ||
| 1981 | ioc->name, raid_device->handle, | ||
| 1982 | le16_to_cpu(pd_pg0.DevHandle), | ||
| 1983 | (unsigned long long)dev_max_lba); | ||
| 1984 | goto out_error; | ||
| 1985 | } | ||
| 1986 | |||
| 1987 | raid_device->pd_handle[count] = le16_to_cpu(pd_pg0.DevHandle); | ||
| 1988 | } | ||
| 1989 | |||
| 1990 | /* | ||
| 1991 | * Assumption for WD: Direct I/O is not supported if the volume is | ||
| 1992 | * not RAID0 | ||
| 1993 | */ | ||
| 1994 | if (raid_device->volume_type != MPI2_RAID_VOL_TYPE_RAID0) { | ||
| 1995 | printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled " | ||
| 1996 | "for the drive with handle(0x%04x): type=%d, " | ||
| 1997 | "s_sz=%uK, blk_size=%u\n", ioc->name, | ||
| 1998 | raid_device->handle, raid_device->volume_type, | ||
| 1999 | (le32_to_cpu(vol_pg0->StripeSize) * | ||
| 2000 | le16_to_cpu(vol_pg0->BlockSize)) / 1024, | ||
| 2001 | le16_to_cpu(vol_pg0->BlockSize)); | ||
| 2002 | goto out_error; | ||
| 2003 | } | ||
| 2004 | |||
| 2005 | stripe_sz = le32_to_cpu(vol_pg0->StripeSize); | ||
| 2006 | stripe_exp = find_first_bit(&stripe_sz, 32); | ||
| 2007 | if (stripe_exp == 32) { | ||
| 2008 | printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled " | ||
| 2009 | "for the drive with handle(0x%04x) invalid stripe sz %uK\n", | ||
| 2010 | ioc->name, raid_device->handle, | ||
| 2011 | (le32_to_cpu(vol_pg0->StripeSize) * | ||
| 2012 | le16_to_cpu(vol_pg0->BlockSize)) / 1024); | ||
| 2013 | goto out_error; | ||
| 2014 | } | ||
| 2015 | raid_device->stripe_exponent = stripe_exp; | ||
| 2016 | block_sz = le16_to_cpu(vol_pg0->BlockSize); | ||
| 2017 | block_exp = find_first_bit(&block_sz, 16); | ||
| 2018 | if (block_exp == 16) { | ||
| 2019 | printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled " | ||
| 2020 | "for the drive with handle(0x%04x) invalid block sz %u\n", | ||
| 2021 | ioc->name, raid_device->handle, | ||
| 2022 | le16_to_cpu(vol_pg0->BlockSize)); | ||
| 2023 | goto out_error; | ||
| 2024 | } | ||
| 2025 | raid_device->block_exponent = block_exp; | ||
| 2026 | raid_device->direct_io_enabled = 1; | ||
| 2027 | |||
| 2028 | printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is Enabled for the drive" | ||
| 2029 | " with handle(0x%04x)\n", ioc->name, raid_device->handle); | ||
| 2030 | /* | ||
| 2031 | * WARPDRIVE: Though the following fields are not used for direct IO, | ||
| 2032 | * stored for future purpose: | ||
| 2033 | */ | ||
| 2034 | raid_device->max_lba = le64_to_cpu(vol_pg0->MaxLBA); | ||
| 2035 | raid_device->stripe_sz = le32_to_cpu(vol_pg0->StripeSize); | ||
| 2036 | raid_device->block_sz = le16_to_cpu(vol_pg0->BlockSize); | ||
| 2037 | |||
| 2038 | |||
| 2039 | kfree(vol_pg0); | ||
| 2040 | return; | ||
| 2041 | |||
| 2042 | out_error: | ||
| 2043 | raid_device->direct_io_enabled = 0; | ||
| 2044 | for (count = 0; count < num_pds; count++) | ||
| 2045 | raid_device->pd_handle[count] = 0; | ||
| 2046 | kfree(vol_pg0); | ||
| 2047 | return; | ||
| 2048 | } | ||
| 2049 | |||
| 2050 | /** | ||
| 2051 | * _scsih_enable_tlr - setting TLR flags | ||
| 2052 | * @ioc: per adapter object | ||
| 2053 | * @sdev: scsi device struct | ||
| 2054 | * | ||
| 2055 | * Enabling Transaction Layer Retries for tape devices when | ||
| 2056 | * vpd page 0x90 is present | ||
| 2057 | * | ||
| 2058 | */ | ||
| 2059 | static void | ||
| 2060 | _scsih_enable_tlr(struct MPT2SAS_ADAPTER *ioc, struct scsi_device *sdev) | ||
| 2061 | { | ||
| 2062 | /* only for TAPE */ | ||
| 2063 | if (sdev->type != TYPE_TAPE) | ||
| 2064 | return; | ||
| 2065 | |||
| 2066 | if (!(ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR)) | ||
| 2067 | return; | ||
| 2068 | |||
| 2069 | sas_enable_tlr(sdev); | ||
| 2070 | sdev_printk(KERN_INFO, sdev, "TLR %s\n", | ||
| 2071 | sas_is_tlr_enabled(sdev) ? "Enabled" : "Disabled"); | ||
| 2072 | return; | ||
| 2073 | |||
| 2074 | } | ||
| 2075 | |||
| 2076 | /** | ||
| 2077 | * _scsih_slave_configure - device configure routine. | ||
| 2078 | * @sdev: scsi device struct | ||
| 2079 | * | ||
| 2080 | * Returns 0 if ok. Any other return is assumed to be an error and | ||
| 2081 | * the device is ignored. | ||
| 2082 | */ | ||
| 2083 | static int | ||
| 2084 | _scsih_slave_configure(struct scsi_device *sdev) | ||
| 2085 | { | ||
| 2086 | struct Scsi_Host *shost = sdev->host; | ||
| 2087 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 2088 | struct MPT2SAS_DEVICE *sas_device_priv_data; | ||
| 2089 | struct MPT2SAS_TARGET *sas_target_priv_data; | ||
| 2090 | struct _sas_device *sas_device; | ||
| 2091 | struct _raid_device *raid_device; | ||
| 2092 | unsigned long flags; | ||
| 2093 | int qdepth; | ||
| 2094 | u8 ssp_target = 0; | ||
| 2095 | char *ds = ""; | ||
| 2096 | char *r_level = ""; | ||
| 2097 | u16 handle, volume_handle = 0; | ||
| 2098 | u64 volume_wwid = 0; | ||
| 2099 | |||
| 2100 | qdepth = 1; | ||
| 2101 | sas_device_priv_data = sdev->hostdata; | ||
| 2102 | sas_device_priv_data->configured_lun = 1; | ||
| 2103 | sas_device_priv_data->flags &= ~MPT_DEVICE_FLAGS_INIT; | ||
| 2104 | sas_target_priv_data = sas_device_priv_data->sas_target; | ||
| 2105 | handle = sas_target_priv_data->handle; | ||
| 2106 | |||
| 2107 | /* raid volume handling */ | ||
| 2108 | if (sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME) { | ||
| 2109 | |||
| 2110 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | ||
| 2111 | raid_device = _scsih_raid_device_find_by_handle(ioc, handle); | ||
| 2112 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); | ||
| 2113 | if (!raid_device) { | ||
| 2114 | dfailprintk(ioc, printk(MPT2SAS_WARN_FMT | ||
| 2115 | "failure at %s:%d/%s()!\n", ioc->name, __FILE__, | ||
| 2116 | __LINE__, __func__)); | ||
| 2117 | return 1; | ||
| 2118 | } | ||
| 2119 | |||
| 2120 | if (_scsih_get_volume_capabilities(ioc, raid_device)) { | ||
| 2121 | dfailprintk(ioc, printk(MPT2SAS_WARN_FMT | ||
| 2122 | "failure at %s:%d/%s()!\n", ioc->name, __FILE__, | ||
| 2123 | __LINE__, __func__)); | ||
| 2124 | return 1; | ||
| 2125 | } | ||
| 2126 | /* | ||
| 2127 | * WARPDRIVE: Initialize the required data for Direct IO | ||
| 2128 | */ | ||
| 2129 | _scsih_init_warpdrive_properties(ioc, raid_device); | ||
| 2130 | |||
| 2131 | /* RAID Queue Depth Support | ||
| 2132 | * IS volume = underlying qdepth of drive type, either | ||
| 2133 | * MPT2SAS_SAS_QUEUE_DEPTH or MPT2SAS_SATA_QUEUE_DEPTH | ||
| 2134 | * IM/IME/R10 = 128 (MPT2SAS_RAID_QUEUE_DEPTH) | ||
| 2135 | */ | ||
| 2136 | if (raid_device->device_info & | ||
| 2137 | MPI2_SAS_DEVICE_INFO_SSP_TARGET) { | ||
| 2138 | qdepth = MPT2SAS_SAS_QUEUE_DEPTH; | ||
| 2139 | ds = "SSP"; | ||
| 2140 | } else { | ||
| 2141 | qdepth = MPT2SAS_SATA_QUEUE_DEPTH; | ||
| 2142 | if (raid_device->device_info & | ||
| 2143 | MPI2_SAS_DEVICE_INFO_SATA_DEVICE) | ||
| 2144 | ds = "SATA"; | ||
| 2145 | else | ||
| 2146 | ds = "STP"; | ||
| 2147 | } | ||
| 2148 | |||
| 2149 | switch (raid_device->volume_type) { | ||
| 2150 | case MPI2_RAID_VOL_TYPE_RAID0: | ||
| 2151 | r_level = "RAID0"; | ||
| 2152 | break; | ||
| 2153 | case MPI2_RAID_VOL_TYPE_RAID1E: | ||
| 2154 | qdepth = MPT2SAS_RAID_QUEUE_DEPTH; | ||
| 2155 | if (ioc->manu_pg10.OEMIdentifier && | ||
| 2156 | (le32_to_cpu(ioc->manu_pg10.GenericFlags0) & | ||
| 2157 | MFG10_GF0_R10_DISPLAY) && | ||
| 2158 | !(raid_device->num_pds % 2)) | ||
| 2159 | r_level = "RAID10"; | ||
| 2160 | else | ||
| 2161 | r_level = "RAID1E"; | ||
| 2162 | break; | ||
| 2163 | case MPI2_RAID_VOL_TYPE_RAID1: | ||
| 2164 | qdepth = MPT2SAS_RAID_QUEUE_DEPTH; | ||
| 2165 | r_level = "RAID1"; | ||
| 2166 | break; | ||
| 2167 | case MPI2_RAID_VOL_TYPE_RAID10: | ||
| 2168 | qdepth = MPT2SAS_RAID_QUEUE_DEPTH; | ||
| 2169 | r_level = "RAID10"; | ||
| 2170 | break; | ||
| 2171 | case MPI2_RAID_VOL_TYPE_UNKNOWN: | ||
| 2172 | default: | ||
| 2173 | qdepth = MPT2SAS_RAID_QUEUE_DEPTH; | ||
| 2174 | r_level = "RAIDX"; | ||
| 2175 | break; | ||
| 2176 | } | ||
| 2177 | |||
| 2178 | if (!ioc->hide_ir_msg) | ||
| 2179 | sdev_printk(KERN_INFO, sdev, "%s: handle(0x%04x), " | ||
| 2180 | "wwid(0x%016llx), pd_count(%d), type(%s)\n", | ||
| 2181 | r_level, raid_device->handle, | ||
| 2182 | (unsigned long long)raid_device->wwid, | ||
| 2183 | raid_device->num_pds, ds); | ||
| 2184 | _scsih_change_queue_depth(sdev, qdepth); | ||
| 2185 | /* raid transport support */ | ||
| 2186 | if (!ioc->is_warpdrive) | ||
| 2187 | _scsih_set_level(sdev, raid_device->volume_type); | ||
| 2188 | return 0; | ||
| 2189 | } | ||
| 2190 | |||
| 2191 | /* non-raid handling */ | ||
| 2192 | if (sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT) { | ||
| 2193 | if (mpt2sas_config_get_volume_handle(ioc, handle, | ||
| 2194 | &volume_handle)) { | ||
| 2195 | dfailprintk(ioc, printk(MPT2SAS_WARN_FMT | ||
| 2196 | "failure at %s:%d/%s()!\n", ioc->name, | ||
| 2197 | __FILE__, __LINE__, __func__)); | ||
| 2198 | return 1; | ||
| 2199 | } | ||
| 2200 | if (volume_handle && mpt2sas_config_get_volume_wwid(ioc, | ||
| 2201 | volume_handle, &volume_wwid)) { | ||
| 2202 | dfailprintk(ioc, printk(MPT2SAS_WARN_FMT | ||
| 2203 | "failure at %s:%d/%s()!\n", ioc->name, | ||
| 2204 | __FILE__, __LINE__, __func__)); | ||
| 2205 | return 1; | ||
| 2206 | } | ||
| 2207 | } | ||
| 2208 | |||
| 2209 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 2210 | sas_device = __mpt2sas_get_sdev_by_addr(ioc, | ||
| 2211 | sas_device_priv_data->sas_target->sas_address); | ||
| 2212 | if (!sas_device) { | ||
| 2213 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 2214 | dfailprintk(ioc, printk(MPT2SAS_WARN_FMT | ||
| 2215 | "failure at %s:%d/%s()!\n", ioc->name, __FILE__, | ||
| 2216 | __LINE__, __func__)); | ||
| 2217 | return 1; | ||
| 2218 | } | ||
| 2219 | sas_device->volume_handle = volume_handle; | ||
| 2220 | sas_device->volume_wwid = volume_wwid; | ||
| 2221 | if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) { | ||
| 2222 | qdepth = MPT2SAS_SAS_QUEUE_DEPTH; | ||
| 2223 | ssp_target = 1; | ||
| 2224 | ds = "SSP"; | ||
| 2225 | } else { | ||
| 2226 | qdepth = MPT2SAS_SATA_QUEUE_DEPTH; | ||
| 2227 | if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET) | ||
| 2228 | ds = "STP"; | ||
| 2229 | else if (sas_device->device_info & | ||
| 2230 | MPI2_SAS_DEVICE_INFO_SATA_DEVICE) | ||
| 2231 | ds = "SATA"; | ||
| 2232 | } | ||
| 2233 | sdev_printk(KERN_INFO, sdev, "%s: handle(0x%04x), " | ||
| 2234 | "sas_addr(0x%016llx), phy(%d), device_name(0x%016llx)\n", | ||
| 2235 | ds, sas_device->handle, | ||
| 2236 | (unsigned long long)sas_device->sas_address, | ||
| 2237 | sas_device->phy, | ||
| 2238 | (unsigned long long)sas_device->device_name); | ||
| 2239 | sdev_printk(KERN_INFO, sdev, "%s: " | ||
| 2240 | "enclosure_logical_id(0x%016llx), slot(%d)\n", ds, | ||
| 2241 | (unsigned long long) sas_device->enclosure_logical_id, | ||
| 2242 | sas_device->slot); | ||
| 2243 | |||
| 2244 | sas_device_put(sas_device); | ||
| 2245 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 2246 | if (!ssp_target) | ||
| 2247 | _scsih_display_sata_capabilities(ioc, handle, sdev); | ||
| 2248 | |||
| 2249 | _scsih_change_queue_depth(sdev, qdepth); | ||
| 2250 | |||
| 2251 | if (ssp_target) { | ||
| 2252 | sas_read_port_mode_page(sdev); | ||
| 2253 | _scsih_enable_tlr(ioc, sdev); | ||
| 2254 | } | ||
| 2255 | |||
| 2256 | return 0; | ||
| 2257 | } | ||
| 2258 | |||
| 2259 | /** | ||
| 2260 | * _scsih_bios_param - fetch head, sector, cylinder info for a disk | ||
| 2261 | * @sdev: scsi device struct | ||
| 2262 | * @bdev: pointer to block device context | ||
| 2263 | * @capacity: device size (in 512 byte sectors) | ||
| 2264 | * @params: three element array to place output: | ||
| 2265 | * params[0] number of heads (max 255) | ||
| 2266 | * params[1] number of sectors (max 63) | ||
| 2267 | * params[2] number of cylinders | ||
| 2268 | * | ||
| 2269 | * Return nothing. | ||
| 2270 | */ | ||
| 2271 | static int | ||
| 2272 | _scsih_bios_param(struct scsi_device *sdev, struct block_device *bdev, | ||
| 2273 | sector_t capacity, int params[]) | ||
| 2274 | { | ||
| 2275 | int heads; | ||
| 2276 | int sectors; | ||
| 2277 | sector_t cylinders; | ||
| 2278 | ulong dummy; | ||
| 2279 | |||
| 2280 | heads = 64; | ||
| 2281 | sectors = 32; | ||
| 2282 | |||
| 2283 | dummy = heads * sectors; | ||
| 2284 | cylinders = capacity; | ||
| 2285 | sector_div(cylinders, dummy); | ||
| 2286 | |||
| 2287 | /* | ||
| 2288 | * Handle extended translation size for logical drives | ||
| 2289 | * > 1Gb | ||
| 2290 | */ | ||
| 2291 | if ((ulong)capacity >= 0x200000) { | ||
| 2292 | heads = 255; | ||
| 2293 | sectors = 63; | ||
| 2294 | dummy = heads * sectors; | ||
| 2295 | cylinders = capacity; | ||
| 2296 | sector_div(cylinders, dummy); | ||
| 2297 | } | ||
| 2298 | |||
| 2299 | /* return result */ | ||
| 2300 | params[0] = heads; | ||
| 2301 | params[1] = sectors; | ||
| 2302 | params[2] = cylinders; | ||
| 2303 | |||
| 2304 | return 0; | ||
| 2305 | } | ||
| 2306 | |||
| 2307 | /** | ||
| 2308 | * _scsih_response_code - translation of device response code | ||
| 2309 | * @ioc: per adapter object | ||
| 2310 | * @response_code: response code returned by the device | ||
| 2311 | * | ||
| 2312 | * Return nothing. | ||
| 2313 | */ | ||
| 2314 | static void | ||
| 2315 | _scsih_response_code(struct MPT2SAS_ADAPTER *ioc, u8 response_code) | ||
| 2316 | { | ||
| 2317 | char *desc; | ||
| 2318 | |||
| 2319 | switch (response_code) { | ||
| 2320 | case MPI2_SCSITASKMGMT_RSP_TM_COMPLETE: | ||
| 2321 | desc = "task management request completed"; | ||
| 2322 | break; | ||
| 2323 | case MPI2_SCSITASKMGMT_RSP_INVALID_FRAME: | ||
| 2324 | desc = "invalid frame"; | ||
| 2325 | break; | ||
| 2326 | case MPI2_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED: | ||
| 2327 | desc = "task management request not supported"; | ||
| 2328 | break; | ||
| 2329 | case MPI2_SCSITASKMGMT_RSP_TM_FAILED: | ||
| 2330 | desc = "task management request failed"; | ||
| 2331 | break; | ||
| 2332 | case MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED: | ||
| 2333 | desc = "task management request succeeded"; | ||
| 2334 | break; | ||
| 2335 | case MPI2_SCSITASKMGMT_RSP_TM_INVALID_LUN: | ||
| 2336 | desc = "invalid lun"; | ||
| 2337 | break; | ||
| 2338 | case 0xA: | ||
| 2339 | desc = "overlapped tag attempted"; | ||
| 2340 | break; | ||
| 2341 | case MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC: | ||
| 2342 | desc = "task queued, however not sent to target"; | ||
| 2343 | break; | ||
| 2344 | default: | ||
| 2345 | desc = "unknown"; | ||
| 2346 | break; | ||
| 2347 | } | ||
| 2348 | printk(MPT2SAS_WARN_FMT "response_code(0x%01x): %s\n", | ||
| 2349 | ioc->name, response_code, desc); | ||
| 2350 | } | ||
| 2351 | |||
| 2352 | /** | ||
| 2353 | * _scsih_tm_done - tm completion routine | ||
| 2354 | * @ioc: per adapter object | ||
| 2355 | * @smid: system request message index | ||
| 2356 | * @msix_index: MSIX table index supplied by the OS | ||
| 2357 | * @reply: reply message frame(lower 32bit addr) | ||
| 2358 | * Context: none. | ||
| 2359 | * | ||
| 2360 | * The callback handler when using scsih_issue_tm. | ||
| 2361 | * | ||
| 2362 | * Return 1 meaning mf should be freed from _base_interrupt | ||
| 2363 | * 0 means the mf is freed from this function. | ||
| 2364 | */ | ||
| 2365 | static u8 | ||
| 2366 | _scsih_tm_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) | ||
| 2367 | { | ||
| 2368 | MPI2DefaultReply_t *mpi_reply; | ||
| 2369 | |||
| 2370 | if (ioc->tm_cmds.status == MPT2_CMD_NOT_USED) | ||
| 2371 | return 1; | ||
| 2372 | if (ioc->tm_cmds.smid != smid) | ||
| 2373 | return 1; | ||
| 2374 | mpt2sas_base_flush_reply_queues(ioc); | ||
| 2375 | ioc->tm_cmds.status |= MPT2_CMD_COMPLETE; | ||
| 2376 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | ||
| 2377 | if (mpi_reply) { | ||
| 2378 | memcpy(ioc->tm_cmds.reply, mpi_reply, mpi_reply->MsgLength*4); | ||
| 2379 | ioc->tm_cmds.status |= MPT2_CMD_REPLY_VALID; | ||
| 2380 | } | ||
| 2381 | ioc->tm_cmds.status &= ~MPT2_CMD_PENDING; | ||
| 2382 | complete(&ioc->tm_cmds.done); | ||
| 2383 | return 1; | ||
| 2384 | } | ||
| 2385 | |||
| 2386 | /** | ||
| 2387 | * mpt2sas_scsih_set_tm_flag - set per target tm_busy | ||
| 2388 | * @ioc: per adapter object | ||
| 2389 | * @handle: device handle | ||
| 2390 | * | ||
| 2391 | * During taskmangement request, we need to freeze the device queue. | ||
| 2392 | */ | ||
| 2393 | void | ||
| 2394 | mpt2sas_scsih_set_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle) | ||
| 2395 | { | ||
| 2396 | struct MPT2SAS_DEVICE *sas_device_priv_data; | ||
| 2397 | struct scsi_device *sdev; | ||
| 2398 | u8 skip = 0; | ||
| 2399 | |||
| 2400 | shost_for_each_device(sdev, ioc->shost) { | ||
| 2401 | if (skip) | ||
| 2402 | continue; | ||
| 2403 | sas_device_priv_data = sdev->hostdata; | ||
| 2404 | if (!sas_device_priv_data) | ||
| 2405 | continue; | ||
| 2406 | if (sas_device_priv_data->sas_target->handle == handle) { | ||
| 2407 | sas_device_priv_data->sas_target->tm_busy = 1; | ||
| 2408 | skip = 1; | ||
| 2409 | ioc->ignore_loginfos = 1; | ||
| 2410 | } | ||
| 2411 | } | ||
| 2412 | } | ||
| 2413 | |||
| 2414 | /** | ||
| 2415 | * mpt2sas_scsih_clear_tm_flag - clear per target tm_busy | ||
| 2416 | * @ioc: per adapter object | ||
| 2417 | * @handle: device handle | ||
| 2418 | * | ||
| 2419 | * During taskmangement request, we need to freeze the device queue. | ||
| 2420 | */ | ||
| 2421 | void | ||
| 2422 | mpt2sas_scsih_clear_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle) | ||
| 2423 | { | ||
| 2424 | struct MPT2SAS_DEVICE *sas_device_priv_data; | ||
| 2425 | struct scsi_device *sdev; | ||
| 2426 | u8 skip = 0; | ||
| 2427 | |||
| 2428 | shost_for_each_device(sdev, ioc->shost) { | ||
| 2429 | if (skip) | ||
| 2430 | continue; | ||
| 2431 | sas_device_priv_data = sdev->hostdata; | ||
| 2432 | if (!sas_device_priv_data) | ||
| 2433 | continue; | ||
| 2434 | if (sas_device_priv_data->sas_target->handle == handle) { | ||
| 2435 | sas_device_priv_data->sas_target->tm_busy = 0; | ||
| 2436 | skip = 1; | ||
| 2437 | ioc->ignore_loginfos = 0; | ||
| 2438 | } | ||
| 2439 | } | ||
| 2440 | } | ||
| 2441 | |||
| 2442 | |||
| 2443 | /** | ||
| 2444 | * mpt2sas_scsih_issue_tm - main routine for sending tm requests | ||
| 2445 | * @ioc: per adapter struct | ||
| 2446 | * @device_handle: device handle | ||
| 2447 | * @channel: the channel assigned by the OS | ||
| 2448 | * @id: the id assigned by the OS | ||
| 2449 | * @lun: lun number | ||
| 2450 | * @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in mpi2_init.h) | ||
| 2451 | * @smid_task: smid assigned to the task | ||
| 2452 | * @timeout: timeout in seconds | ||
| 2453 | * @m_type: TM_MUTEX_ON or TM_MUTEX_OFF | ||
| 2454 | * Context: user | ||
| 2455 | * | ||
| 2456 | * A generic API for sending task management requests to firmware. | ||
| 2457 | * | ||
| 2458 | * The callback index is set inside `ioc->tm_cb_idx`. | ||
| 2459 | * | ||
| 2460 | * Return SUCCESS or FAILED. | ||
| 2461 | */ | ||
| 2462 | int | ||
| 2463 | mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel, | ||
| 2464 | uint id, uint lun, u8 type, u16 smid_task, ulong timeout, | ||
| 2465 | enum mutex_type m_type) | ||
| 2466 | { | ||
| 2467 | Mpi2SCSITaskManagementRequest_t *mpi_request; | ||
| 2468 | Mpi2SCSITaskManagementReply_t *mpi_reply; | ||
| 2469 | u16 smid = 0; | ||
| 2470 | u32 ioc_state; | ||
| 2471 | unsigned long timeleft; | ||
| 2472 | struct scsiio_tracker *scsi_lookup = NULL; | ||
| 2473 | int rc; | ||
| 2474 | |||
| 2475 | if (m_type == TM_MUTEX_ON) | ||
| 2476 | mutex_lock(&ioc->tm_cmds.mutex); | ||
| 2477 | if (ioc->tm_cmds.status != MPT2_CMD_NOT_USED) { | ||
| 2478 | printk(MPT2SAS_INFO_FMT "%s: tm_cmd busy!!!\n", | ||
| 2479 | __func__, ioc->name); | ||
| 2480 | rc = FAILED; | ||
| 2481 | goto err_out; | ||
| 2482 | } | ||
| 2483 | |||
| 2484 | if (ioc->shost_recovery || ioc->remove_host || | ||
| 2485 | ioc->pci_error_recovery) { | ||
| 2486 | printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n", | ||
| 2487 | __func__, ioc->name); | ||
| 2488 | rc = FAILED; | ||
| 2489 | goto err_out; | ||
| 2490 | } | ||
| 2491 | |||
| 2492 | ioc_state = mpt2sas_base_get_iocstate(ioc, 0); | ||
| 2493 | if (ioc_state & MPI2_DOORBELL_USED) { | ||
| 2494 | dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "unexpected doorbell " | ||
| 2495 | "active!\n", ioc->name)); | ||
| 2496 | rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, | ||
| 2497 | FORCE_BIG_HAMMER); | ||
| 2498 | rc = (!rc) ? SUCCESS : FAILED; | ||
| 2499 | goto err_out; | ||
| 2500 | } | ||
| 2501 | |||
| 2502 | if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) { | ||
| 2503 | mpt2sas_base_fault_info(ioc, ioc_state & | ||
| 2504 | MPI2_DOORBELL_DATA_MASK); | ||
| 2505 | rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, | ||
| 2506 | FORCE_BIG_HAMMER); | ||
| 2507 | rc = (!rc) ? SUCCESS : FAILED; | ||
| 2508 | goto err_out; | ||
| 2509 | } | ||
| 2510 | |||
| 2511 | smid = mpt2sas_base_get_smid_hpr(ioc, ioc->tm_cb_idx); | ||
| 2512 | if (!smid) { | ||
| 2513 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", | ||
| 2514 | ioc->name, __func__); | ||
| 2515 | rc = FAILED; | ||
| 2516 | goto err_out; | ||
| 2517 | } | ||
| 2518 | |||
| 2519 | if (type == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK) | ||
| 2520 | scsi_lookup = &ioc->scsi_lookup[smid_task - 1]; | ||
| 2521 | |||
| 2522 | dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "sending tm: handle(0x%04x)," | ||
| 2523 | " task_type(0x%02x), smid(%d)\n", ioc->name, handle, type, | ||
| 2524 | smid_task)); | ||
| 2525 | ioc->tm_cmds.status = MPT2_CMD_PENDING; | ||
| 2526 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); | ||
| 2527 | ioc->tm_cmds.smid = smid; | ||
| 2528 | memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t)); | ||
| 2529 | memset(ioc->tm_cmds.reply, 0, sizeof(Mpi2SCSITaskManagementReply_t)); | ||
| 2530 | mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; | ||
| 2531 | mpi_request->DevHandle = cpu_to_le16(handle); | ||
| 2532 | mpi_request->TaskType = type; | ||
| 2533 | mpi_request->TaskMID = cpu_to_le16(smid_task); | ||
| 2534 | int_to_scsilun(lun, (struct scsi_lun *)mpi_request->LUN); | ||
| 2535 | mpt2sas_scsih_set_tm_flag(ioc, handle); | ||
| 2536 | init_completion(&ioc->tm_cmds.done); | ||
| 2537 | mpt2sas_base_put_smid_hi_priority(ioc, smid); | ||
| 2538 | timeleft = wait_for_completion_timeout(&ioc->tm_cmds.done, timeout*HZ); | ||
| 2539 | if (!(ioc->tm_cmds.status & MPT2_CMD_COMPLETE)) { | ||
| 2540 | printk(MPT2SAS_ERR_FMT "%s: timeout\n", | ||
| 2541 | ioc->name, __func__); | ||
| 2542 | _debug_dump_mf(mpi_request, | ||
| 2543 | sizeof(Mpi2SCSITaskManagementRequest_t)/4); | ||
| 2544 | if (!(ioc->tm_cmds.status & MPT2_CMD_RESET)) { | ||
| 2545 | rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, | ||
| 2546 | FORCE_BIG_HAMMER); | ||
| 2547 | rc = (!rc) ? SUCCESS : FAILED; | ||
| 2548 | ioc->tm_cmds.status = MPT2_CMD_NOT_USED; | ||
| 2549 | mpt2sas_scsih_clear_tm_flag(ioc, handle); | ||
| 2550 | goto err_out; | ||
| 2551 | } | ||
| 2552 | } | ||
| 2553 | |||
| 2554 | if (ioc->tm_cmds.status & MPT2_CMD_REPLY_VALID) { | ||
| 2555 | mpi_reply = ioc->tm_cmds.reply; | ||
| 2556 | dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "complete tm: " | ||
| 2557 | "ioc_status(0x%04x), loginfo(0x%08x), term_count(0x%08x)\n", | ||
| 2558 | ioc->name, le16_to_cpu(mpi_reply->IOCStatus), | ||
| 2559 | le32_to_cpu(mpi_reply->IOCLogInfo), | ||
| 2560 | le32_to_cpu(mpi_reply->TerminationCount))); | ||
| 2561 | if (ioc->logging_level & MPT_DEBUG_TM) { | ||
| 2562 | _scsih_response_code(ioc, mpi_reply->ResponseCode); | ||
| 2563 | if (mpi_reply->IOCStatus) | ||
| 2564 | _debug_dump_mf(mpi_request, | ||
| 2565 | sizeof(Mpi2SCSITaskManagementRequest_t)/4); | ||
| 2566 | } | ||
| 2567 | } | ||
| 2568 | |||
| 2569 | switch (type) { | ||
| 2570 | case MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK: | ||
| 2571 | rc = SUCCESS; | ||
| 2572 | if (scsi_lookup->scmd == NULL) | ||
| 2573 | break; | ||
| 2574 | rc = FAILED; | ||
| 2575 | break; | ||
| 2576 | |||
| 2577 | case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET: | ||
| 2578 | if (_scsih_scsi_lookup_find_by_target(ioc, id, channel)) | ||
| 2579 | rc = FAILED; | ||
| 2580 | else | ||
| 2581 | rc = SUCCESS; | ||
| 2582 | break; | ||
| 2583 | |||
| 2584 | case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET: | ||
| 2585 | case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET: | ||
| 2586 | if (_scsih_scsi_lookup_find_by_lun(ioc, id, lun, channel)) | ||
| 2587 | rc = FAILED; | ||
| 2588 | else | ||
| 2589 | rc = SUCCESS; | ||
| 2590 | break; | ||
| 2591 | case MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK: | ||
| 2592 | rc = SUCCESS; | ||
| 2593 | break; | ||
| 2594 | default: | ||
| 2595 | rc = FAILED; | ||
| 2596 | break; | ||
| 2597 | } | ||
| 2598 | |||
| 2599 | mpt2sas_scsih_clear_tm_flag(ioc, handle); | ||
| 2600 | ioc->tm_cmds.status = MPT2_CMD_NOT_USED; | ||
| 2601 | if (m_type == TM_MUTEX_ON) | ||
| 2602 | mutex_unlock(&ioc->tm_cmds.mutex); | ||
| 2603 | |||
| 2604 | return rc; | ||
| 2605 | |||
| 2606 | err_out: | ||
| 2607 | if (m_type == TM_MUTEX_ON) | ||
| 2608 | mutex_unlock(&ioc->tm_cmds.mutex); | ||
| 2609 | return rc; | ||
| 2610 | } | ||
| 2611 | |||
| 2612 | /** | ||
| 2613 | * _scsih_tm_display_info - displays info about the device | ||
| 2614 | * @ioc: per adapter struct | ||
| 2615 | * @scmd: pointer to scsi command object | ||
| 2616 | * | ||
| 2617 | * Called by task management callback handlers. | ||
| 2618 | */ | ||
| 2619 | static void | ||
| 2620 | _scsih_tm_display_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd) | ||
| 2621 | { | ||
| 2622 | struct scsi_target *starget = scmd->device->sdev_target; | ||
| 2623 | struct MPT2SAS_TARGET *priv_target = starget->hostdata; | ||
| 2624 | struct _sas_device *sas_device = NULL; | ||
| 2625 | unsigned long flags; | ||
| 2626 | char *device_str = NULL; | ||
| 2627 | |||
| 2628 | if (!priv_target) | ||
| 2629 | return; | ||
| 2630 | if (ioc->hide_ir_msg) | ||
| 2631 | device_str = "WarpDrive"; | ||
| 2632 | else | ||
| 2633 | device_str = "volume"; | ||
| 2634 | |||
| 2635 | scsi_print_command(scmd); | ||
| 2636 | if (priv_target->flags & MPT_TARGET_FLAGS_VOLUME) { | ||
| 2637 | starget_printk(KERN_INFO, starget, "%s handle(0x%04x), " | ||
| 2638 | "%s wwid(0x%016llx)\n", device_str, priv_target->handle, | ||
| 2639 | device_str, (unsigned long long)priv_target->sas_address); | ||
| 2640 | } else { | ||
| 2641 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 2642 | sas_device = __mpt2sas_get_sdev_from_target(ioc, priv_target); | ||
| 2643 | if (sas_device) { | ||
| 2644 | if (priv_target->flags & | ||
| 2645 | MPT_TARGET_FLAGS_RAID_COMPONENT) { | ||
| 2646 | starget_printk(KERN_INFO, starget, | ||
| 2647 | "volume handle(0x%04x), " | ||
| 2648 | "volume wwid(0x%016llx)\n", | ||
| 2649 | sas_device->volume_handle, | ||
| 2650 | (unsigned long long)sas_device->volume_wwid); | ||
| 2651 | } | ||
| 2652 | starget_printk(KERN_INFO, starget, | ||
| 2653 | "handle(0x%04x), sas_address(0x%016llx), phy(%d)\n", | ||
| 2654 | sas_device->handle, | ||
| 2655 | (unsigned long long)sas_device->sas_address, | ||
| 2656 | sas_device->phy); | ||
| 2657 | starget_printk(KERN_INFO, starget, | ||
| 2658 | "enclosure_logical_id(0x%016llx), slot(%d)\n", | ||
| 2659 | (unsigned long long)sas_device->enclosure_logical_id, | ||
| 2660 | sas_device->slot); | ||
| 2661 | |||
| 2662 | sas_device_put(sas_device); | ||
| 2663 | } | ||
| 2664 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 2665 | } | ||
| 2666 | } | ||
| 2667 | |||
| 2668 | /** | ||
| 2669 | * _scsih_abort - eh threads main abort routine | ||
| 2670 | * @scmd: pointer to scsi command object | ||
| 2671 | * | ||
| 2672 | * Returns SUCCESS if command aborted else FAILED | ||
| 2673 | */ | ||
| 2674 | static int | ||
| 2675 | _scsih_abort(struct scsi_cmnd *scmd) | ||
| 2676 | { | ||
| 2677 | struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host); | ||
| 2678 | struct MPT2SAS_DEVICE *sas_device_priv_data; | ||
| 2679 | u16 smid; | ||
| 2680 | u16 handle; | ||
| 2681 | int r; | ||
| 2682 | |||
| 2683 | sdev_printk(KERN_INFO, scmd->device, "attempting task abort! " | ||
| 2684 | "scmd(%p)\n", scmd); | ||
| 2685 | _scsih_tm_display_info(ioc, scmd); | ||
| 2686 | |||
| 2687 | sas_device_priv_data = scmd->device->hostdata; | ||
| 2688 | if (!sas_device_priv_data || !sas_device_priv_data->sas_target) { | ||
| 2689 | sdev_printk(KERN_INFO, scmd->device, "device been deleted! " | ||
| 2690 | "scmd(%p)\n", scmd); | ||
| 2691 | scmd->result = DID_NO_CONNECT << 16; | ||
| 2692 | scmd->scsi_done(scmd); | ||
| 2693 | r = SUCCESS; | ||
| 2694 | goto out; | ||
| 2695 | } | ||
| 2696 | |||
| 2697 | /* search for the command */ | ||
| 2698 | smid = _scsih_scsi_lookup_find_by_scmd(ioc, scmd); | ||
| 2699 | if (!smid) { | ||
| 2700 | scmd->result = DID_RESET << 16; | ||
| 2701 | r = SUCCESS; | ||
| 2702 | goto out; | ||
| 2703 | } | ||
| 2704 | |||
| 2705 | /* for hidden raid components and volumes this is not supported */ | ||
| 2706 | if (sas_device_priv_data->sas_target->flags & | ||
| 2707 | MPT_TARGET_FLAGS_RAID_COMPONENT || | ||
| 2708 | sas_device_priv_data->sas_target->flags & MPT_TARGET_FLAGS_VOLUME) { | ||
| 2709 | scmd->result = DID_RESET << 16; | ||
| 2710 | r = FAILED; | ||
| 2711 | goto out; | ||
| 2712 | } | ||
| 2713 | |||
| 2714 | mpt2sas_halt_firmware(ioc); | ||
| 2715 | |||
| 2716 | handle = sas_device_priv_data->sas_target->handle; | ||
| 2717 | r = mpt2sas_scsih_issue_tm(ioc, handle, scmd->device->channel, | ||
| 2718 | scmd->device->id, scmd->device->lun, | ||
| 2719 | MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30, TM_MUTEX_ON); | ||
| 2720 | |||
| 2721 | out: | ||
| 2722 | sdev_printk(KERN_INFO, scmd->device, "task abort: %s scmd(%p)\n", | ||
| 2723 | ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); | ||
| 2724 | return r; | ||
| 2725 | } | ||
| 2726 | |||
| 2727 | /** | ||
| 2728 | * _scsih_dev_reset - eh threads main device reset routine | ||
| 2729 | * @scmd: pointer to scsi command object | ||
| 2730 | * | ||
| 2731 | * Returns SUCCESS if command aborted else FAILED | ||
| 2732 | */ | ||
| 2733 | static int | ||
| 2734 | _scsih_dev_reset(struct scsi_cmnd *scmd) | ||
| 2735 | { | ||
| 2736 | struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host); | ||
| 2737 | struct MPT2SAS_DEVICE *sas_device_priv_data; | ||
| 2738 | struct _sas_device *sas_device = NULL; | ||
| 2739 | u16 handle; | ||
| 2740 | int r; | ||
| 2741 | |||
| 2742 | struct scsi_target *starget = scmd->device->sdev_target; | ||
| 2743 | struct MPT2SAS_TARGET *target_priv_data = starget->hostdata; | ||
| 2744 | |||
| 2745 | starget_printk(KERN_INFO, starget, "attempting device reset! " | ||
| 2746 | "scmd(%p)\n", scmd); | ||
| 2747 | _scsih_tm_display_info(ioc, scmd); | ||
| 2748 | |||
| 2749 | sas_device_priv_data = scmd->device->hostdata; | ||
| 2750 | if (!sas_device_priv_data || !sas_device_priv_data->sas_target) { | ||
| 2751 | starget_printk(KERN_INFO, starget, "device been deleted! " | ||
| 2752 | "scmd(%p)\n", scmd); | ||
| 2753 | scmd->result = DID_NO_CONNECT << 16; | ||
| 2754 | scmd->scsi_done(scmd); | ||
| 2755 | r = SUCCESS; | ||
| 2756 | goto out; | ||
| 2757 | } | ||
| 2758 | |||
| 2759 | /* for hidden raid components obtain the volume_handle */ | ||
| 2760 | handle = 0; | ||
| 2761 | if (sas_device_priv_data->sas_target->flags & | ||
| 2762 | MPT_TARGET_FLAGS_RAID_COMPONENT) { | ||
| 2763 | sas_device = mpt2sas_get_sdev_from_target(ioc, | ||
| 2764 | target_priv_data); | ||
| 2765 | if (sas_device) | ||
| 2766 | handle = sas_device->volume_handle; | ||
| 2767 | } else | ||
| 2768 | handle = sas_device_priv_data->sas_target->handle; | ||
| 2769 | |||
| 2770 | if (!handle) { | ||
| 2771 | scmd->result = DID_RESET << 16; | ||
| 2772 | r = FAILED; | ||
| 2773 | goto out; | ||
| 2774 | } | ||
| 2775 | |||
| 2776 | r = mpt2sas_scsih_issue_tm(ioc, handle, scmd->device->channel, | ||
| 2777 | scmd->device->id, scmd->device->lun, | ||
| 2778 | MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 30, TM_MUTEX_ON); | ||
| 2779 | |||
| 2780 | out: | ||
| 2781 | sdev_printk(KERN_INFO, scmd->device, "device reset: %s scmd(%p)\n", | ||
| 2782 | ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); | ||
| 2783 | |||
| 2784 | if (sas_device) | ||
| 2785 | sas_device_put(sas_device); | ||
| 2786 | |||
| 2787 | return r; | ||
| 2788 | } | ||
| 2789 | |||
| 2790 | /** | ||
| 2791 | * _scsih_target_reset - eh threads main target reset routine | ||
| 2792 | * @scmd: pointer to scsi command object | ||
| 2793 | * | ||
| 2794 | * Returns SUCCESS if command aborted else FAILED | ||
| 2795 | */ | ||
| 2796 | static int | ||
| 2797 | _scsih_target_reset(struct scsi_cmnd *scmd) | ||
| 2798 | { | ||
| 2799 | struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host); | ||
| 2800 | struct MPT2SAS_DEVICE *sas_device_priv_data; | ||
| 2801 | struct _sas_device *sas_device = NULL; | ||
| 2802 | u16 handle; | ||
| 2803 | int r; | ||
| 2804 | struct scsi_target *starget = scmd->device->sdev_target; | ||
| 2805 | struct MPT2SAS_TARGET *target_priv_data = starget->hostdata; | ||
| 2806 | |||
| 2807 | starget_printk(KERN_INFO, starget, "attempting target reset! " | ||
| 2808 | "scmd(%p)\n", scmd); | ||
| 2809 | _scsih_tm_display_info(ioc, scmd); | ||
| 2810 | |||
| 2811 | sas_device_priv_data = scmd->device->hostdata; | ||
| 2812 | if (!sas_device_priv_data || !sas_device_priv_data->sas_target) { | ||
| 2813 | starget_printk(KERN_INFO, starget, "target been deleted! " | ||
| 2814 | "scmd(%p)\n", scmd); | ||
| 2815 | scmd->result = DID_NO_CONNECT << 16; | ||
| 2816 | scmd->scsi_done(scmd); | ||
| 2817 | r = SUCCESS; | ||
| 2818 | goto out; | ||
| 2819 | } | ||
| 2820 | |||
| 2821 | /* for hidden raid components obtain the volume_handle */ | ||
| 2822 | handle = 0; | ||
| 2823 | if (sas_device_priv_data->sas_target->flags & | ||
| 2824 | MPT_TARGET_FLAGS_RAID_COMPONENT) { | ||
| 2825 | sas_device = mpt2sas_get_sdev_from_target(ioc, | ||
| 2826 | target_priv_data); | ||
| 2827 | if (sas_device) | ||
| 2828 | handle = sas_device->volume_handle; | ||
| 2829 | } else | ||
| 2830 | handle = sas_device_priv_data->sas_target->handle; | ||
| 2831 | |||
| 2832 | if (!handle) { | ||
| 2833 | scmd->result = DID_RESET << 16; | ||
| 2834 | r = FAILED; | ||
| 2835 | goto out; | ||
| 2836 | } | ||
| 2837 | |||
| 2838 | r = mpt2sas_scsih_issue_tm(ioc, handle, scmd->device->channel, | ||
| 2839 | scmd->device->id, 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, | ||
| 2840 | 30, TM_MUTEX_ON); | ||
| 2841 | |||
| 2842 | out: | ||
| 2843 | starget_printk(KERN_INFO, starget, "target reset: %s scmd(%p)\n", | ||
| 2844 | ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); | ||
| 2845 | |||
| 2846 | if (sas_device) | ||
| 2847 | sas_device_put(sas_device); | ||
| 2848 | |||
| 2849 | return r; | ||
| 2850 | } | ||
| 2851 | |||
| 2852 | /** | ||
| 2853 | * _scsih_host_reset - eh threads main host reset routine | ||
| 2854 | * @scmd: pointer to scsi command object | ||
| 2855 | * | ||
| 2856 | * Returns SUCCESS if command aborted else FAILED | ||
| 2857 | */ | ||
| 2858 | static int | ||
| 2859 | _scsih_host_reset(struct scsi_cmnd *scmd) | ||
| 2860 | { | ||
| 2861 | struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host); | ||
| 2862 | int r, retval; | ||
| 2863 | |||
| 2864 | printk(MPT2SAS_INFO_FMT "attempting host reset! scmd(%p)\n", | ||
| 2865 | ioc->name, scmd); | ||
| 2866 | scsi_print_command(scmd); | ||
| 2867 | |||
| 2868 | if (ioc->is_driver_loading) { | ||
| 2869 | printk(MPT2SAS_INFO_FMT "Blocking the host reset\n", | ||
| 2870 | ioc->name); | ||
| 2871 | r = FAILED; | ||
| 2872 | goto out; | ||
| 2873 | } | ||
| 2874 | |||
| 2875 | retval = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, | ||
| 2876 | FORCE_BIG_HAMMER); | ||
| 2877 | r = (retval < 0) ? FAILED : SUCCESS; | ||
| 2878 | |||
| 2879 | out: | ||
| 2880 | printk(MPT2SAS_INFO_FMT "host reset: %s scmd(%p)\n", | ||
| 2881 | ioc->name, ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); | ||
| 2882 | |||
| 2883 | return r; | ||
| 2884 | } | ||
| 2885 | |||
| 2886 | /** | ||
| 2887 | * _scsih_fw_event_add - insert and queue up fw_event | ||
| 2888 | * @ioc: per adapter object | ||
| 2889 | * @fw_event: object describing the event | ||
| 2890 | * Context: This function will acquire ioc->fw_event_lock. | ||
| 2891 | * | ||
| 2892 | * This adds the firmware event object into link list, then queues it up to | ||
| 2893 | * be processed from user context. | ||
| 2894 | * | ||
| 2895 | * Return nothing. | ||
| 2896 | */ | ||
| 2897 | static void | ||
| 2898 | _scsih_fw_event_add(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work *fw_event) | ||
| 2899 | { | ||
| 2900 | unsigned long flags; | ||
| 2901 | |||
| 2902 | if (ioc->firmware_event_thread == NULL) | ||
| 2903 | return; | ||
| 2904 | |||
| 2905 | spin_lock_irqsave(&ioc->fw_event_lock, flags); | ||
| 2906 | fw_event_work_get(fw_event); | ||
| 2907 | list_add_tail(&fw_event->list, &ioc->fw_event_list); | ||
| 2908 | INIT_DELAYED_WORK(&fw_event->delayed_work, _firmware_event_work); | ||
| 2909 | fw_event_work_get(fw_event); | ||
| 2910 | queue_delayed_work(ioc->firmware_event_thread, | ||
| 2911 | &fw_event->delayed_work, 0); | ||
| 2912 | spin_unlock_irqrestore(&ioc->fw_event_lock, flags); | ||
| 2913 | } | ||
| 2914 | |||
| 2915 | /** | ||
| 2916 | * _scsih_fw_event_del_from_list - delete fw_event from the list | ||
| 2917 | * @ioc: per adapter object | ||
| 2918 | * @fw_event: object describing the event | ||
| 2919 | * Context: This function will acquire ioc->fw_event_lock. | ||
| 2920 | * | ||
| 2921 | * If the fw_event is on the fw_event_list, remove it and do a put. | ||
| 2922 | * | ||
| 2923 | * Return nothing. | ||
| 2924 | */ | ||
| 2925 | static void | ||
| 2926 | _scsih_fw_event_del_from_list(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work | ||
| 2927 | *fw_event) | ||
| 2928 | { | ||
| 2929 | unsigned long flags; | ||
| 2930 | |||
| 2931 | spin_lock_irqsave(&ioc->fw_event_lock, flags); | ||
| 2932 | if (!list_empty(&fw_event->list)) { | ||
| 2933 | list_del_init(&fw_event->list); | ||
| 2934 | fw_event_work_put(fw_event); | ||
| 2935 | } | ||
| 2936 | spin_unlock_irqrestore(&ioc->fw_event_lock, flags); | ||
| 2937 | } | ||
| 2938 | |||
| 2939 | /** | ||
| 2940 | * _scsih_error_recovery_delete_devices - remove devices not responding | ||
| 2941 | * @ioc: per adapter object | ||
| 2942 | * | ||
| 2943 | * Return nothing. | ||
| 2944 | */ | ||
| 2945 | static void | ||
| 2946 | _scsih_error_recovery_delete_devices(struct MPT2SAS_ADAPTER *ioc) | ||
| 2947 | { | ||
| 2948 | struct fw_event_work *fw_event; | ||
| 2949 | |||
| 2950 | if (ioc->is_driver_loading) | ||
| 2951 | return; | ||
| 2952 | |||
| 2953 | fw_event = alloc_fw_event_work(0); | ||
| 2954 | if (!fw_event) | ||
| 2955 | return; | ||
| 2956 | |||
| 2957 | fw_event->event = MPT2SAS_REMOVE_UNRESPONDING_DEVICES; | ||
| 2958 | fw_event->ioc = ioc; | ||
| 2959 | _scsih_fw_event_add(ioc, fw_event); | ||
| 2960 | fw_event_work_put(fw_event); | ||
| 2961 | } | ||
| 2962 | |||
| 2963 | /** | ||
| 2964 | * mpt2sas_port_enable_complete - port enable completed (fake event) | ||
| 2965 | * @ioc: per adapter object | ||
| 2966 | * | ||
| 2967 | * Return nothing. | ||
| 2968 | */ | ||
| 2969 | void | ||
| 2970 | mpt2sas_port_enable_complete(struct MPT2SAS_ADAPTER *ioc) | ||
| 2971 | { | ||
| 2972 | struct fw_event_work *fw_event; | ||
| 2973 | |||
| 2974 | fw_event = alloc_fw_event_work(0); | ||
| 2975 | if (!fw_event) | ||
| 2976 | return; | ||
| 2977 | fw_event->event = MPT2SAS_PORT_ENABLE_COMPLETE; | ||
| 2978 | fw_event->ioc = ioc; | ||
| 2979 | _scsih_fw_event_add(ioc, fw_event); | ||
| 2980 | fw_event_work_put(fw_event); | ||
| 2981 | } | ||
| 2982 | |||
| 2983 | static struct fw_event_work *dequeue_next_fw_event(struct MPT2SAS_ADAPTER *ioc) | ||
| 2984 | { | ||
| 2985 | unsigned long flags; | ||
| 2986 | struct fw_event_work *fw_event = NULL; | ||
| 2987 | |||
| 2988 | spin_lock_irqsave(&ioc->fw_event_lock, flags); | ||
| 2989 | if (!list_empty(&ioc->fw_event_list)) { | ||
| 2990 | fw_event = list_first_entry(&ioc->fw_event_list, | ||
| 2991 | struct fw_event_work, list); | ||
| 2992 | list_del_init(&fw_event->list); | ||
| 2993 | } | ||
| 2994 | spin_unlock_irqrestore(&ioc->fw_event_lock, flags); | ||
| 2995 | |||
| 2996 | return fw_event; | ||
| 2997 | } | ||
| 2998 | |||
| 2999 | /** | ||
| 3000 | * _scsih_fw_event_cleanup_queue - cleanup event queue | ||
| 3001 | * @ioc: per adapter object | ||
| 3002 | * | ||
| 3003 | * Walk the firmware event queue, either killing timers, or waiting | ||
| 3004 | * for outstanding events to complete | ||
| 3005 | * | ||
| 3006 | * Return nothing. | ||
| 3007 | */ | ||
| 3008 | static void | ||
| 3009 | _scsih_fw_event_cleanup_queue(struct MPT2SAS_ADAPTER *ioc) | ||
| 3010 | { | ||
| 3011 | struct fw_event_work *fw_event; | ||
| 3012 | |||
| 3013 | if (list_empty(&ioc->fw_event_list) || | ||
| 3014 | !ioc->firmware_event_thread || in_interrupt()) | ||
| 3015 | return; | ||
| 3016 | |||
| 3017 | while ((fw_event = dequeue_next_fw_event(ioc))) { | ||
| 3018 | /* | ||
| 3019 | * Wait on the fw_event to complete. If this returns 1, then | ||
| 3020 | * the event was never executed, and we need a put for the | ||
| 3021 | * reference the delayed_work had on the fw_event. | ||
| 3022 | * | ||
| 3023 | * If it did execute, we wait for it to finish, and the put will | ||
| 3024 | * happen from _firmware_event_work() | ||
| 3025 | */ | ||
| 3026 | if (cancel_delayed_work_sync(&fw_event->delayed_work)) | ||
| 3027 | fw_event_work_put(fw_event); | ||
| 3028 | |||
| 3029 | fw_event_work_put(fw_event); | ||
| 3030 | } | ||
| 3031 | } | ||
| 3032 | |||
| 3033 | /** | ||
| 3034 | * _scsih_ublock_io_all_device - unblock every device | ||
| 3035 | * @ioc: per adapter object | ||
| 3036 | * | ||
| 3037 | * change the device state from block to running | ||
| 3038 | */ | ||
| 3039 | static void | ||
| 3040 | _scsih_ublock_io_all_device(struct MPT2SAS_ADAPTER *ioc) | ||
| 3041 | { | ||
| 3042 | struct MPT2SAS_DEVICE *sas_device_priv_data; | ||
| 3043 | struct scsi_device *sdev; | ||
| 3044 | |||
| 3045 | shost_for_each_device(sdev, ioc->shost) { | ||
| 3046 | sas_device_priv_data = sdev->hostdata; | ||
| 3047 | if (!sas_device_priv_data) | ||
| 3048 | continue; | ||
| 3049 | if (!sas_device_priv_data->block) | ||
| 3050 | continue; | ||
| 3051 | sas_device_priv_data->block = 0; | ||
| 3052 | dewtprintk(ioc, sdev_printk(KERN_INFO, sdev, "device_running, " | ||
| 3053 | "handle(0x%04x)\n", | ||
| 3054 | sas_device_priv_data->sas_target->handle)); | ||
| 3055 | scsi_internal_device_unblock(sdev, SDEV_RUNNING); | ||
| 3056 | } | ||
| 3057 | } | ||
| 3058 | /** | ||
| 3059 | * _scsih_ublock_io_device - set the device state to SDEV_RUNNING | ||
| 3060 | * @ioc: per adapter object | ||
| 3061 | * @handle: device handle | ||
| 3062 | * | ||
| 3063 | * During device pull we need to appropiately set the sdev state. | ||
| 3064 | */ | ||
| 3065 | static void | ||
| 3066 | _scsih_ublock_io_device(struct MPT2SAS_ADAPTER *ioc, u64 sas_address) | ||
| 3067 | { | ||
| 3068 | struct MPT2SAS_DEVICE *sas_device_priv_data; | ||
| 3069 | struct scsi_device *sdev; | ||
| 3070 | |||
| 3071 | shost_for_each_device(sdev, ioc->shost) { | ||
| 3072 | sas_device_priv_data = sdev->hostdata; | ||
| 3073 | if (!sas_device_priv_data) | ||
| 3074 | continue; | ||
| 3075 | if (!sas_device_priv_data->block) | ||
| 3076 | continue; | ||
| 3077 | if (sas_device_priv_data->sas_target->sas_address == | ||
| 3078 | sas_address) { | ||
| 3079 | dewtprintk(ioc, sdev_printk(KERN_INFO, sdev, | ||
| 3080 | MPT2SAS_INFO_FMT "SDEV_RUNNING: " | ||
| 3081 | "sas address(0x%016llx)\n", ioc->name, | ||
| 3082 | (unsigned long long)sas_address)); | ||
| 3083 | sas_device_priv_data->block = 0; | ||
| 3084 | scsi_internal_device_unblock(sdev, SDEV_RUNNING); | ||
| 3085 | } | ||
| 3086 | } | ||
| 3087 | } | ||
| 3088 | |||
| 3089 | /** | ||
| 3090 | * _scsih_block_io_all_device - set the device state to SDEV_BLOCK | ||
| 3091 | * @ioc: per adapter object | ||
| 3092 | * @handle: device handle | ||
| 3093 | * | ||
| 3094 | * During device pull we need to appropiately set the sdev state. | ||
| 3095 | */ | ||
| 3096 | static void | ||
| 3097 | _scsih_block_io_all_device(struct MPT2SAS_ADAPTER *ioc) | ||
| 3098 | { | ||
| 3099 | struct MPT2SAS_DEVICE *sas_device_priv_data; | ||
| 3100 | struct scsi_device *sdev; | ||
| 3101 | |||
| 3102 | shost_for_each_device(sdev, ioc->shost) { | ||
| 3103 | sas_device_priv_data = sdev->hostdata; | ||
| 3104 | if (!sas_device_priv_data) | ||
| 3105 | continue; | ||
| 3106 | if (sas_device_priv_data->block) | ||
| 3107 | continue; | ||
| 3108 | sas_device_priv_data->block = 1; | ||
| 3109 | dewtprintk(ioc, sdev_printk(KERN_INFO, sdev, "device_blocked, " | ||
| 3110 | "handle(0x%04x)\n", | ||
| 3111 | sas_device_priv_data->sas_target->handle)); | ||
| 3112 | scsi_internal_device_block(sdev); | ||
| 3113 | } | ||
| 3114 | } | ||
| 3115 | |||
| 3116 | |||
| 3117 | /** | ||
| 3118 | * _scsih_block_io_device - set the device state to SDEV_BLOCK | ||
| 3119 | * @ioc: per adapter object | ||
| 3120 | * @handle: device handle | ||
| 3121 | * | ||
| 3122 | * During device pull we need to appropiately set the sdev state. | ||
| 3123 | */ | ||
| 3124 | static void | ||
| 3125 | _scsih_block_io_device(struct MPT2SAS_ADAPTER *ioc, u16 handle) | ||
| 3126 | { | ||
| 3127 | struct MPT2SAS_DEVICE *sas_device_priv_data; | ||
| 3128 | struct scsi_device *sdev; | ||
| 3129 | |||
| 3130 | shost_for_each_device(sdev, ioc->shost) { | ||
| 3131 | sas_device_priv_data = sdev->hostdata; | ||
| 3132 | if (!sas_device_priv_data) | ||
| 3133 | continue; | ||
| 3134 | if (sas_device_priv_data->block) | ||
| 3135 | continue; | ||
| 3136 | if (sas_device_priv_data->sas_target->handle == handle) { | ||
| 3137 | dewtprintk(ioc, sdev_printk(KERN_INFO, sdev, | ||
| 3138 | MPT2SAS_INFO_FMT "SDEV_BLOCK: " | ||
| 3139 | "handle(0x%04x)\n", ioc->name, handle)); | ||
| 3140 | sas_device_priv_data->block = 1; | ||
| 3141 | scsi_internal_device_block(sdev); | ||
| 3142 | } | ||
| 3143 | } | ||
| 3144 | } | ||
| 3145 | |||
| 3146 | /** | ||
| 3147 | * _scsih_block_io_to_children_attached_to_ex | ||
| 3148 | * @ioc: per adapter object | ||
| 3149 | * @sas_expander: the sas_device object | ||
| 3150 | * | ||
| 3151 | * This routine set sdev state to SDEV_BLOCK for all devices | ||
| 3152 | * attached to this expander. This function called when expander is | ||
| 3153 | * pulled. | ||
| 3154 | */ | ||
| 3155 | static void | ||
| 3156 | _scsih_block_io_to_children_attached_to_ex(struct MPT2SAS_ADAPTER *ioc, | ||
| 3157 | struct _sas_node *sas_expander) | ||
| 3158 | { | ||
| 3159 | struct _sas_port *mpt2sas_port; | ||
| 3160 | struct _sas_device *sas_device; | ||
| 3161 | struct _sas_node *expander_sibling; | ||
| 3162 | unsigned long flags; | ||
| 3163 | |||
| 3164 | if (!sas_expander) | ||
| 3165 | return; | ||
| 3166 | |||
| 3167 | list_for_each_entry(mpt2sas_port, | ||
| 3168 | &sas_expander->sas_port_list, port_list) { | ||
| 3169 | if (mpt2sas_port->remote_identify.device_type == SAS_END_DEVICE) { | ||
| 3170 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 3171 | sas_device = __mpt2sas_get_sdev_by_addr(ioc, | ||
| 3172 | mpt2sas_port->remote_identify.sas_address); | ||
| 3173 | if (sas_device) { | ||
| 3174 | set_bit(sas_device->handle, | ||
| 3175 | ioc->blocking_handles); | ||
| 3176 | sas_device_put(sas_device); | ||
| 3177 | } | ||
| 3178 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 3179 | } | ||
| 3180 | } | ||
| 3181 | |||
| 3182 | list_for_each_entry(mpt2sas_port, | ||
| 3183 | &sas_expander->sas_port_list, port_list) { | ||
| 3184 | |||
| 3185 | if (mpt2sas_port->remote_identify.device_type == | ||
| 3186 | SAS_EDGE_EXPANDER_DEVICE || | ||
| 3187 | mpt2sas_port->remote_identify.device_type == | ||
| 3188 | SAS_FANOUT_EXPANDER_DEVICE) { | ||
| 3189 | expander_sibling = | ||
| 3190 | mpt2sas_scsih_expander_find_by_sas_address( | ||
| 3191 | ioc, mpt2sas_port->remote_identify.sas_address); | ||
| 3192 | _scsih_block_io_to_children_attached_to_ex(ioc, | ||
| 3193 | expander_sibling); | ||
| 3194 | } | ||
| 3195 | } | ||
| 3196 | } | ||
| 3197 | |||
| 3198 | /** | ||
| 3199 | * _scsih_block_io_to_children_attached_directly | ||
| 3200 | * @ioc: per adapter object | ||
| 3201 | * @event_data: topology change event data | ||
| 3202 | * | ||
| 3203 | * This routine set sdev state to SDEV_BLOCK for all devices | ||
| 3204 | * direct attached during device pull. | ||
| 3205 | */ | ||
| 3206 | static void | ||
| 3207 | _scsih_block_io_to_children_attached_directly(struct MPT2SAS_ADAPTER *ioc, | ||
| 3208 | Mpi2EventDataSasTopologyChangeList_t *event_data) | ||
| 3209 | { | ||
| 3210 | int i; | ||
| 3211 | u16 handle; | ||
| 3212 | u16 reason_code; | ||
| 3213 | u8 phy_number; | ||
| 3214 | |||
| 3215 | for (i = 0; i < event_data->NumEntries; i++) { | ||
| 3216 | handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle); | ||
| 3217 | if (!handle) | ||
| 3218 | continue; | ||
| 3219 | phy_number = event_data->StartPhyNum + i; | ||
| 3220 | reason_code = event_data->PHY[i].PhyStatus & | ||
| 3221 | MPI2_EVENT_SAS_TOPO_RC_MASK; | ||
| 3222 | if (reason_code == MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING) | ||
| 3223 | _scsih_block_io_device(ioc, handle); | ||
| 3224 | } | ||
| 3225 | } | ||
| 3226 | |||
| 3227 | /** | ||
| 3228 | * _scsih_tm_tr_send - send task management request | ||
| 3229 | * @ioc: per adapter object | ||
| 3230 | * @handle: device handle | ||
| 3231 | * Context: interrupt time. | ||
| 3232 | * | ||
| 3233 | * This code is to initiate the device removal handshake protocol | ||
| 3234 | * with controller firmware. This function will issue target reset | ||
| 3235 | * using high priority request queue. It will send a sas iounit | ||
| 3236 | * control request (MPI2_SAS_OP_REMOVE_DEVICE) from this completion. | ||
| 3237 | * | ||
| 3238 | * This is designed to send muliple task management request at the same | ||
| 3239 | * time to the fifo. If the fifo is full, we will append the request, | ||
| 3240 | * and process it in a future completion. | ||
| 3241 | */ | ||
| 3242 | static void | ||
| 3243 | _scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle) | ||
| 3244 | { | ||
| 3245 | Mpi2SCSITaskManagementRequest_t *mpi_request; | ||
| 3246 | u16 smid; | ||
| 3247 | struct _sas_device *sas_device = NULL; | ||
| 3248 | struct MPT2SAS_TARGET *sas_target_priv_data = NULL; | ||
| 3249 | u64 sas_address = 0; | ||
| 3250 | unsigned long flags; | ||
| 3251 | struct _tr_list *delayed_tr; | ||
| 3252 | u32 ioc_state; | ||
| 3253 | |||
| 3254 | if (ioc->remove_host) { | ||
| 3255 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host has been " | ||
| 3256 | "removed: handle(0x%04x)\n", __func__, ioc->name, handle)); | ||
| 3257 | return; | ||
| 3258 | } else if (ioc->pci_error_recovery) { | ||
| 3259 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host in pci " | ||
| 3260 | "error recovery: handle(0x%04x)\n", __func__, ioc->name, | ||
| 3261 | handle)); | ||
| 3262 | return; | ||
| 3263 | } | ||
| 3264 | ioc_state = mpt2sas_base_get_iocstate(ioc, 1); | ||
| 3265 | if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { | ||
| 3266 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host is not " | ||
| 3267 | "operational: handle(0x%04x)\n", __func__, ioc->name, | ||
| 3268 | handle)); | ||
| 3269 | return; | ||
| 3270 | } | ||
| 3271 | |||
| 3272 | /* if PD, then return */ | ||
| 3273 | if (test_bit(handle, ioc->pd_handles)) | ||
| 3274 | return; | ||
| 3275 | |||
| 3276 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 3277 | sas_device = __mpt2sas_get_sdev_by_handle(ioc, handle); | ||
| 3278 | if (sas_device && sas_device->starget && | ||
| 3279 | sas_device->starget->hostdata) { | ||
| 3280 | sas_target_priv_data = sas_device->starget->hostdata; | ||
| 3281 | sas_target_priv_data->deleted = 1; | ||
| 3282 | sas_address = sas_device->sas_address; | ||
| 3283 | } | ||
| 3284 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 3285 | |||
| 3286 | if (sas_target_priv_data) { | ||
| 3287 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "setting delete flag: " | ||
| 3288 | "handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name, handle, | ||
| 3289 | (unsigned long long)sas_address)); | ||
| 3290 | _scsih_ublock_io_device(ioc, sas_address); | ||
| 3291 | sas_target_priv_data->handle = MPT2SAS_INVALID_DEVICE_HANDLE; | ||
| 3292 | } | ||
| 3293 | |||
| 3294 | smid = mpt2sas_base_get_smid_hpr(ioc, ioc->tm_tr_cb_idx); | ||
| 3295 | if (!smid) { | ||
| 3296 | delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC); | ||
| 3297 | if (!delayed_tr) | ||
| 3298 | goto out; | ||
| 3299 | INIT_LIST_HEAD(&delayed_tr->list); | ||
| 3300 | delayed_tr->handle = handle; | ||
| 3301 | list_add_tail(&delayed_tr->list, &ioc->delayed_tr_list); | ||
| 3302 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 3303 | "DELAYED:tr:handle(0x%04x), (open)\n", | ||
| 3304 | ioc->name, handle)); | ||
| 3305 | goto out; | ||
| 3306 | } | ||
| 3307 | |||
| 3308 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "tr_send:handle(0x%04x), " | ||
| 3309 | "(open), smid(%d), cb(%d)\n", ioc->name, handle, smid, | ||
| 3310 | ioc->tm_tr_cb_idx)); | ||
| 3311 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); | ||
| 3312 | memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t)); | ||
| 3313 | mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; | ||
| 3314 | mpi_request->DevHandle = cpu_to_le16(handle); | ||
| 3315 | mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; | ||
| 3316 | mpt2sas_base_put_smid_hi_priority(ioc, smid); | ||
| 3317 | out: | ||
| 3318 | if (sas_device) | ||
| 3319 | sas_device_put(sas_device); | ||
| 3320 | } | ||
| 3321 | |||
| 3322 | |||
| 3323 | |||
| 3324 | /** | ||
| 3325 | * _scsih_sas_control_complete - completion routine | ||
| 3326 | * @ioc: per adapter object | ||
| 3327 | * @smid: system request message index | ||
| 3328 | * @msix_index: MSIX table index supplied by the OS | ||
| 3329 | * @reply: reply message frame(lower 32bit addr) | ||
| 3330 | * Context: interrupt time. | ||
| 3331 | * | ||
| 3332 | * This is the sas iounit control completion routine. | ||
| 3333 | * This code is part of the code to initiate the device removal | ||
| 3334 | * handshake protocol with controller firmware. | ||
| 3335 | * | ||
| 3336 | * Return 1 meaning mf should be freed from _base_interrupt | ||
| 3337 | * 0 means the mf is freed from this function. | ||
| 3338 | */ | ||
| 3339 | static u8 | ||
| 3340 | _scsih_sas_control_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, | ||
| 3341 | u8 msix_index, u32 reply) | ||
| 3342 | { | ||
| 3343 | Mpi2SasIoUnitControlReply_t *mpi_reply = | ||
| 3344 | mpt2sas_base_get_reply_virt_addr(ioc, reply); | ||
| 3345 | if (likely(mpi_reply)) { | ||
| 3346 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 3347 | "sc_complete:handle(0x%04x), (open) " | ||
| 3348 | "smid(%d), ioc_status(0x%04x), loginfo(0x%08x)\n", | ||
| 3349 | ioc->name, le16_to_cpu(mpi_reply->DevHandle), smid, | ||
| 3350 | le16_to_cpu(mpi_reply->IOCStatus), | ||
| 3351 | le32_to_cpu(mpi_reply->IOCLogInfo))); | ||
| 3352 | } else { | ||
| 3353 | printk(MPT2SAS_ERR_FMT "mpi_reply not valid at %s:%d/%s()!\n", | ||
| 3354 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 3355 | } | ||
| 3356 | return 1; | ||
| 3357 | } | ||
| 3358 | |||
| 3359 | /** | ||
| 3360 | * _scsih_tm_tr_volume_send - send target reset request for volumes | ||
| 3361 | * @ioc: per adapter object | ||
| 3362 | * @handle: device handle | ||
| 3363 | * Context: interrupt time. | ||
| 3364 | * | ||
| 3365 | * This is designed to send muliple task management request at the same | ||
| 3366 | * time to the fifo. If the fifo is full, we will append the request, | ||
| 3367 | * and process it in a future completion. | ||
| 3368 | */ | ||
| 3369 | static void | ||
| 3370 | _scsih_tm_tr_volume_send(struct MPT2SAS_ADAPTER *ioc, u16 handle) | ||
| 3371 | { | ||
| 3372 | Mpi2SCSITaskManagementRequest_t *mpi_request; | ||
| 3373 | u16 smid; | ||
| 3374 | struct _tr_list *delayed_tr; | ||
| 3375 | |||
| 3376 | if (ioc->shost_recovery || ioc->remove_host || | ||
| 3377 | ioc->pci_error_recovery) { | ||
| 3378 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host reset in " | ||
| 3379 | "progress!\n", __func__, ioc->name)); | ||
| 3380 | return; | ||
| 3381 | } | ||
| 3382 | |||
| 3383 | smid = mpt2sas_base_get_smid_hpr(ioc, ioc->tm_tr_volume_cb_idx); | ||
| 3384 | if (!smid) { | ||
| 3385 | delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC); | ||
| 3386 | if (!delayed_tr) | ||
| 3387 | return; | ||
| 3388 | INIT_LIST_HEAD(&delayed_tr->list); | ||
| 3389 | delayed_tr->handle = handle; | ||
| 3390 | list_add_tail(&delayed_tr->list, &ioc->delayed_tr_volume_list); | ||
| 3391 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 3392 | "DELAYED:tr:handle(0x%04x), (open)\n", | ||
| 3393 | ioc->name, handle)); | ||
| 3394 | return; | ||
| 3395 | } | ||
| 3396 | |||
| 3397 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "tr_send:handle(0x%04x), " | ||
| 3398 | "(open), smid(%d), cb(%d)\n", ioc->name, handle, smid, | ||
| 3399 | ioc->tm_tr_volume_cb_idx)); | ||
| 3400 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); | ||
| 3401 | memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t)); | ||
| 3402 | mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; | ||
| 3403 | mpi_request->DevHandle = cpu_to_le16(handle); | ||
| 3404 | mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; | ||
| 3405 | mpt2sas_base_put_smid_hi_priority(ioc, smid); | ||
| 3406 | } | ||
| 3407 | |||
| 3408 | /** | ||
| 3409 | * _scsih_tm_volume_tr_complete - target reset completion | ||
| 3410 | * @ioc: per adapter object | ||
| 3411 | * @smid: system request message index | ||
| 3412 | * @msix_index: MSIX table index supplied by the OS | ||
| 3413 | * @reply: reply message frame(lower 32bit addr) | ||
| 3414 | * Context: interrupt time. | ||
| 3415 | * | ||
| 3416 | * Return 1 meaning mf should be freed from _base_interrupt | ||
| 3417 | * 0 means the mf is freed from this function. | ||
| 3418 | */ | ||
| 3419 | static u8 | ||
| 3420 | _scsih_tm_volume_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, | ||
| 3421 | u8 msix_index, u32 reply) | ||
| 3422 | { | ||
| 3423 | u16 handle; | ||
| 3424 | Mpi2SCSITaskManagementRequest_t *mpi_request_tm; | ||
| 3425 | Mpi2SCSITaskManagementReply_t *mpi_reply = | ||
| 3426 | mpt2sas_base_get_reply_virt_addr(ioc, reply); | ||
| 3427 | |||
| 3428 | if (ioc->shost_recovery || ioc->remove_host || | ||
| 3429 | ioc->pci_error_recovery) { | ||
| 3430 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host reset in " | ||
| 3431 | "progress!\n", __func__, ioc->name)); | ||
| 3432 | return 1; | ||
| 3433 | } | ||
| 3434 | if (unlikely(!mpi_reply)) { | ||
| 3435 | printk(MPT2SAS_ERR_FMT "mpi_reply not valid at %s:%d/%s()!\n", | ||
| 3436 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 3437 | return 1; | ||
| 3438 | } | ||
| 3439 | mpi_request_tm = mpt2sas_base_get_msg_frame(ioc, smid); | ||
| 3440 | handle = le16_to_cpu(mpi_request_tm->DevHandle); | ||
| 3441 | if (handle != le16_to_cpu(mpi_reply->DevHandle)) { | ||
| 3442 | dewtprintk(ioc, printk("spurious interrupt: " | ||
| 3443 | "handle(0x%04x:0x%04x), smid(%d)!!!\n", handle, | ||
| 3444 | le16_to_cpu(mpi_reply->DevHandle), smid)); | ||
| 3445 | return 0; | ||
| 3446 | } | ||
| 3447 | |||
| 3448 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 3449 | "tr_complete:handle(0x%04x), (open) smid(%d), ioc_status(0x%04x), " | ||
| 3450 | "loginfo(0x%08x), completed(%d)\n", ioc->name, | ||
| 3451 | handle, smid, le16_to_cpu(mpi_reply->IOCStatus), | ||
| 3452 | le32_to_cpu(mpi_reply->IOCLogInfo), | ||
| 3453 | le32_to_cpu(mpi_reply->TerminationCount))); | ||
| 3454 | |||
| 3455 | return _scsih_check_for_pending_tm(ioc, smid); | ||
| 3456 | } | ||
| 3457 | |||
| 3458 | /** | ||
| 3459 | * _scsih_tm_tr_complete - | ||
| 3460 | * @ioc: per adapter object | ||
| 3461 | * @smid: system request message index | ||
| 3462 | * @msix_index: MSIX table index supplied by the OS | ||
| 3463 | * @reply: reply message frame(lower 32bit addr) | ||
| 3464 | * Context: interrupt time. | ||
| 3465 | * | ||
| 3466 | * This is the target reset completion routine. | ||
| 3467 | * This code is part of the code to initiate the device removal | ||
| 3468 | * handshake protocol with controller firmware. | ||
| 3469 | * It will send a sas iounit control request (MPI2_SAS_OP_REMOVE_DEVICE) | ||
| 3470 | * | ||
| 3471 | * Return 1 meaning mf should be freed from _base_interrupt | ||
| 3472 | * 0 means the mf is freed from this function. | ||
| 3473 | */ | ||
| 3474 | static u8 | ||
| 3475 | _scsih_tm_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | ||
| 3476 | u32 reply) | ||
| 3477 | { | ||
| 3478 | u16 handle; | ||
| 3479 | Mpi2SCSITaskManagementRequest_t *mpi_request_tm; | ||
| 3480 | Mpi2SCSITaskManagementReply_t *mpi_reply = | ||
| 3481 | mpt2sas_base_get_reply_virt_addr(ioc, reply); | ||
| 3482 | Mpi2SasIoUnitControlRequest_t *mpi_request; | ||
| 3483 | u16 smid_sas_ctrl; | ||
| 3484 | u32 ioc_state; | ||
| 3485 | |||
| 3486 | if (ioc->remove_host) { | ||
| 3487 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host has been " | ||
| 3488 | "removed\n", __func__, ioc->name)); | ||
| 3489 | return 1; | ||
| 3490 | } else if (ioc->pci_error_recovery) { | ||
| 3491 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host in pci " | ||
| 3492 | "error recovery\n", __func__, ioc->name)); | ||
| 3493 | return 1; | ||
| 3494 | } | ||
| 3495 | ioc_state = mpt2sas_base_get_iocstate(ioc, 1); | ||
| 3496 | if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { | ||
| 3497 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host is not " | ||
| 3498 | "operational\n", __func__, ioc->name)); | ||
| 3499 | return 1; | ||
| 3500 | } | ||
| 3501 | if (unlikely(!mpi_reply)) { | ||
| 3502 | printk(MPT2SAS_ERR_FMT "mpi_reply not valid at %s:%d/%s()!\n", | ||
| 3503 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 3504 | return 1; | ||
| 3505 | } | ||
| 3506 | mpi_request_tm = mpt2sas_base_get_msg_frame(ioc, smid); | ||
| 3507 | handle = le16_to_cpu(mpi_request_tm->DevHandle); | ||
| 3508 | if (handle != le16_to_cpu(mpi_reply->DevHandle)) { | ||
| 3509 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "spurious interrupt: " | ||
| 3510 | "handle(0x%04x:0x%04x), smid(%d)!!!\n", ioc->name, handle, | ||
| 3511 | le16_to_cpu(mpi_reply->DevHandle), smid)); | ||
| 3512 | return 0; | ||
| 3513 | } | ||
| 3514 | |||
| 3515 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 3516 | "tr_complete:handle(0x%04x), (open) smid(%d), ioc_status(0x%04x), " | ||
| 3517 | "loginfo(0x%08x), completed(%d)\n", ioc->name, | ||
| 3518 | handle, smid, le16_to_cpu(mpi_reply->IOCStatus), | ||
| 3519 | le32_to_cpu(mpi_reply->IOCLogInfo), | ||
| 3520 | le32_to_cpu(mpi_reply->TerminationCount))); | ||
| 3521 | |||
| 3522 | smid_sas_ctrl = mpt2sas_base_get_smid(ioc, ioc->tm_sas_control_cb_idx); | ||
| 3523 | if (!smid_sas_ctrl) { | ||
| 3524 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", | ||
| 3525 | ioc->name, __func__); | ||
| 3526 | return 1; | ||
| 3527 | } | ||
| 3528 | |||
| 3529 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "sc_send:handle(0x%04x), " | ||
| 3530 | "(open), smid(%d), cb(%d)\n", ioc->name, handle, smid_sas_ctrl, | ||
| 3531 | ioc->tm_sas_control_cb_idx)); | ||
| 3532 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid_sas_ctrl); | ||
| 3533 | memset(mpi_request, 0, sizeof(Mpi2SasIoUnitControlRequest_t)); | ||
| 3534 | mpi_request->Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL; | ||
| 3535 | mpi_request->Operation = MPI2_SAS_OP_REMOVE_DEVICE; | ||
| 3536 | mpi_request->DevHandle = mpi_request_tm->DevHandle; | ||
| 3537 | mpt2sas_base_put_smid_default(ioc, smid_sas_ctrl); | ||
| 3538 | |||
| 3539 | return _scsih_check_for_pending_tm(ioc, smid); | ||
| 3540 | } | ||
| 3541 | |||
| 3542 | /** | ||
| 3543 | * _scsih_check_for_pending_tm - check for pending task management | ||
| 3544 | * @ioc: per adapter object | ||
| 3545 | * @smid: system request message index | ||
| 3546 | * | ||
| 3547 | * This will check delayed target reset list, and feed the | ||
| 3548 | * next reqeust. | ||
| 3549 | * | ||
| 3550 | * Return 1 meaning mf should be freed from _base_interrupt | ||
| 3551 | * 0 means the mf is freed from this function. | ||
| 3552 | */ | ||
| 3553 | static u8 | ||
| 3554 | _scsih_check_for_pending_tm(struct MPT2SAS_ADAPTER *ioc, u16 smid) | ||
| 3555 | { | ||
| 3556 | struct _tr_list *delayed_tr; | ||
| 3557 | |||
| 3558 | if (!list_empty(&ioc->delayed_tr_volume_list)) { | ||
| 3559 | delayed_tr = list_entry(ioc->delayed_tr_volume_list.next, | ||
| 3560 | struct _tr_list, list); | ||
| 3561 | mpt2sas_base_free_smid(ioc, smid); | ||
| 3562 | _scsih_tm_tr_volume_send(ioc, delayed_tr->handle); | ||
| 3563 | list_del(&delayed_tr->list); | ||
| 3564 | kfree(delayed_tr); | ||
| 3565 | return 0; | ||
| 3566 | } | ||
| 3567 | |||
| 3568 | if (!list_empty(&ioc->delayed_tr_list)) { | ||
| 3569 | delayed_tr = list_entry(ioc->delayed_tr_list.next, | ||
| 3570 | struct _tr_list, list); | ||
| 3571 | mpt2sas_base_free_smid(ioc, smid); | ||
| 3572 | _scsih_tm_tr_send(ioc, delayed_tr->handle); | ||
| 3573 | list_del(&delayed_tr->list); | ||
| 3574 | kfree(delayed_tr); | ||
| 3575 | return 0; | ||
| 3576 | } | ||
| 3577 | |||
| 3578 | return 1; | ||
| 3579 | } | ||
| 3580 | |||
| 3581 | /** | ||
| 3582 | * _scsih_check_topo_delete_events - sanity check on topo events | ||
| 3583 | * @ioc: per adapter object | ||
| 3584 | * @event_data: the event data payload | ||
| 3585 | * | ||
| 3586 | * This routine added to better handle cable breaker. | ||
| 3587 | * | ||
| 3588 | * This handles the case where driver receives multiple expander | ||
| 3589 | * add and delete events in a single shot. When there is a delete event | ||
| 3590 | * the routine will void any pending add events waiting in the event queue. | ||
| 3591 | * | ||
| 3592 | * Return nothing. | ||
| 3593 | */ | ||
| 3594 | static void | ||
| 3595 | _scsih_check_topo_delete_events(struct MPT2SAS_ADAPTER *ioc, | ||
| 3596 | Mpi2EventDataSasTopologyChangeList_t *event_data) | ||
| 3597 | { | ||
| 3598 | struct fw_event_work *fw_event; | ||
| 3599 | Mpi2EventDataSasTopologyChangeList_t *local_event_data; | ||
| 3600 | u16 expander_handle; | ||
| 3601 | struct _sas_node *sas_expander; | ||
| 3602 | unsigned long flags; | ||
| 3603 | int i, reason_code; | ||
| 3604 | u16 handle; | ||
| 3605 | |||
| 3606 | for (i = 0 ; i < event_data->NumEntries; i++) { | ||
| 3607 | handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle); | ||
| 3608 | if (!handle) | ||
| 3609 | continue; | ||
| 3610 | reason_code = event_data->PHY[i].PhyStatus & | ||
| 3611 | MPI2_EVENT_SAS_TOPO_RC_MASK; | ||
| 3612 | if (reason_code == MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING) | ||
| 3613 | _scsih_tm_tr_send(ioc, handle); | ||
| 3614 | } | ||
| 3615 | |||
| 3616 | expander_handle = le16_to_cpu(event_data->ExpanderDevHandle); | ||
| 3617 | if (expander_handle < ioc->sas_hba.num_phys) { | ||
| 3618 | _scsih_block_io_to_children_attached_directly(ioc, event_data); | ||
| 3619 | return; | ||
| 3620 | } | ||
| 3621 | if (event_data->ExpStatus == | ||
| 3622 | MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING) { | ||
| 3623 | /* put expander attached devices into blocking state */ | ||
| 3624 | spin_lock_irqsave(&ioc->sas_node_lock, flags); | ||
| 3625 | sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc, | ||
| 3626 | expander_handle); | ||
| 3627 | _scsih_block_io_to_children_attached_to_ex(ioc, sas_expander); | ||
| 3628 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | ||
| 3629 | do { | ||
| 3630 | handle = find_first_bit(ioc->blocking_handles, | ||
| 3631 | ioc->facts.MaxDevHandle); | ||
| 3632 | if (handle < ioc->facts.MaxDevHandle) | ||
| 3633 | _scsih_block_io_device(ioc, handle); | ||
| 3634 | } while (test_and_clear_bit(handle, ioc->blocking_handles)); | ||
| 3635 | } else if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_RESPONDING) | ||
| 3636 | _scsih_block_io_to_children_attached_directly(ioc, event_data); | ||
| 3637 | |||
| 3638 | if (event_data->ExpStatus != MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING) | ||
| 3639 | return; | ||
| 3640 | |||
| 3641 | /* mark ignore flag for pending events */ | ||
| 3642 | spin_lock_irqsave(&ioc->fw_event_lock, flags); | ||
| 3643 | list_for_each_entry(fw_event, &ioc->fw_event_list, list) { | ||
| 3644 | if (fw_event->event != MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST || | ||
| 3645 | fw_event->ignore) | ||
| 3646 | continue; | ||
| 3647 | local_event_data = (Mpi2EventDataSasTopologyChangeList_t *) | ||
| 3648 | fw_event->event_data; | ||
| 3649 | if (local_event_data->ExpStatus == | ||
| 3650 | MPI2_EVENT_SAS_TOPO_ES_ADDED || | ||
| 3651 | local_event_data->ExpStatus == | ||
| 3652 | MPI2_EVENT_SAS_TOPO_ES_RESPONDING) { | ||
| 3653 | if (le16_to_cpu(local_event_data->ExpanderDevHandle) == | ||
| 3654 | expander_handle) { | ||
| 3655 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 3656 | "setting ignoring flag\n", ioc->name)); | ||
| 3657 | fw_event->ignore = 1; | ||
| 3658 | } | ||
| 3659 | } | ||
| 3660 | } | ||
| 3661 | spin_unlock_irqrestore(&ioc->fw_event_lock, flags); | ||
| 3662 | } | ||
| 3663 | |||
| 3664 | /** | ||
| 3665 | * _scsih_set_volume_delete_flag - setting volume delete flag | ||
| 3666 | * @ioc: per adapter object | ||
| 3667 | * @handle: device handle | ||
| 3668 | * | ||
| 3669 | * This | ||
| 3670 | * Return nothing. | ||
| 3671 | */ | ||
| 3672 | static void | ||
| 3673 | _scsih_set_volume_delete_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle) | ||
| 3674 | { | ||
| 3675 | struct _raid_device *raid_device; | ||
| 3676 | struct MPT2SAS_TARGET *sas_target_priv_data; | ||
| 3677 | unsigned long flags; | ||
| 3678 | |||
| 3679 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | ||
| 3680 | raid_device = _scsih_raid_device_find_by_handle(ioc, handle); | ||
| 3681 | if (raid_device && raid_device->starget && | ||
| 3682 | raid_device->starget->hostdata) { | ||
| 3683 | sas_target_priv_data = | ||
| 3684 | raid_device->starget->hostdata; | ||
| 3685 | sas_target_priv_data->deleted = 1; | ||
| 3686 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 3687 | "setting delete flag: handle(0x%04x), " | ||
| 3688 | "wwid(0x%016llx)\n", ioc->name, handle, | ||
| 3689 | (unsigned long long) raid_device->wwid)); | ||
| 3690 | } | ||
| 3691 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); | ||
| 3692 | } | ||
| 3693 | |||
| 3694 | /** | ||
| 3695 | * _scsih_set_volume_handle_for_tr - set handle for target reset to volume | ||
| 3696 | * @handle: input handle | ||
| 3697 | * @a: handle for volume a | ||
| 3698 | * @b: handle for volume b | ||
| 3699 | * | ||
| 3700 | * IR firmware only supports two raid volumes. The purpose of this | ||
| 3701 | * routine is to set the volume handle in either a or b. When the given | ||
| 3702 | * input handle is non-zero, or when a and b have not been set before. | ||
| 3703 | */ | ||
| 3704 | static void | ||
| 3705 | _scsih_set_volume_handle_for_tr(u16 handle, u16 *a, u16 *b) | ||
| 3706 | { | ||
| 3707 | if (!handle || handle == *a || handle == *b) | ||
| 3708 | return; | ||
| 3709 | if (!*a) | ||
| 3710 | *a = handle; | ||
| 3711 | else if (!*b) | ||
| 3712 | *b = handle; | ||
| 3713 | } | ||
| 3714 | |||
| 3715 | /** | ||
| 3716 | * _scsih_check_ir_config_unhide_events - check for UNHIDE events | ||
| 3717 | * @ioc: per adapter object | ||
| 3718 | * @event_data: the event data payload | ||
| 3719 | * Context: interrupt time. | ||
| 3720 | * | ||
| 3721 | * This routine will send target reset to volume, followed by target | ||
| 3722 | * resets to the PDs. This is called when a PD has been removed, or | ||
| 3723 | * volume has been deleted or removed. When the target reset is sent | ||
| 3724 | * to volume, the PD target resets need to be queued to start upon | ||
| 3725 | * completion of the volume target reset. | ||
| 3726 | * | ||
| 3727 | * Return nothing. | ||
| 3728 | */ | ||
| 3729 | static void | ||
| 3730 | _scsih_check_ir_config_unhide_events(struct MPT2SAS_ADAPTER *ioc, | ||
| 3731 | Mpi2EventDataIrConfigChangeList_t *event_data) | ||
| 3732 | { | ||
| 3733 | Mpi2EventIrConfigElement_t *element; | ||
| 3734 | int i; | ||
| 3735 | u16 handle, volume_handle, a, b; | ||
| 3736 | struct _tr_list *delayed_tr; | ||
| 3737 | |||
| 3738 | a = 0; | ||
| 3739 | b = 0; | ||
| 3740 | |||
| 3741 | if (ioc->is_warpdrive) | ||
| 3742 | return; | ||
| 3743 | |||
| 3744 | /* Volume Resets for Deleted or Removed */ | ||
| 3745 | element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; | ||
| 3746 | for (i = 0; i < event_data->NumElements; i++, element++) { | ||
| 3747 | if (element->ReasonCode == | ||
| 3748 | MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED || | ||
| 3749 | element->ReasonCode == | ||
| 3750 | MPI2_EVENT_IR_CHANGE_RC_REMOVED) { | ||
| 3751 | volume_handle = le16_to_cpu(element->VolDevHandle); | ||
| 3752 | _scsih_set_volume_delete_flag(ioc, volume_handle); | ||
| 3753 | _scsih_set_volume_handle_for_tr(volume_handle, &a, &b); | ||
| 3754 | } | ||
| 3755 | } | ||
| 3756 | |||
| 3757 | /* Volume Resets for UNHIDE events */ | ||
| 3758 | element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; | ||
| 3759 | for (i = 0; i < event_data->NumElements; i++, element++) { | ||
| 3760 | if (le32_to_cpu(event_data->Flags) & | ||
| 3761 | MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) | ||
| 3762 | continue; | ||
| 3763 | if (element->ReasonCode == MPI2_EVENT_IR_CHANGE_RC_UNHIDE) { | ||
| 3764 | volume_handle = le16_to_cpu(element->VolDevHandle); | ||
| 3765 | _scsih_set_volume_handle_for_tr(volume_handle, &a, &b); | ||
| 3766 | } | ||
| 3767 | } | ||
| 3768 | |||
| 3769 | if (a) | ||
| 3770 | _scsih_tm_tr_volume_send(ioc, a); | ||
| 3771 | if (b) | ||
| 3772 | _scsih_tm_tr_volume_send(ioc, b); | ||
| 3773 | |||
| 3774 | /* PD target resets */ | ||
| 3775 | element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; | ||
| 3776 | for (i = 0; i < event_data->NumElements; i++, element++) { | ||
| 3777 | if (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_UNHIDE) | ||
| 3778 | continue; | ||
| 3779 | handle = le16_to_cpu(element->PhysDiskDevHandle); | ||
| 3780 | volume_handle = le16_to_cpu(element->VolDevHandle); | ||
| 3781 | clear_bit(handle, ioc->pd_handles); | ||
| 3782 | if (!volume_handle) | ||
| 3783 | _scsih_tm_tr_send(ioc, handle); | ||
| 3784 | else if (volume_handle == a || volume_handle == b) { | ||
| 3785 | delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC); | ||
| 3786 | BUG_ON(!delayed_tr); | ||
| 3787 | INIT_LIST_HEAD(&delayed_tr->list); | ||
| 3788 | delayed_tr->handle = handle; | ||
| 3789 | list_add_tail(&delayed_tr->list, &ioc->delayed_tr_list); | ||
| 3790 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 3791 | "DELAYED:tr:handle(0x%04x), (open)\n", ioc->name, | ||
| 3792 | handle)); | ||
| 3793 | } else | ||
| 3794 | _scsih_tm_tr_send(ioc, handle); | ||
| 3795 | } | ||
| 3796 | } | ||
| 3797 | |||
| 3798 | |||
| 3799 | /** | ||
| 3800 | * _scsih_check_volume_delete_events - set delete flag for volumes | ||
| 3801 | * @ioc: per adapter object | ||
| 3802 | * @event_data: the event data payload | ||
| 3803 | * Context: interrupt time. | ||
| 3804 | * | ||
| 3805 | * This will handle the case when the cable connected to entire volume is | ||
| 3806 | * pulled. We will take care of setting the deleted flag so normal IO will | ||
| 3807 | * not be sent. | ||
| 3808 | * | ||
| 3809 | * Return nothing. | ||
| 3810 | */ | ||
| 3811 | static void | ||
| 3812 | _scsih_check_volume_delete_events(struct MPT2SAS_ADAPTER *ioc, | ||
| 3813 | Mpi2EventDataIrVolume_t *event_data) | ||
| 3814 | { | ||
| 3815 | u32 state; | ||
| 3816 | |||
| 3817 | if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED) | ||
| 3818 | return; | ||
| 3819 | state = le32_to_cpu(event_data->NewValue); | ||
| 3820 | if (state == MPI2_RAID_VOL_STATE_MISSING || state == | ||
| 3821 | MPI2_RAID_VOL_STATE_FAILED) | ||
| 3822 | _scsih_set_volume_delete_flag(ioc, | ||
| 3823 | le16_to_cpu(event_data->VolDevHandle)); | ||
| 3824 | } | ||
| 3825 | |||
| 3826 | /** | ||
| 3827 | * _scsih_temp_threshold_events - display temperature threshold exceeded events | ||
| 3828 | * @ioc: per adapter object | ||
| 3829 | * @event_data: the temp threshold event data | ||
| 3830 | * Context: interrupt time. | ||
| 3831 | * | ||
| 3832 | * Return nothing. | ||
| 3833 | */ | ||
| 3834 | static void | ||
| 3835 | _scsih_temp_threshold_events(struct MPT2SAS_ADAPTER *ioc, | ||
| 3836 | Mpi2EventDataTemperature_t *event_data) | ||
| 3837 | { | ||
| 3838 | if (ioc->temp_sensors_count >= event_data->SensorNum) { | ||
| 3839 | printk(MPT2SAS_ERR_FMT "Temperature Threshold flags %s%s%s%s" | ||
| 3840 | " exceeded for Sensor: %d !!!\n", ioc->name, | ||
| 3841 | ((le16_to_cpu(event_data->Status) & 0x1) == 1) ? "0 " : " ", | ||
| 3842 | ((le16_to_cpu(event_data->Status) & 0x2) == 2) ? "1 " : " ", | ||
| 3843 | ((le16_to_cpu(event_data->Status) & 0x4) == 4) ? "2 " : " ", | ||
| 3844 | ((le16_to_cpu(event_data->Status) & 0x8) == 8) ? "3 " : " ", | ||
| 3845 | event_data->SensorNum); | ||
| 3846 | printk(MPT2SAS_ERR_FMT "Current Temp In Celsius: %d\n", | ||
| 3847 | ioc->name, event_data->CurrentTemperature); | ||
| 3848 | } | ||
| 3849 | } | ||
| 3850 | |||
| 3851 | /** | ||
| 3852 | * _scsih_flush_running_cmds - completing outstanding commands. | ||
| 3853 | * @ioc: per adapter object | ||
| 3854 | * | ||
| 3855 | * The flushing out of all pending scmd commands following host reset, | ||
| 3856 | * where all IO is dropped to the floor. | ||
| 3857 | * | ||
| 3858 | * Return nothing. | ||
| 3859 | */ | ||
| 3860 | static void | ||
| 3861 | _scsih_flush_running_cmds(struct MPT2SAS_ADAPTER *ioc) | ||
| 3862 | { | ||
| 3863 | struct scsi_cmnd *scmd; | ||
| 3864 | u16 smid; | ||
| 3865 | u16 count = 0; | ||
| 3866 | |||
| 3867 | for (smid = 1; smid <= ioc->scsiio_depth; smid++) { | ||
| 3868 | scmd = _scsih_scsi_lookup_get_clear(ioc, smid); | ||
| 3869 | if (!scmd) | ||
| 3870 | continue; | ||
| 3871 | count++; | ||
| 3872 | mpt2sas_base_free_smid(ioc, smid); | ||
| 3873 | scsi_dma_unmap(scmd); | ||
| 3874 | if (ioc->pci_error_recovery) | ||
| 3875 | scmd->result = DID_NO_CONNECT << 16; | ||
| 3876 | else | ||
| 3877 | scmd->result = DID_RESET << 16; | ||
| 3878 | scmd->scsi_done(scmd); | ||
| 3879 | } | ||
| 3880 | dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "completing %d cmds\n", | ||
| 3881 | ioc->name, count)); | ||
| 3882 | } | ||
| 3883 | |||
| 3884 | /** | ||
| 3885 | * _scsih_setup_eedp - setup MPI request for EEDP transfer | ||
| 3886 | * @scmd: pointer to scsi command object | ||
| 3887 | * @mpi_request: pointer to the SCSI_IO reqest message frame | ||
| 3888 | * | ||
| 3889 | * Supporting protection 1 and 3. | ||
| 3890 | * | ||
| 3891 | * Returns nothing | ||
| 3892 | */ | ||
| 3893 | static void | ||
| 3894 | _scsih_setup_eedp(struct scsi_cmnd *scmd, Mpi2SCSIIORequest_t *mpi_request) | ||
| 3895 | { | ||
| 3896 | u16 eedp_flags; | ||
| 3897 | unsigned char prot_op = scsi_get_prot_op(scmd); | ||
| 3898 | unsigned char prot_type = scsi_get_prot_type(scmd); | ||
| 3899 | |||
| 3900 | if (prot_type == SCSI_PROT_DIF_TYPE0 || prot_op == SCSI_PROT_NORMAL) | ||
| 3901 | return; | ||
| 3902 | |||
| 3903 | if (prot_op == SCSI_PROT_READ_STRIP) | ||
| 3904 | eedp_flags = MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP; | ||
| 3905 | else if (prot_op == SCSI_PROT_WRITE_INSERT) | ||
| 3906 | eedp_flags = MPI2_SCSIIO_EEDPFLAGS_INSERT_OP; | ||
| 3907 | else | ||
| 3908 | return; | ||
| 3909 | |||
| 3910 | switch (prot_type) { | ||
| 3911 | case SCSI_PROT_DIF_TYPE1: | ||
| 3912 | case SCSI_PROT_DIF_TYPE2: | ||
| 3913 | |||
| 3914 | /* | ||
| 3915 | * enable ref/guard checking | ||
| 3916 | * auto increment ref tag | ||
| 3917 | */ | ||
| 3918 | eedp_flags |= MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG | | ||
| 3919 | MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG | | ||
| 3920 | MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD; | ||
| 3921 | mpi_request->CDB.EEDP32.PrimaryReferenceTag = | ||
| 3922 | cpu_to_be32(scsi_get_lba(scmd)); | ||
| 3923 | break; | ||
| 3924 | |||
| 3925 | case SCSI_PROT_DIF_TYPE3: | ||
| 3926 | |||
| 3927 | /* | ||
| 3928 | * enable guard checking | ||
| 3929 | */ | ||
| 3930 | eedp_flags |= MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD; | ||
| 3931 | break; | ||
| 3932 | } | ||
| 3933 | mpi_request->EEDPBlockSize = cpu_to_le32(scmd->device->sector_size); | ||
| 3934 | mpi_request->EEDPFlags = cpu_to_le16(eedp_flags); | ||
| 3935 | } | ||
| 3936 | |||
| 3937 | /** | ||
| 3938 | * _scsih_eedp_error_handling - return sense code for EEDP errors | ||
| 3939 | * @scmd: pointer to scsi command object | ||
| 3940 | * @ioc_status: ioc status | ||
| 3941 | * | ||
| 3942 | * Returns nothing | ||
| 3943 | */ | ||
| 3944 | static void | ||
| 3945 | _scsih_eedp_error_handling(struct scsi_cmnd *scmd, u16 ioc_status) | ||
| 3946 | { | ||
| 3947 | u8 ascq; | ||
| 3948 | |||
| 3949 | switch (ioc_status) { | ||
| 3950 | case MPI2_IOCSTATUS_EEDP_GUARD_ERROR: | ||
| 3951 | ascq = 0x01; | ||
| 3952 | break; | ||
| 3953 | case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR: | ||
| 3954 | ascq = 0x02; | ||
| 3955 | break; | ||
| 3956 | case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR: | ||
| 3957 | ascq = 0x03; | ||
| 3958 | break; | ||
| 3959 | default: | ||
| 3960 | ascq = 0x00; | ||
| 3961 | break; | ||
| 3962 | } | ||
| 3963 | |||
| 3964 | scsi_build_sense_buffer(0, scmd->sense_buffer, ILLEGAL_REQUEST, 0x10, ascq); | ||
| 3965 | scmd->result = DRIVER_SENSE << 24 | (DID_ABORT << 16) | | ||
| 3966 | SAM_STAT_CHECK_CONDITION; | ||
| 3967 | } | ||
| 3968 | |||
| 3969 | /** | ||
| 3970 | * _scsih_scsi_direct_io_get - returns direct io flag | ||
| 3971 | * @ioc: per adapter object | ||
| 3972 | * @smid: system request message index | ||
| 3973 | * | ||
| 3974 | * Returns the smid stored scmd pointer. | ||
| 3975 | */ | ||
| 3976 | static inline u8 | ||
| 3977 | _scsih_scsi_direct_io_get(struct MPT2SAS_ADAPTER *ioc, u16 smid) | ||
| 3978 | { | ||
| 3979 | return ioc->scsi_lookup[smid - 1].direct_io; | ||
| 3980 | } | ||
| 3981 | |||
| 3982 | /** | ||
| 3983 | * _scsih_scsi_direct_io_set - sets direct io flag | ||
| 3984 | * @ioc: per adapter object | ||
| 3985 | * @smid: system request message index | ||
| 3986 | * @direct_io: Zero or non-zero value to set in the direct_io flag | ||
| 3987 | * | ||
| 3988 | * Returns Nothing. | ||
| 3989 | */ | ||
| 3990 | static inline void | ||
| 3991 | _scsih_scsi_direct_io_set(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 direct_io) | ||
| 3992 | { | ||
| 3993 | ioc->scsi_lookup[smid - 1].direct_io = direct_io; | ||
| 3994 | } | ||
| 3995 | |||
| 3996 | |||
| 3997 | /** | ||
| 3998 | * _scsih_setup_direct_io - setup MPI request for WARPDRIVE Direct I/O | ||
| 3999 | * @ioc: per adapter object | ||
| 4000 | * @scmd: pointer to scsi command object | ||
| 4001 | * @raid_device: pointer to raid device data structure | ||
| 4002 | * @mpi_request: pointer to the SCSI_IO reqest message frame | ||
| 4003 | * @smid: system request message index | ||
| 4004 | * | ||
| 4005 | * Returns nothing | ||
| 4006 | */ | ||
| 4007 | static void | ||
| 4008 | _scsih_setup_direct_io(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, | ||
| 4009 | struct _raid_device *raid_device, Mpi2SCSIIORequest_t *mpi_request, | ||
| 4010 | u16 smid) | ||
| 4011 | { | ||
| 4012 | sector_t v_lba, p_lba, stripe_off, column, io_size; | ||
| 4013 | u32 stripe_sz, stripe_exp; | ||
| 4014 | u8 num_pds, cmd = scmd->cmnd[0]; | ||
| 4015 | |||
| 4016 | if (cmd != READ_10 && cmd != WRITE_10 && | ||
| 4017 | cmd != READ_16 && cmd != WRITE_16) | ||
| 4018 | return; | ||
| 4019 | |||
| 4020 | if (cmd == READ_10 || cmd == WRITE_10) | ||
| 4021 | v_lba = get_unaligned_be32(&mpi_request->CDB.CDB32[2]); | ||
| 4022 | else | ||
| 4023 | v_lba = get_unaligned_be64(&mpi_request->CDB.CDB32[2]); | ||
| 4024 | |||
| 4025 | io_size = scsi_bufflen(scmd) >> raid_device->block_exponent; | ||
| 4026 | |||
| 4027 | if (v_lba + io_size - 1 > raid_device->max_lba) | ||
| 4028 | return; | ||
| 4029 | |||
| 4030 | stripe_sz = raid_device->stripe_sz; | ||
| 4031 | stripe_exp = raid_device->stripe_exponent; | ||
| 4032 | stripe_off = v_lba & (stripe_sz - 1); | ||
| 4033 | |||
| 4034 | /* Return unless IO falls within a stripe */ | ||
| 4035 | if (stripe_off + io_size > stripe_sz) | ||
| 4036 | return; | ||
| 4037 | |||
| 4038 | num_pds = raid_device->num_pds; | ||
| 4039 | p_lba = v_lba >> stripe_exp; | ||
| 4040 | column = sector_div(p_lba, num_pds); | ||
| 4041 | p_lba = (p_lba << stripe_exp) + stripe_off; | ||
| 4042 | |||
| 4043 | mpi_request->DevHandle = cpu_to_le16(raid_device->pd_handle[column]); | ||
| 4044 | |||
| 4045 | if (cmd == READ_10 || cmd == WRITE_10) | ||
| 4046 | put_unaligned_be32(lower_32_bits(p_lba), | ||
| 4047 | &mpi_request->CDB.CDB32[2]); | ||
| 4048 | else | ||
| 4049 | put_unaligned_be64(p_lba, &mpi_request->CDB.CDB32[2]); | ||
| 4050 | |||
| 4051 | _scsih_scsi_direct_io_set(ioc, smid, 1); | ||
| 4052 | } | ||
| 4053 | |||
| 4054 | /** | ||
| 4055 | * _scsih_qcmd - main scsi request entry point | ||
| 4056 | * @scmd: pointer to scsi command object | ||
| 4057 | * @done: function pointer to be invoked on completion | ||
| 4058 | * | ||
| 4059 | * The callback index is set inside `ioc->scsi_io_cb_idx`. | ||
| 4060 | * | ||
| 4061 | * Returns 0 on success. If there's a failure, return either: | ||
| 4062 | * SCSI_MLQUEUE_DEVICE_BUSY if the device queue is full, or | ||
| 4063 | * SCSI_MLQUEUE_HOST_BUSY if the entire host queue is full | ||
| 4064 | */ | ||
| 4065 | static int | ||
| 4066 | _scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd) | ||
| 4067 | { | ||
| 4068 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 4069 | struct MPT2SAS_DEVICE *sas_device_priv_data; | ||
| 4070 | struct MPT2SAS_TARGET *sas_target_priv_data; | ||
| 4071 | struct _raid_device *raid_device; | ||
| 4072 | Mpi2SCSIIORequest_t *mpi_request; | ||
| 4073 | u32 mpi_control; | ||
| 4074 | u16 smid; | ||
| 4075 | |||
| 4076 | sas_device_priv_data = scmd->device->hostdata; | ||
| 4077 | if (!sas_device_priv_data || !sas_device_priv_data->sas_target) { | ||
| 4078 | scmd->result = DID_NO_CONNECT << 16; | ||
| 4079 | scmd->scsi_done(scmd); | ||
| 4080 | return 0; | ||
| 4081 | } | ||
| 4082 | |||
| 4083 | if (ioc->pci_error_recovery || ioc->remove_host) { | ||
| 4084 | scmd->result = DID_NO_CONNECT << 16; | ||
| 4085 | scmd->scsi_done(scmd); | ||
| 4086 | return 0; | ||
| 4087 | } | ||
| 4088 | |||
| 4089 | sas_target_priv_data = sas_device_priv_data->sas_target; | ||
| 4090 | /* invalid device handle */ | ||
| 4091 | if (sas_target_priv_data->handle == MPT2SAS_INVALID_DEVICE_HANDLE) { | ||
| 4092 | scmd->result = DID_NO_CONNECT << 16; | ||
| 4093 | scmd->scsi_done(scmd); | ||
| 4094 | return 0; | ||
| 4095 | } | ||
| 4096 | |||
| 4097 | /* host recovery or link resets sent via IOCTLs */ | ||
| 4098 | if (ioc->shost_recovery || ioc->ioc_link_reset_in_progress) | ||
| 4099 | return SCSI_MLQUEUE_HOST_BUSY; | ||
| 4100 | /* device busy with task management */ | ||
| 4101 | else if (sas_device_priv_data->block || sas_target_priv_data->tm_busy) | ||
| 4102 | return SCSI_MLQUEUE_DEVICE_BUSY; | ||
| 4103 | /* device has been deleted */ | ||
| 4104 | else if (sas_target_priv_data->deleted) { | ||
| 4105 | scmd->result = DID_NO_CONNECT << 16; | ||
| 4106 | scmd->scsi_done(scmd); | ||
| 4107 | return 0; | ||
| 4108 | } | ||
| 4109 | |||
| 4110 | if (scmd->sc_data_direction == DMA_FROM_DEVICE) | ||
| 4111 | mpi_control = MPI2_SCSIIO_CONTROL_READ; | ||
| 4112 | else if (scmd->sc_data_direction == DMA_TO_DEVICE) | ||
| 4113 | mpi_control = MPI2_SCSIIO_CONTROL_WRITE; | ||
| 4114 | else | ||
| 4115 | mpi_control = MPI2_SCSIIO_CONTROL_NODATATRANSFER; | ||
| 4116 | |||
| 4117 | /* set tags */ | ||
| 4118 | mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ; | ||
| 4119 | |||
| 4120 | /* Make sure Device is not raid volume. | ||
| 4121 | * We do not expose raid functionality to upper layer for warpdrive. | ||
| 4122 | */ | ||
| 4123 | if (!ioc->is_warpdrive && !_scsih_is_raid(&scmd->device->sdev_gendev) && | ||
| 4124 | sas_is_tlr_enabled(scmd->device) && scmd->cmd_len != 32) | ||
| 4125 | mpi_control |= MPI2_SCSIIO_CONTROL_TLR_ON; | ||
| 4126 | |||
| 4127 | smid = mpt2sas_base_get_smid_scsiio(ioc, ioc->scsi_io_cb_idx, scmd); | ||
| 4128 | if (!smid) { | ||
| 4129 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", | ||
| 4130 | ioc->name, __func__); | ||
| 4131 | goto out; | ||
| 4132 | } | ||
| 4133 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); | ||
| 4134 | memset(mpi_request, 0, sizeof(Mpi2SCSIIORequest_t)); | ||
| 4135 | _scsih_setup_eedp(scmd, mpi_request); | ||
| 4136 | if (scmd->cmd_len == 32) | ||
| 4137 | mpi_control |= 4 << MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT; | ||
| 4138 | mpi_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST; | ||
| 4139 | if (sas_device_priv_data->sas_target->flags & | ||
| 4140 | MPT_TARGET_FLAGS_RAID_COMPONENT) | ||
| 4141 | mpi_request->Function = MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH; | ||
| 4142 | else | ||
| 4143 | mpi_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST; | ||
| 4144 | mpi_request->DevHandle = | ||
| 4145 | cpu_to_le16(sas_device_priv_data->sas_target->handle); | ||
| 4146 | mpi_request->DataLength = cpu_to_le32(scsi_bufflen(scmd)); | ||
| 4147 | mpi_request->Control = cpu_to_le32(mpi_control); | ||
| 4148 | mpi_request->IoFlags = cpu_to_le16(scmd->cmd_len); | ||
| 4149 | mpi_request->MsgFlags = MPI2_SCSIIO_MSGFLAGS_SYSTEM_SENSE_ADDR; | ||
| 4150 | mpi_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE; | ||
| 4151 | mpi_request->SenseBufferLowAddress = | ||
| 4152 | mpt2sas_base_get_sense_buffer_dma(ioc, smid); | ||
| 4153 | mpi_request->SGLOffset0 = offsetof(Mpi2SCSIIORequest_t, SGL) / 4; | ||
| 4154 | mpi_request->SGLFlags = cpu_to_le16(MPI2_SCSIIO_SGLFLAGS_TYPE_MPI + | ||
| 4155 | MPI2_SCSIIO_SGLFLAGS_SYSTEM_ADDR); | ||
| 4156 | mpi_request->VF_ID = 0; /* TODO */ | ||
| 4157 | mpi_request->VP_ID = 0; | ||
| 4158 | int_to_scsilun(sas_device_priv_data->lun, (struct scsi_lun *) | ||
| 4159 | mpi_request->LUN); | ||
| 4160 | memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len); | ||
| 4161 | |||
| 4162 | if (!mpi_request->DataLength) { | ||
| 4163 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request->SGL); | ||
| 4164 | } else { | ||
| 4165 | if (_scsih_build_scatter_gather(ioc, scmd, smid)) { | ||
| 4166 | mpt2sas_base_free_smid(ioc, smid); | ||
| 4167 | goto out; | ||
| 4168 | } | ||
| 4169 | } | ||
| 4170 | |||
| 4171 | raid_device = sas_target_priv_data->raid_device; | ||
| 4172 | if (raid_device && raid_device->direct_io_enabled) | ||
| 4173 | _scsih_setup_direct_io(ioc, scmd, raid_device, mpi_request, | ||
| 4174 | smid); | ||
| 4175 | |||
| 4176 | if (likely(mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST)) | ||
| 4177 | mpt2sas_base_put_smid_scsi_io(ioc, smid, | ||
| 4178 | le16_to_cpu(mpi_request->DevHandle)); | ||
| 4179 | else | ||
| 4180 | mpt2sas_base_put_smid_default(ioc, smid); | ||
| 4181 | return 0; | ||
| 4182 | |||
| 4183 | out: | ||
| 4184 | return SCSI_MLQUEUE_HOST_BUSY; | ||
| 4185 | } | ||
| 4186 | |||
| 4187 | /** | ||
| 4188 | * _scsih_normalize_sense - normalize descriptor and fixed format sense data | ||
| 4189 | * @sense_buffer: sense data returned by target | ||
| 4190 | * @data: normalized skey/asc/ascq | ||
| 4191 | * | ||
| 4192 | * Return nothing. | ||
| 4193 | */ | ||
| 4194 | static void | ||
| 4195 | _scsih_normalize_sense(char *sense_buffer, struct sense_info *data) | ||
| 4196 | { | ||
| 4197 | if ((sense_buffer[0] & 0x7F) >= 0x72) { | ||
| 4198 | /* descriptor format */ | ||
| 4199 | data->skey = sense_buffer[1] & 0x0F; | ||
| 4200 | data->asc = sense_buffer[2]; | ||
| 4201 | data->ascq = sense_buffer[3]; | ||
| 4202 | } else { | ||
| 4203 | /* fixed format */ | ||
| 4204 | data->skey = sense_buffer[2] & 0x0F; | ||
| 4205 | data->asc = sense_buffer[12]; | ||
| 4206 | data->ascq = sense_buffer[13]; | ||
| 4207 | } | ||
| 4208 | } | ||
| 4209 | |||
| 4210 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | ||
| 4211 | /** | ||
| 4212 | * _scsih_scsi_ioc_info - translated non-successful SCSI_IO request | ||
| 4213 | * @ioc: per adapter object | ||
| 4214 | * @scmd: pointer to scsi command object | ||
| 4215 | * @mpi_reply: reply mf payload returned from firmware | ||
| 4216 | * | ||
| 4217 | * scsi_status - SCSI Status code returned from target device | ||
| 4218 | * scsi_state - state info associated with SCSI_IO determined by ioc | ||
| 4219 | * ioc_status - ioc supplied status info | ||
| 4220 | * | ||
| 4221 | * Return nothing. | ||
| 4222 | */ | ||
| 4223 | static void | ||
| 4224 | _scsih_scsi_ioc_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, | ||
| 4225 | Mpi2SCSIIOReply_t *mpi_reply, u16 smid) | ||
| 4226 | { | ||
| 4227 | u32 response_info; | ||
| 4228 | u8 *response_bytes; | ||
| 4229 | u16 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & | ||
| 4230 | MPI2_IOCSTATUS_MASK; | ||
| 4231 | u8 scsi_state = mpi_reply->SCSIState; | ||
| 4232 | u8 scsi_status = mpi_reply->SCSIStatus; | ||
| 4233 | char *desc_ioc_state = NULL; | ||
| 4234 | char *desc_scsi_status = NULL; | ||
| 4235 | char *desc_scsi_state = ioc->tmp_string; | ||
| 4236 | u32 log_info = le32_to_cpu(mpi_reply->IOCLogInfo); | ||
| 4237 | struct _sas_device *sas_device = NULL; | ||
| 4238 | struct scsi_target *starget = scmd->device->sdev_target; | ||
| 4239 | struct MPT2SAS_TARGET *priv_target = starget->hostdata; | ||
| 4240 | char *device_str = NULL; | ||
| 4241 | |||
| 4242 | if (!priv_target) | ||
| 4243 | return; | ||
| 4244 | |||
| 4245 | if (ioc->hide_ir_msg) | ||
| 4246 | device_str = "WarpDrive"; | ||
| 4247 | else | ||
| 4248 | device_str = "volume"; | ||
| 4249 | |||
| 4250 | if (log_info == 0x31170000) | ||
| 4251 | return; | ||
| 4252 | |||
| 4253 | switch (ioc_status) { | ||
| 4254 | case MPI2_IOCSTATUS_SUCCESS: | ||
| 4255 | desc_ioc_state = "success"; | ||
| 4256 | break; | ||
| 4257 | case MPI2_IOCSTATUS_INVALID_FUNCTION: | ||
| 4258 | desc_ioc_state = "invalid function"; | ||
| 4259 | break; | ||
| 4260 | case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR: | ||
| 4261 | desc_ioc_state = "scsi recovered error"; | ||
| 4262 | break; | ||
| 4263 | case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE: | ||
| 4264 | desc_ioc_state = "scsi invalid dev handle"; | ||
| 4265 | break; | ||
| 4266 | case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE: | ||
| 4267 | desc_ioc_state = "scsi device not there"; | ||
| 4268 | break; | ||
| 4269 | case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN: | ||
| 4270 | desc_ioc_state = "scsi data overrun"; | ||
| 4271 | break; | ||
| 4272 | case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN: | ||
| 4273 | desc_ioc_state = "scsi data underrun"; | ||
| 4274 | break; | ||
| 4275 | case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR: | ||
| 4276 | desc_ioc_state = "scsi io data error"; | ||
| 4277 | break; | ||
| 4278 | case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR: | ||
| 4279 | desc_ioc_state = "scsi protocol error"; | ||
| 4280 | break; | ||
| 4281 | case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED: | ||
| 4282 | desc_ioc_state = "scsi task terminated"; | ||
| 4283 | break; | ||
| 4284 | case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: | ||
| 4285 | desc_ioc_state = "scsi residual mismatch"; | ||
| 4286 | break; | ||
| 4287 | case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED: | ||
| 4288 | desc_ioc_state = "scsi task mgmt failed"; | ||
| 4289 | break; | ||
| 4290 | case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED: | ||
| 4291 | desc_ioc_state = "scsi ioc terminated"; | ||
| 4292 | break; | ||
| 4293 | case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED: | ||
| 4294 | desc_ioc_state = "scsi ext terminated"; | ||
| 4295 | break; | ||
| 4296 | case MPI2_IOCSTATUS_EEDP_GUARD_ERROR: | ||
| 4297 | desc_ioc_state = "eedp guard error"; | ||
| 4298 | break; | ||
| 4299 | case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR: | ||
| 4300 | desc_ioc_state = "eedp ref tag error"; | ||
| 4301 | break; | ||
| 4302 | case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR: | ||
| 4303 | desc_ioc_state = "eedp app tag error"; | ||
| 4304 | break; | ||
| 4305 | default: | ||
| 4306 | desc_ioc_state = "unknown"; | ||
| 4307 | break; | ||
| 4308 | } | ||
| 4309 | |||
| 4310 | switch (scsi_status) { | ||
| 4311 | case MPI2_SCSI_STATUS_GOOD: | ||
| 4312 | desc_scsi_status = "good"; | ||
| 4313 | break; | ||
| 4314 | case MPI2_SCSI_STATUS_CHECK_CONDITION: | ||
| 4315 | desc_scsi_status = "check condition"; | ||
| 4316 | break; | ||
| 4317 | case MPI2_SCSI_STATUS_CONDITION_MET: | ||
| 4318 | desc_scsi_status = "condition met"; | ||
| 4319 | break; | ||
| 4320 | case MPI2_SCSI_STATUS_BUSY: | ||
| 4321 | desc_scsi_status = "busy"; | ||
| 4322 | break; | ||
| 4323 | case MPI2_SCSI_STATUS_INTERMEDIATE: | ||
| 4324 | desc_scsi_status = "intermediate"; | ||
| 4325 | break; | ||
| 4326 | case MPI2_SCSI_STATUS_INTERMEDIATE_CONDMET: | ||
| 4327 | desc_scsi_status = "intermediate condmet"; | ||
| 4328 | break; | ||
| 4329 | case MPI2_SCSI_STATUS_RESERVATION_CONFLICT: | ||
| 4330 | desc_scsi_status = "reservation conflict"; | ||
| 4331 | break; | ||
| 4332 | case MPI2_SCSI_STATUS_COMMAND_TERMINATED: | ||
| 4333 | desc_scsi_status = "command terminated"; | ||
| 4334 | break; | ||
| 4335 | case MPI2_SCSI_STATUS_TASK_SET_FULL: | ||
| 4336 | desc_scsi_status = "task set full"; | ||
| 4337 | break; | ||
| 4338 | case MPI2_SCSI_STATUS_ACA_ACTIVE: | ||
| 4339 | desc_scsi_status = "aca active"; | ||
| 4340 | break; | ||
| 4341 | case MPI2_SCSI_STATUS_TASK_ABORTED: | ||
| 4342 | desc_scsi_status = "task aborted"; | ||
| 4343 | break; | ||
| 4344 | default: | ||
| 4345 | desc_scsi_status = "unknown"; | ||
| 4346 | break; | ||
| 4347 | } | ||
| 4348 | |||
| 4349 | desc_scsi_state[0] = '\0'; | ||
| 4350 | if (!scsi_state) | ||
| 4351 | desc_scsi_state = " "; | ||
| 4352 | if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) | ||
| 4353 | strcat(desc_scsi_state, "response info "); | ||
| 4354 | if (scsi_state & MPI2_SCSI_STATE_TERMINATED) | ||
| 4355 | strcat(desc_scsi_state, "state terminated "); | ||
| 4356 | if (scsi_state & MPI2_SCSI_STATE_NO_SCSI_STATUS) | ||
| 4357 | strcat(desc_scsi_state, "no status "); | ||
| 4358 | if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_FAILED) | ||
| 4359 | strcat(desc_scsi_state, "autosense failed "); | ||
| 4360 | if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) | ||
| 4361 | strcat(desc_scsi_state, "autosense valid "); | ||
| 4362 | |||
| 4363 | scsi_print_command(scmd); | ||
| 4364 | |||
| 4365 | if (priv_target->flags & MPT_TARGET_FLAGS_VOLUME) { | ||
| 4366 | printk(MPT2SAS_WARN_FMT "\t%s wwid(0x%016llx)\n", ioc->name, | ||
| 4367 | device_str, (unsigned long long)priv_target->sas_address); | ||
| 4368 | } else { | ||
| 4369 | sas_device = mpt2sas_get_sdev_from_target(ioc, priv_target); | ||
| 4370 | if (sas_device) { | ||
| 4371 | printk(MPT2SAS_WARN_FMT "\tsas_address(0x%016llx), " | ||
| 4372 | "phy(%d)\n", ioc->name, sas_device->sas_address, | ||
| 4373 | sas_device->phy); | ||
| 4374 | printk(MPT2SAS_WARN_FMT | ||
| 4375 | "\tenclosure_logical_id(0x%016llx), slot(%d)\n", | ||
| 4376 | ioc->name, sas_device->enclosure_logical_id, | ||
| 4377 | sas_device->slot); | ||
| 4378 | |||
| 4379 | sas_device_put(sas_device); | ||
| 4380 | } | ||
| 4381 | } | ||
| 4382 | |||
| 4383 | printk(MPT2SAS_WARN_FMT "\thandle(0x%04x), ioc_status(%s)(0x%04x), " | ||
| 4384 | "smid(%d)\n", ioc->name, le16_to_cpu(mpi_reply->DevHandle), | ||
| 4385 | desc_ioc_state, ioc_status, smid); | ||
| 4386 | printk(MPT2SAS_WARN_FMT "\trequest_len(%d), underflow(%d), " | ||
| 4387 | "resid(%d)\n", ioc->name, scsi_bufflen(scmd), scmd->underflow, | ||
| 4388 | scsi_get_resid(scmd)); | ||
| 4389 | printk(MPT2SAS_WARN_FMT "\ttag(%d), transfer_count(%d), " | ||
| 4390 | "sc->result(0x%08x)\n", ioc->name, le16_to_cpu(mpi_reply->TaskTag), | ||
| 4391 | le32_to_cpu(mpi_reply->TransferCount), scmd->result); | ||
| 4392 | printk(MPT2SAS_WARN_FMT "\tscsi_status(%s)(0x%02x), " | ||
| 4393 | "scsi_state(%s)(0x%02x)\n", ioc->name, desc_scsi_status, | ||
| 4394 | scsi_status, desc_scsi_state, scsi_state); | ||
| 4395 | |||
| 4396 | if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) { | ||
| 4397 | struct sense_info data; | ||
| 4398 | _scsih_normalize_sense(scmd->sense_buffer, &data); | ||
| 4399 | printk(MPT2SAS_WARN_FMT "\t[sense_key,asc,ascq]: " | ||
| 4400 | "[0x%02x,0x%02x,0x%02x], count(%d)\n", ioc->name, data.skey, | ||
| 4401 | data.asc, data.ascq, le32_to_cpu(mpi_reply->SenseCount)); | ||
| 4402 | } | ||
| 4403 | |||
| 4404 | if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) { | ||
| 4405 | response_info = le32_to_cpu(mpi_reply->ResponseInfo); | ||
| 4406 | response_bytes = (u8 *)&response_info; | ||
| 4407 | _scsih_response_code(ioc, response_bytes[0]); | ||
| 4408 | } | ||
| 4409 | } | ||
| 4410 | #endif | ||
| 4411 | |||
| 4412 | /** | ||
| 4413 | * _scsih_turn_on_pfa_led - illuminate PFA LED | ||
| 4414 | * @ioc: per adapter object | ||
| 4415 | * @handle: device handle | ||
| 4416 | * Context: process | ||
| 4417 | * | ||
| 4418 | * Return nothing. | ||
| 4419 | */ | ||
| 4420 | static void | ||
| 4421 | _scsih_turn_on_pfa_led(struct MPT2SAS_ADAPTER *ioc, u16 handle) | ||
| 4422 | { | ||
| 4423 | Mpi2SepReply_t mpi_reply; | ||
| 4424 | Mpi2SepRequest_t mpi_request; | ||
| 4425 | struct _sas_device *sas_device; | ||
| 4426 | |||
| 4427 | sas_device = mpt2sas_get_sdev_by_handle(ioc, handle); | ||
| 4428 | if (!sas_device) | ||
| 4429 | return; | ||
| 4430 | |||
| 4431 | memset(&mpi_request, 0, sizeof(Mpi2SepRequest_t)); | ||
| 4432 | mpi_request.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR; | ||
| 4433 | mpi_request.Action = MPI2_SEP_REQ_ACTION_WRITE_STATUS; | ||
| 4434 | mpi_request.SlotStatus = | ||
| 4435 | cpu_to_le32(MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT); | ||
| 4436 | mpi_request.DevHandle = cpu_to_le16(handle); | ||
| 4437 | mpi_request.Flags = MPI2_SEP_REQ_FLAGS_DEVHANDLE_ADDRESS; | ||
| 4438 | if ((mpt2sas_base_scsi_enclosure_processor(ioc, &mpi_reply, | ||
| 4439 | &mpi_request)) != 0) { | ||
| 4440 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", ioc->name, | ||
| 4441 | __FILE__, __LINE__, __func__); | ||
| 4442 | goto out; | ||
| 4443 | } | ||
| 4444 | sas_device->pfa_led_on = 1; | ||
| 4445 | |||
| 4446 | |||
| 4447 | if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) { | ||
| 4448 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 4449 | "enclosure_processor: ioc_status (0x%04x), loginfo(0x%08x)\n", | ||
| 4450 | ioc->name, le16_to_cpu(mpi_reply.IOCStatus), | ||
| 4451 | le32_to_cpu(mpi_reply.IOCLogInfo))); | ||
| 4452 | goto out; | ||
| 4453 | } | ||
| 4454 | out: | ||
| 4455 | sas_device_put(sas_device); | ||
| 4456 | } | ||
| 4457 | |||
| 4458 | /** | ||
| 4459 | * _scsih_turn_off_pfa_led - turn off PFA LED | ||
| 4460 | * @ioc: per adapter object | ||
| 4461 | * @sas_device: sas device whose PFA LED has to turned off | ||
| 4462 | * Context: process | ||
| 4463 | * | ||
| 4464 | * Return nothing. | ||
| 4465 | */ | ||
| 4466 | static void | ||
| 4467 | _scsih_turn_off_pfa_led(struct MPT2SAS_ADAPTER *ioc, | ||
| 4468 | struct _sas_device *sas_device) | ||
| 4469 | { | ||
| 4470 | Mpi2SepReply_t mpi_reply; | ||
| 4471 | Mpi2SepRequest_t mpi_request; | ||
| 4472 | |||
| 4473 | memset(&mpi_request, 0, sizeof(Mpi2SepRequest_t)); | ||
| 4474 | mpi_request.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR; | ||
| 4475 | mpi_request.Action = MPI2_SEP_REQ_ACTION_WRITE_STATUS; | ||
| 4476 | mpi_request.SlotStatus = 0; | ||
| 4477 | mpi_request.Slot = cpu_to_le16(sas_device->slot); | ||
| 4478 | mpi_request.DevHandle = 0; | ||
| 4479 | mpi_request.EnclosureHandle = cpu_to_le16(sas_device->enclosure_handle); | ||
| 4480 | mpi_request.Flags = MPI2_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS; | ||
| 4481 | if ((mpt2sas_base_scsi_enclosure_processor(ioc, &mpi_reply, | ||
| 4482 | &mpi_request)) != 0) { | ||
| 4483 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", ioc->name, | ||
| 4484 | __FILE__, __LINE__, __func__); | ||
| 4485 | return; | ||
| 4486 | } | ||
| 4487 | |||
| 4488 | if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) { | ||
| 4489 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "enclosure_processor: " | ||
| 4490 | "ioc_status (0x%04x), loginfo(0x%08x)\n", ioc->name, | ||
| 4491 | le16_to_cpu(mpi_reply.IOCStatus), | ||
| 4492 | le32_to_cpu(mpi_reply.IOCLogInfo))); | ||
| 4493 | return; | ||
| 4494 | } | ||
| 4495 | } | ||
| 4496 | |||
| 4497 | /** | ||
| 4498 | * _scsih_send_event_to_turn_on_pfa_led - fire delayed event | ||
| 4499 | * @ioc: per adapter object | ||
| 4500 | * @handle: device handle | ||
| 4501 | * Context: interrupt. | ||
| 4502 | * | ||
| 4503 | * Return nothing. | ||
| 4504 | */ | ||
| 4505 | static void | ||
| 4506 | _scsih_send_event_to_turn_on_pfa_led(struct MPT2SAS_ADAPTER *ioc, u16 handle) | ||
| 4507 | { | ||
| 4508 | struct fw_event_work *fw_event; | ||
| 4509 | |||
| 4510 | fw_event = alloc_fw_event_work(0); | ||
| 4511 | if (!fw_event) | ||
| 4512 | return; | ||
| 4513 | fw_event->event = MPT2SAS_TURN_ON_PFA_LED; | ||
| 4514 | fw_event->device_handle = handle; | ||
| 4515 | fw_event->ioc = ioc; | ||
| 4516 | _scsih_fw_event_add(ioc, fw_event); | ||
| 4517 | fw_event_work_put(fw_event); | ||
| 4518 | } | ||
| 4519 | |||
| 4520 | /** | ||
| 4521 | * _scsih_smart_predicted_fault - process smart errors | ||
| 4522 | * @ioc: per adapter object | ||
| 4523 | * @handle: device handle | ||
| 4524 | * Context: interrupt. | ||
| 4525 | * | ||
| 4526 | * Return nothing. | ||
| 4527 | */ | ||
| 4528 | static void | ||
| 4529 | _scsih_smart_predicted_fault(struct MPT2SAS_ADAPTER *ioc, u16 handle) | ||
| 4530 | { | ||
| 4531 | struct scsi_target *starget; | ||
| 4532 | struct MPT2SAS_TARGET *sas_target_priv_data; | ||
| 4533 | Mpi2EventNotificationReply_t *event_reply; | ||
| 4534 | Mpi2EventDataSasDeviceStatusChange_t *event_data; | ||
| 4535 | struct _sas_device *sas_device; | ||
| 4536 | ssize_t sz; | ||
| 4537 | unsigned long flags; | ||
| 4538 | |||
| 4539 | /* only handle non-raid devices */ | ||
| 4540 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 4541 | sas_device = __mpt2sas_get_sdev_by_handle(ioc, handle); | ||
| 4542 | if (!sas_device) { | ||
| 4543 | goto out_unlock; | ||
| 4544 | } | ||
| 4545 | starget = sas_device->starget; | ||
| 4546 | sas_target_priv_data = starget->hostdata; | ||
| 4547 | |||
| 4548 | if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT) || | ||
| 4549 | ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME))) | ||
| 4550 | goto out_unlock; | ||
| 4551 | |||
| 4552 | starget_printk(KERN_WARNING, starget, "predicted fault\n"); | ||
| 4553 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 4554 | |||
| 4555 | if (ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM) | ||
| 4556 | _scsih_send_event_to_turn_on_pfa_led(ioc, handle); | ||
| 4557 | |||
| 4558 | /* insert into event log */ | ||
| 4559 | sz = offsetof(Mpi2EventNotificationReply_t, EventData) + | ||
| 4560 | sizeof(Mpi2EventDataSasDeviceStatusChange_t); | ||
| 4561 | event_reply = kzalloc(sz, GFP_ATOMIC); | ||
| 4562 | if (!event_reply) { | ||
| 4563 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 4564 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 4565 | goto out; | ||
| 4566 | } | ||
| 4567 | |||
| 4568 | event_reply->Function = MPI2_FUNCTION_EVENT_NOTIFICATION; | ||
| 4569 | event_reply->Event = | ||
| 4570 | cpu_to_le16(MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE); | ||
| 4571 | event_reply->MsgLength = sz/4; | ||
| 4572 | event_reply->EventDataLength = | ||
| 4573 | cpu_to_le16(sizeof(Mpi2EventDataSasDeviceStatusChange_t)/4); | ||
| 4574 | event_data = (Mpi2EventDataSasDeviceStatusChange_t *) | ||
| 4575 | event_reply->EventData; | ||
| 4576 | event_data->ReasonCode = MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA; | ||
| 4577 | event_data->ASC = 0x5D; | ||
| 4578 | event_data->DevHandle = cpu_to_le16(handle); | ||
| 4579 | event_data->SASAddress = cpu_to_le64(sas_target_priv_data->sas_address); | ||
| 4580 | mpt2sas_ctl_add_to_event_log(ioc, event_reply); | ||
| 4581 | kfree(event_reply); | ||
| 4582 | out: | ||
| 4583 | if (sas_device) | ||
| 4584 | sas_device_put(sas_device); | ||
| 4585 | return; | ||
| 4586 | |||
| 4587 | out_unlock: | ||
| 4588 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 4589 | goto out; | ||
| 4590 | } | ||
| 4591 | |||
| 4592 | /** | ||
| 4593 | * _scsih_io_done - scsi request callback | ||
| 4594 | * @ioc: per adapter object | ||
| 4595 | * @smid: system request message index | ||
| 4596 | * @msix_index: MSIX table index supplied by the OS | ||
| 4597 | * @reply: reply message frame(lower 32bit addr) | ||
| 4598 | * | ||
| 4599 | * Callback handler when using _scsih_qcmd. | ||
| 4600 | * | ||
| 4601 | * Return 1 meaning mf should be freed from _base_interrupt | ||
| 4602 | * 0 means the mf is freed from this function. | ||
| 4603 | */ | ||
| 4604 | static u8 | ||
| 4605 | _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) | ||
| 4606 | { | ||
| 4607 | Mpi2SCSIIORequest_t *mpi_request; | ||
| 4608 | Mpi2SCSIIOReply_t *mpi_reply; | ||
| 4609 | struct scsi_cmnd *scmd; | ||
| 4610 | u16 ioc_status; | ||
| 4611 | u32 xfer_cnt; | ||
| 4612 | u8 scsi_state; | ||
| 4613 | u8 scsi_status; | ||
| 4614 | u32 log_info; | ||
| 4615 | struct MPT2SAS_DEVICE *sas_device_priv_data; | ||
| 4616 | u32 response_code = 0; | ||
| 4617 | unsigned long flags; | ||
| 4618 | |||
| 4619 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | ||
| 4620 | scmd = _scsih_scsi_lookup_get_clear(ioc, smid); | ||
| 4621 | if (scmd == NULL) | ||
| 4622 | return 1; | ||
| 4623 | |||
| 4624 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); | ||
| 4625 | |||
| 4626 | if (mpi_reply == NULL) { | ||
| 4627 | scmd->result = DID_OK << 16; | ||
| 4628 | goto out; | ||
| 4629 | } | ||
| 4630 | |||
| 4631 | sas_device_priv_data = scmd->device->hostdata; | ||
| 4632 | if (!sas_device_priv_data || !sas_device_priv_data->sas_target || | ||
| 4633 | sas_device_priv_data->sas_target->deleted) { | ||
| 4634 | scmd->result = DID_NO_CONNECT << 16; | ||
| 4635 | goto out; | ||
| 4636 | } | ||
| 4637 | ioc_status = le16_to_cpu(mpi_reply->IOCStatus); | ||
| 4638 | /* | ||
| 4639 | * WARPDRIVE: If direct_io is set then it is directIO, | ||
| 4640 | * the failed direct I/O should be redirected to volume | ||
| 4641 | */ | ||
| 4642 | if (_scsih_scsi_direct_io_get(ioc, smid) && | ||
| 4643 | ((ioc_status & MPI2_IOCSTATUS_MASK) | ||
| 4644 | != MPI2_IOCSTATUS_SCSI_TASK_TERMINATED)) { | ||
| 4645 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | ||
| 4646 | ioc->scsi_lookup[smid - 1].scmd = scmd; | ||
| 4647 | _scsih_scsi_direct_io_set(ioc, smid, 0); | ||
| 4648 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | ||
| 4649 | memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len); | ||
| 4650 | mpi_request->DevHandle = | ||
| 4651 | cpu_to_le16(sas_device_priv_data->sas_target->handle); | ||
| 4652 | mpt2sas_base_put_smid_scsi_io(ioc, smid, | ||
| 4653 | sas_device_priv_data->sas_target->handle); | ||
| 4654 | return 0; | ||
| 4655 | } | ||
| 4656 | |||
| 4657 | |||
| 4658 | /* turning off TLR */ | ||
| 4659 | scsi_state = mpi_reply->SCSIState; | ||
| 4660 | if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) | ||
| 4661 | response_code = | ||
| 4662 | le32_to_cpu(mpi_reply->ResponseInfo) & 0xFF; | ||
| 4663 | if (!sas_device_priv_data->tlr_snoop_check) { | ||
| 4664 | sas_device_priv_data->tlr_snoop_check++; | ||
| 4665 | /* Make sure Device is not raid volume. | ||
| 4666 | * We do not expose raid functionality to upper layer for warpdrive. | ||
| 4667 | */ | ||
| 4668 | if (!ioc->is_warpdrive && !_scsih_is_raid(&scmd->device->sdev_gendev) && | ||
| 4669 | sas_is_tlr_enabled(scmd->device) && | ||
| 4670 | response_code == MPI2_SCSITASKMGMT_RSP_INVALID_FRAME) { | ||
| 4671 | sas_disable_tlr(scmd->device); | ||
| 4672 | sdev_printk(KERN_INFO, scmd->device, "TLR disabled\n"); | ||
| 4673 | } | ||
| 4674 | } | ||
| 4675 | |||
| 4676 | xfer_cnt = le32_to_cpu(mpi_reply->TransferCount); | ||
| 4677 | scsi_set_resid(scmd, scsi_bufflen(scmd) - xfer_cnt); | ||
| 4678 | if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) | ||
| 4679 | log_info = le32_to_cpu(mpi_reply->IOCLogInfo); | ||
| 4680 | else | ||
| 4681 | log_info = 0; | ||
| 4682 | ioc_status &= MPI2_IOCSTATUS_MASK; | ||
| 4683 | scsi_status = mpi_reply->SCSIStatus; | ||
| 4684 | |||
| 4685 | if (ioc_status == MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 && | ||
| 4686 | (scsi_status == MPI2_SCSI_STATUS_BUSY || | ||
| 4687 | scsi_status == MPI2_SCSI_STATUS_RESERVATION_CONFLICT || | ||
| 4688 | scsi_status == MPI2_SCSI_STATUS_TASK_SET_FULL)) { | ||
| 4689 | ioc_status = MPI2_IOCSTATUS_SUCCESS; | ||
| 4690 | } | ||
| 4691 | |||
| 4692 | if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) { | ||
| 4693 | struct sense_info data; | ||
| 4694 | const void *sense_data = mpt2sas_base_get_sense_buffer(ioc, | ||
| 4695 | smid); | ||
| 4696 | u32 sz = min_t(u32, SCSI_SENSE_BUFFERSIZE, | ||
| 4697 | le32_to_cpu(mpi_reply->SenseCount)); | ||
| 4698 | memcpy(scmd->sense_buffer, sense_data, sz); | ||
| 4699 | _scsih_normalize_sense(scmd->sense_buffer, &data); | ||
| 4700 | /* failure prediction threshold exceeded */ | ||
| 4701 | if (data.asc == 0x5D) | ||
| 4702 | _scsih_smart_predicted_fault(ioc, | ||
| 4703 | le16_to_cpu(mpi_reply->DevHandle)); | ||
| 4704 | } | ||
| 4705 | |||
| 4706 | switch (ioc_status) { | ||
| 4707 | case MPI2_IOCSTATUS_BUSY: | ||
| 4708 | case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES: | ||
| 4709 | scmd->result = SAM_STAT_BUSY; | ||
| 4710 | break; | ||
| 4711 | |||
| 4712 | case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE: | ||
| 4713 | scmd->result = DID_NO_CONNECT << 16; | ||
| 4714 | break; | ||
| 4715 | |||
| 4716 | case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED: | ||
| 4717 | if (sas_device_priv_data->block) { | ||
| 4718 | scmd->result = DID_TRANSPORT_DISRUPTED << 16; | ||
| 4719 | goto out; | ||
| 4720 | } | ||
| 4721 | if (log_info == 0x32010081) { | ||
| 4722 | scmd->result = DID_RESET << 16; | ||
| 4723 | break; | ||
| 4724 | } | ||
| 4725 | scmd->result = DID_SOFT_ERROR << 16; | ||
| 4726 | break; | ||
| 4727 | case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED: | ||
| 4728 | case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED: | ||
| 4729 | scmd->result = DID_RESET << 16; | ||
| 4730 | break; | ||
| 4731 | |||
| 4732 | case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: | ||
| 4733 | if ((xfer_cnt == 0) || (scmd->underflow > xfer_cnt)) | ||
| 4734 | scmd->result = DID_SOFT_ERROR << 16; | ||
| 4735 | else | ||
| 4736 | scmd->result = (DID_OK << 16) | scsi_status; | ||
| 4737 | break; | ||
| 4738 | |||
| 4739 | case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN: | ||
| 4740 | scmd->result = (DID_OK << 16) | scsi_status; | ||
| 4741 | |||
| 4742 | if ((scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID)) | ||
| 4743 | break; | ||
| 4744 | |||
| 4745 | if (xfer_cnt < scmd->underflow) { | ||
| 4746 | if (scsi_status == SAM_STAT_BUSY) | ||
| 4747 | scmd->result = SAM_STAT_BUSY; | ||
| 4748 | else | ||
| 4749 | scmd->result = DID_SOFT_ERROR << 16; | ||
| 4750 | } else if (scsi_state & (MPI2_SCSI_STATE_AUTOSENSE_FAILED | | ||
| 4751 | MPI2_SCSI_STATE_NO_SCSI_STATUS)) | ||
| 4752 | scmd->result = DID_SOFT_ERROR << 16; | ||
| 4753 | else if (scsi_state & MPI2_SCSI_STATE_TERMINATED) | ||
| 4754 | scmd->result = DID_RESET << 16; | ||
| 4755 | else if (!xfer_cnt && scmd->cmnd[0] == REPORT_LUNS) { | ||
| 4756 | mpi_reply->SCSIState = MPI2_SCSI_STATE_AUTOSENSE_VALID; | ||
| 4757 | mpi_reply->SCSIStatus = SAM_STAT_CHECK_CONDITION; | ||
| 4758 | scmd->result = (DRIVER_SENSE << 24) | | ||
| 4759 | SAM_STAT_CHECK_CONDITION; | ||
| 4760 | scmd->sense_buffer[0] = 0x70; | ||
| 4761 | scmd->sense_buffer[2] = ILLEGAL_REQUEST; | ||
| 4762 | scmd->sense_buffer[12] = 0x20; | ||
| 4763 | scmd->sense_buffer[13] = 0; | ||
| 4764 | } | ||
| 4765 | break; | ||
| 4766 | |||
| 4767 | case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN: | ||
| 4768 | scsi_set_resid(scmd, 0); | ||
| 4769 | case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR: | ||
| 4770 | case MPI2_IOCSTATUS_SUCCESS: | ||
| 4771 | scmd->result = (DID_OK << 16) | scsi_status; | ||
| 4772 | if (response_code == | ||
| 4773 | MPI2_SCSITASKMGMT_RSP_INVALID_FRAME || | ||
| 4774 | (scsi_state & (MPI2_SCSI_STATE_AUTOSENSE_FAILED | | ||
| 4775 | MPI2_SCSI_STATE_NO_SCSI_STATUS))) | ||
| 4776 | scmd->result = DID_SOFT_ERROR << 16; | ||
| 4777 | else if (scsi_state & MPI2_SCSI_STATE_TERMINATED) | ||
| 4778 | scmd->result = DID_RESET << 16; | ||
| 4779 | break; | ||
| 4780 | |||
| 4781 | case MPI2_IOCSTATUS_EEDP_GUARD_ERROR: | ||
| 4782 | case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR: | ||
| 4783 | case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR: | ||
| 4784 | _scsih_eedp_error_handling(scmd, ioc_status); | ||
| 4785 | break; | ||
| 4786 | case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR: | ||
| 4787 | case MPI2_IOCSTATUS_INVALID_FUNCTION: | ||
| 4788 | case MPI2_IOCSTATUS_INVALID_SGL: | ||
| 4789 | case MPI2_IOCSTATUS_INTERNAL_ERROR: | ||
| 4790 | case MPI2_IOCSTATUS_INVALID_FIELD: | ||
| 4791 | case MPI2_IOCSTATUS_INVALID_STATE: | ||
| 4792 | case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR: | ||
| 4793 | case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED: | ||
| 4794 | default: | ||
| 4795 | scmd->result = DID_SOFT_ERROR << 16; | ||
| 4796 | break; | ||
| 4797 | |||
| 4798 | } | ||
| 4799 | |||
| 4800 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | ||
| 4801 | if (scmd->result && (ioc->logging_level & MPT_DEBUG_REPLY)) | ||
| 4802 | _scsih_scsi_ioc_info(ioc , scmd, mpi_reply, smid); | ||
| 4803 | #endif | ||
| 4804 | |||
| 4805 | out: | ||
| 4806 | scsi_dma_unmap(scmd); | ||
| 4807 | scmd->scsi_done(scmd); | ||
| 4808 | return 1; | ||
| 4809 | } | ||
| 4810 | |||
| 4811 | /** | ||
| 4812 | * _scsih_sas_host_refresh - refreshing sas host object contents | ||
| 4813 | * @ioc: per adapter object | ||
| 4814 | * Context: user | ||
| 4815 | * | ||
| 4816 | * During port enable, fw will send topology events for every device. Its | ||
| 4817 | * possible that the handles may change from the previous setting, so this | ||
| 4818 | * code keeping handles updating if changed. | ||
| 4819 | * | ||
| 4820 | * Return nothing. | ||
| 4821 | */ | ||
| 4822 | static void | ||
| 4823 | _scsih_sas_host_refresh(struct MPT2SAS_ADAPTER *ioc) | ||
| 4824 | { | ||
| 4825 | u16 sz; | ||
| 4826 | u16 ioc_status; | ||
| 4827 | int i; | ||
| 4828 | Mpi2ConfigReply_t mpi_reply; | ||
| 4829 | Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL; | ||
| 4830 | u16 attached_handle; | ||
| 4831 | u8 link_rate; | ||
| 4832 | |||
| 4833 | dtmprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 4834 | "updating handles for sas_host(0x%016llx)\n", | ||
| 4835 | ioc->name, (unsigned long long)ioc->sas_hba.sas_address)); | ||
| 4836 | |||
| 4837 | sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys | ||
| 4838 | * sizeof(Mpi2SasIOUnit0PhyData_t)); | ||
| 4839 | sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL); | ||
| 4840 | if (!sas_iounit_pg0) { | ||
| 4841 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 4842 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 4843 | return; | ||
| 4844 | } | ||
| 4845 | |||
| 4846 | if ((mpt2sas_config_get_sas_iounit_pg0(ioc, &mpi_reply, | ||
| 4847 | sas_iounit_pg0, sz)) != 0) | ||
| 4848 | goto out; | ||
| 4849 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; | ||
| 4850 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) | ||
| 4851 | goto out; | ||
| 4852 | for (i = 0; i < ioc->sas_hba.num_phys ; i++) { | ||
| 4853 | link_rate = sas_iounit_pg0->PhyData[i].NegotiatedLinkRate >> 4; | ||
| 4854 | if (i == 0) | ||
| 4855 | ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0-> | ||
| 4856 | PhyData[0].ControllerDevHandle); | ||
| 4857 | ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle; | ||
| 4858 | attached_handle = le16_to_cpu(sas_iounit_pg0->PhyData[i]. | ||
| 4859 | AttachedDevHandle); | ||
| 4860 | if (attached_handle && link_rate < MPI2_SAS_NEG_LINK_RATE_1_5) | ||
| 4861 | link_rate = MPI2_SAS_NEG_LINK_RATE_1_5; | ||
| 4862 | mpt2sas_transport_update_links(ioc, ioc->sas_hba.sas_address, | ||
| 4863 | attached_handle, i, link_rate); | ||
| 4864 | } | ||
| 4865 | out: | ||
| 4866 | kfree(sas_iounit_pg0); | ||
| 4867 | } | ||
| 4868 | |||
| 4869 | /** | ||
| 4870 | * _scsih_sas_host_add - create sas host object | ||
| 4871 | * @ioc: per adapter object | ||
| 4872 | * | ||
| 4873 | * Creating host side data object, stored in ioc->sas_hba | ||
| 4874 | * | ||
| 4875 | * Return nothing. | ||
| 4876 | */ | ||
| 4877 | static void | ||
| 4878 | _scsih_sas_host_add(struct MPT2SAS_ADAPTER *ioc) | ||
| 4879 | { | ||
| 4880 | int i; | ||
| 4881 | Mpi2ConfigReply_t mpi_reply; | ||
| 4882 | Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL; | ||
| 4883 | Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL; | ||
| 4884 | Mpi2SasPhyPage0_t phy_pg0; | ||
| 4885 | Mpi2SasDevicePage0_t sas_device_pg0; | ||
| 4886 | Mpi2SasEnclosurePage0_t enclosure_pg0; | ||
| 4887 | u16 ioc_status; | ||
| 4888 | u16 sz; | ||
| 4889 | u16 device_missing_delay; | ||
| 4890 | |||
| 4891 | mpt2sas_config_get_number_hba_phys(ioc, &ioc->sas_hba.num_phys); | ||
| 4892 | if (!ioc->sas_hba.num_phys) { | ||
| 4893 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 4894 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 4895 | return; | ||
| 4896 | } | ||
| 4897 | |||
| 4898 | /* sas_iounit page 0 */ | ||
| 4899 | sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys * | ||
| 4900 | sizeof(Mpi2SasIOUnit0PhyData_t)); | ||
| 4901 | sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL); | ||
| 4902 | if (!sas_iounit_pg0) { | ||
| 4903 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 4904 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 4905 | return; | ||
| 4906 | } | ||
| 4907 | if ((mpt2sas_config_get_sas_iounit_pg0(ioc, &mpi_reply, | ||
| 4908 | sas_iounit_pg0, sz))) { | ||
| 4909 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 4910 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 4911 | goto out; | ||
| 4912 | } | ||
| 4913 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
| 4914 | MPI2_IOCSTATUS_MASK; | ||
| 4915 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { | ||
| 4916 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 4917 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 4918 | goto out; | ||
| 4919 | } | ||
| 4920 | |||
| 4921 | /* sas_iounit page 1 */ | ||
| 4922 | sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys * | ||
| 4923 | sizeof(Mpi2SasIOUnit1PhyData_t)); | ||
| 4924 | sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL); | ||
| 4925 | if (!sas_iounit_pg1) { | ||
| 4926 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 4927 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 4928 | goto out; | ||
| 4929 | } | ||
| 4930 | if ((mpt2sas_config_get_sas_iounit_pg1(ioc, &mpi_reply, | ||
| 4931 | sas_iounit_pg1, sz))) { | ||
| 4932 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 4933 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 4934 | goto out; | ||
| 4935 | } | ||
| 4936 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
| 4937 | MPI2_IOCSTATUS_MASK; | ||
| 4938 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { | ||
| 4939 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 4940 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 4941 | goto out; | ||
| 4942 | } | ||
| 4943 | |||
| 4944 | ioc->io_missing_delay = | ||
| 4945 | le16_to_cpu(sas_iounit_pg1->IODeviceMissingDelay); | ||
| 4946 | device_missing_delay = | ||
| 4947 | le16_to_cpu(sas_iounit_pg1->ReportDeviceMissingDelay); | ||
| 4948 | if (device_missing_delay & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16) | ||
| 4949 | ioc->device_missing_delay = (device_missing_delay & | ||
| 4950 | MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16; | ||
| 4951 | else | ||
| 4952 | ioc->device_missing_delay = device_missing_delay & | ||
| 4953 | MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK; | ||
| 4954 | |||
| 4955 | ioc->sas_hba.parent_dev = &ioc->shost->shost_gendev; | ||
| 4956 | ioc->sas_hba.phy = kcalloc(ioc->sas_hba.num_phys, | ||
| 4957 | sizeof(struct _sas_phy), GFP_KERNEL); | ||
| 4958 | if (!ioc->sas_hba.phy) { | ||
| 4959 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 4960 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 4961 | goto out; | ||
| 4962 | } | ||
| 4963 | for (i = 0; i < ioc->sas_hba.num_phys ; i++) { | ||
| 4964 | if ((mpt2sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0, | ||
| 4965 | i))) { | ||
| 4966 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 4967 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 4968 | goto out; | ||
| 4969 | } | ||
| 4970 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
| 4971 | MPI2_IOCSTATUS_MASK; | ||
| 4972 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { | ||
| 4973 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 4974 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 4975 | goto out; | ||
| 4976 | } | ||
| 4977 | |||
| 4978 | if (i == 0) | ||
| 4979 | ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0-> | ||
| 4980 | PhyData[0].ControllerDevHandle); | ||
| 4981 | ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle; | ||
| 4982 | ioc->sas_hba.phy[i].phy_id = i; | ||
| 4983 | mpt2sas_transport_add_host_phy(ioc, &ioc->sas_hba.phy[i], | ||
| 4984 | phy_pg0, ioc->sas_hba.parent_dev); | ||
| 4985 | } | ||
| 4986 | if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, | ||
| 4987 | MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, ioc->sas_hba.handle))) { | ||
| 4988 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 4989 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 4990 | goto out; | ||
| 4991 | } | ||
| 4992 | ioc->sas_hba.enclosure_handle = | ||
| 4993 | le16_to_cpu(sas_device_pg0.EnclosureHandle); | ||
| 4994 | ioc->sas_hba.sas_address = le64_to_cpu(sas_device_pg0.SASAddress); | ||
| 4995 | printk(MPT2SAS_INFO_FMT "host_add: handle(0x%04x), " | ||
| 4996 | "sas_addr(0x%016llx), phys(%d)\n", ioc->name, ioc->sas_hba.handle, | ||
| 4997 | (unsigned long long) ioc->sas_hba.sas_address, | ||
| 4998 | ioc->sas_hba.num_phys) ; | ||
| 4999 | |||
| 5000 | if (ioc->sas_hba.enclosure_handle) { | ||
| 5001 | if (!(mpt2sas_config_get_enclosure_pg0(ioc, &mpi_reply, | ||
| 5002 | &enclosure_pg0, | ||
| 5003 | MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE, | ||
| 5004 | ioc->sas_hba.enclosure_handle))) { | ||
| 5005 | ioc->sas_hba.enclosure_logical_id = | ||
| 5006 | le64_to_cpu(enclosure_pg0.EnclosureLogicalID); | ||
| 5007 | } | ||
| 5008 | } | ||
| 5009 | |||
| 5010 | out: | ||
| 5011 | kfree(sas_iounit_pg1); | ||
| 5012 | kfree(sas_iounit_pg0); | ||
| 5013 | } | ||
| 5014 | |||
| 5015 | /** | ||
| 5016 | * _scsih_expander_add - creating expander object | ||
| 5017 | * @ioc: per adapter object | ||
| 5018 | * @handle: expander handle | ||
| 5019 | * | ||
| 5020 | * Creating expander object, stored in ioc->sas_expander_list. | ||
| 5021 | * | ||
| 5022 | * Return 0 for success, else error. | ||
| 5023 | */ | ||
| 5024 | static int | ||
| 5025 | _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle) | ||
| 5026 | { | ||
| 5027 | struct _sas_node *sas_expander; | ||
| 5028 | Mpi2ConfigReply_t mpi_reply; | ||
| 5029 | Mpi2ExpanderPage0_t expander_pg0; | ||
| 5030 | Mpi2ExpanderPage1_t expander_pg1; | ||
| 5031 | Mpi2SasEnclosurePage0_t enclosure_pg0; | ||
| 5032 | u32 ioc_status; | ||
| 5033 | u16 parent_handle; | ||
| 5034 | u64 sas_address, sas_address_parent = 0; | ||
| 5035 | int i; | ||
| 5036 | unsigned long flags; | ||
| 5037 | struct _sas_port *mpt2sas_port = NULL; | ||
| 5038 | int rc = 0; | ||
| 5039 | |||
| 5040 | if (!handle) | ||
| 5041 | return -1; | ||
| 5042 | |||
| 5043 | if (ioc->shost_recovery || ioc->pci_error_recovery) | ||
| 5044 | return -1; | ||
| 5045 | |||
| 5046 | if ((mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0, | ||
| 5047 | MPI2_SAS_EXPAND_PGAD_FORM_HNDL, handle))) { | ||
| 5048 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 5049 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 5050 | return -1; | ||
| 5051 | } | ||
| 5052 | |||
| 5053 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
| 5054 | MPI2_IOCSTATUS_MASK; | ||
| 5055 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { | ||
| 5056 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 5057 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 5058 | return -1; | ||
| 5059 | } | ||
| 5060 | |||
| 5061 | /* handle out of order topology events */ | ||
| 5062 | parent_handle = le16_to_cpu(expander_pg0.ParentDevHandle); | ||
| 5063 | if (_scsih_get_sas_address(ioc, parent_handle, &sas_address_parent) | ||
| 5064 | != 0) { | ||
| 5065 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 5066 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 5067 | return -1; | ||
| 5068 | } | ||
| 5069 | if (sas_address_parent != ioc->sas_hba.sas_address) { | ||
| 5070 | spin_lock_irqsave(&ioc->sas_node_lock, flags); | ||
| 5071 | sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc, | ||
| 5072 | sas_address_parent); | ||
| 5073 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | ||
| 5074 | if (!sas_expander) { | ||
| 5075 | rc = _scsih_expander_add(ioc, parent_handle); | ||
| 5076 | if (rc != 0) | ||
| 5077 | return rc; | ||
| 5078 | } | ||
| 5079 | } | ||
| 5080 | |||
| 5081 | spin_lock_irqsave(&ioc->sas_node_lock, flags); | ||
| 5082 | sas_address = le64_to_cpu(expander_pg0.SASAddress); | ||
| 5083 | sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc, | ||
| 5084 | sas_address); | ||
| 5085 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | ||
| 5086 | |||
| 5087 | if (sas_expander) | ||
| 5088 | return 0; | ||
| 5089 | |||
| 5090 | sas_expander = kzalloc(sizeof(struct _sas_node), | ||
| 5091 | GFP_KERNEL); | ||
| 5092 | if (!sas_expander) { | ||
| 5093 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 5094 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 5095 | return -1; | ||
| 5096 | } | ||
| 5097 | |||
| 5098 | sas_expander->handle = handle; | ||
| 5099 | sas_expander->num_phys = expander_pg0.NumPhys; | ||
| 5100 | sas_expander->sas_address_parent = sas_address_parent; | ||
| 5101 | sas_expander->sas_address = sas_address; | ||
| 5102 | |||
| 5103 | printk(MPT2SAS_INFO_FMT "expander_add: handle(0x%04x)," | ||
| 5104 | " parent(0x%04x), sas_addr(0x%016llx), phys(%d)\n", ioc->name, | ||
| 5105 | handle, parent_handle, (unsigned long long) | ||
| 5106 | sas_expander->sas_address, sas_expander->num_phys); | ||
| 5107 | |||
| 5108 | if (!sas_expander->num_phys) | ||
| 5109 | goto out_fail; | ||
| 5110 | sas_expander->phy = kcalloc(sas_expander->num_phys, | ||
| 5111 | sizeof(struct _sas_phy), GFP_KERNEL); | ||
| 5112 | if (!sas_expander->phy) { | ||
| 5113 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 5114 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 5115 | rc = -1; | ||
| 5116 | goto out_fail; | ||
| 5117 | } | ||
| 5118 | |||
| 5119 | INIT_LIST_HEAD(&sas_expander->sas_port_list); | ||
| 5120 | mpt2sas_port = mpt2sas_transport_port_add(ioc, handle, | ||
| 5121 | sas_address_parent); | ||
| 5122 | if (!mpt2sas_port) { | ||
| 5123 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 5124 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 5125 | rc = -1; | ||
| 5126 | goto out_fail; | ||
| 5127 | } | ||
| 5128 | sas_expander->parent_dev = &mpt2sas_port->rphy->dev; | ||
| 5129 | |||
| 5130 | for (i = 0 ; i < sas_expander->num_phys ; i++) { | ||
| 5131 | if ((mpt2sas_config_get_expander_pg1(ioc, &mpi_reply, | ||
| 5132 | &expander_pg1, i, handle))) { | ||
| 5133 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 5134 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 5135 | rc = -1; | ||
| 5136 | goto out_fail; | ||
| 5137 | } | ||
| 5138 | sas_expander->phy[i].handle = handle; | ||
| 5139 | sas_expander->phy[i].phy_id = i; | ||
| 5140 | |||
| 5141 | if ((mpt2sas_transport_add_expander_phy(ioc, | ||
| 5142 | &sas_expander->phy[i], expander_pg1, | ||
| 5143 | sas_expander->parent_dev))) { | ||
| 5144 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 5145 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 5146 | rc = -1; | ||
| 5147 | goto out_fail; | ||
| 5148 | } | ||
| 5149 | } | ||
| 5150 | |||
| 5151 | if (sas_expander->enclosure_handle) { | ||
| 5152 | if (!(mpt2sas_config_get_enclosure_pg0(ioc, &mpi_reply, | ||
| 5153 | &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE, | ||
| 5154 | sas_expander->enclosure_handle))) { | ||
| 5155 | sas_expander->enclosure_logical_id = | ||
| 5156 | le64_to_cpu(enclosure_pg0.EnclosureLogicalID); | ||
| 5157 | } | ||
| 5158 | } | ||
| 5159 | |||
| 5160 | _scsih_expander_node_add(ioc, sas_expander); | ||
| 5161 | return 0; | ||
| 5162 | |||
| 5163 | out_fail: | ||
| 5164 | |||
| 5165 | if (mpt2sas_port) | ||
| 5166 | mpt2sas_transport_port_remove(ioc, sas_expander->sas_address, | ||
| 5167 | sas_address_parent); | ||
| 5168 | kfree(sas_expander); | ||
| 5169 | return rc; | ||
| 5170 | } | ||
| 5171 | |||
| 5172 | /** | ||
| 5173 | * _scsih_done - scsih callback handler. | ||
| 5174 | * @ioc: per adapter object | ||
| 5175 | * @smid: system request message index | ||
| 5176 | * @msix_index: MSIX table index supplied by the OS | ||
| 5177 | * @reply: reply message frame(lower 32bit addr) | ||
| 5178 | * | ||
| 5179 | * Callback handler when sending internal generated message frames. | ||
| 5180 | * The callback index passed is `ioc->scsih_cb_idx` | ||
| 5181 | * | ||
| 5182 | * Return 1 meaning mf should be freed from _base_interrupt | ||
| 5183 | * 0 means the mf is freed from this function. | ||
| 5184 | */ | ||
| 5185 | static u8 | ||
| 5186 | _scsih_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) | ||
| 5187 | { | ||
| 5188 | MPI2DefaultReply_t *mpi_reply; | ||
| 5189 | |||
| 5190 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | ||
| 5191 | if (ioc->scsih_cmds.status == MPT2_CMD_NOT_USED) | ||
| 5192 | return 1; | ||
| 5193 | if (ioc->scsih_cmds.smid != smid) | ||
| 5194 | return 1; | ||
| 5195 | ioc->scsih_cmds.status |= MPT2_CMD_COMPLETE; | ||
| 5196 | if (mpi_reply) { | ||
| 5197 | memcpy(ioc->scsih_cmds.reply, mpi_reply, | ||
| 5198 | mpi_reply->MsgLength*4); | ||
| 5199 | ioc->scsih_cmds.status |= MPT2_CMD_REPLY_VALID; | ||
| 5200 | } | ||
| 5201 | ioc->scsih_cmds.status &= ~MPT2_CMD_PENDING; | ||
| 5202 | complete(&ioc->scsih_cmds.done); | ||
| 5203 | return 1; | ||
| 5204 | } | ||
| 5205 | |||
| 5206 | /** | ||
| 5207 | * mpt2sas_expander_remove - removing expander object | ||
| 5208 | * @ioc: per adapter object | ||
| 5209 | * @sas_address: expander sas_address | ||
| 5210 | * | ||
| 5211 | * Return nothing. | ||
| 5212 | */ | ||
| 5213 | void | ||
| 5214 | mpt2sas_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address) | ||
| 5215 | { | ||
| 5216 | struct _sas_node *sas_expander; | ||
| 5217 | unsigned long flags; | ||
| 5218 | |||
| 5219 | if (ioc->shost_recovery) | ||
| 5220 | return; | ||
| 5221 | |||
| 5222 | spin_lock_irqsave(&ioc->sas_node_lock, flags); | ||
| 5223 | sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc, | ||
| 5224 | sas_address); | ||
| 5225 | if (sas_expander) | ||
| 5226 | list_del(&sas_expander->list); | ||
| 5227 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | ||
| 5228 | if (sas_expander) | ||
| 5229 | _scsih_expander_node_remove(ioc, sas_expander); | ||
| 5230 | } | ||
| 5231 | |||
| 5232 | /** | ||
| 5233 | * _scsih_check_access_status - check access flags | ||
| 5234 | * @ioc: per adapter object | ||
| 5235 | * @sas_address: sas address | ||
| 5236 | * @handle: sas device handle | ||
| 5237 | * @access_flags: errors returned during discovery of the device | ||
| 5238 | * | ||
| 5239 | * Return 0 for success, else failure | ||
| 5240 | */ | ||
| 5241 | static u8 | ||
| 5242 | _scsih_check_access_status(struct MPT2SAS_ADAPTER *ioc, u64 sas_address, | ||
| 5243 | u16 handle, u8 access_status) | ||
| 5244 | { | ||
| 5245 | u8 rc = 1; | ||
| 5246 | char *desc = NULL; | ||
| 5247 | |||
| 5248 | switch (access_status) { | ||
| 5249 | case MPI2_SAS_DEVICE0_ASTATUS_NO_ERRORS: | ||
| 5250 | case MPI2_SAS_DEVICE0_ASTATUS_SATA_NEEDS_INITIALIZATION: | ||
| 5251 | rc = 0; | ||
| 5252 | break; | ||
| 5253 | case MPI2_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED: | ||
| 5254 | desc = "sata capability failed"; | ||
| 5255 | break; | ||
| 5256 | case MPI2_SAS_DEVICE0_ASTATUS_SATA_AFFILIATION_CONFLICT: | ||
| 5257 | desc = "sata affiliation conflict"; | ||
| 5258 | break; | ||
| 5259 | case MPI2_SAS_DEVICE0_ASTATUS_ROUTE_NOT_ADDRESSABLE: | ||
| 5260 | desc = "route not addressable"; | ||
| 5261 | break; | ||
| 5262 | case MPI2_SAS_DEVICE0_ASTATUS_SMP_ERROR_NOT_ADDRESSABLE: | ||
| 5263 | desc = "smp error not addressable"; | ||
| 5264 | break; | ||
| 5265 | case MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED: | ||
| 5266 | desc = "device blocked"; | ||
| 5267 | break; | ||
| 5268 | case MPI2_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED: | ||
| 5269 | case MPI2_SAS_DEVICE0_ASTATUS_SIF_UNKNOWN: | ||
| 5270 | case MPI2_SAS_DEVICE0_ASTATUS_SIF_AFFILIATION_CONFLICT: | ||
| 5271 | case MPI2_SAS_DEVICE0_ASTATUS_SIF_DIAG: | ||
| 5272 | case MPI2_SAS_DEVICE0_ASTATUS_SIF_IDENTIFICATION: | ||
| 5273 | case MPI2_SAS_DEVICE0_ASTATUS_SIF_CHECK_POWER: | ||
| 5274 | case MPI2_SAS_DEVICE0_ASTATUS_SIF_PIO_SN: | ||
| 5275 | case MPI2_SAS_DEVICE0_ASTATUS_SIF_MDMA_SN: | ||
| 5276 | case MPI2_SAS_DEVICE0_ASTATUS_SIF_UDMA_SN: | ||
| 5277 | case MPI2_SAS_DEVICE0_ASTATUS_SIF_ZONING_VIOLATION: | ||
| 5278 | case MPI2_SAS_DEVICE0_ASTATUS_SIF_NOT_ADDRESSABLE: | ||
| 5279 | case MPI2_SAS_DEVICE0_ASTATUS_SIF_MAX: | ||
| 5280 | desc = "sata initialization failed"; | ||
| 5281 | break; | ||
| 5282 | default: | ||
| 5283 | desc = "unknown"; | ||
| 5284 | break; | ||
| 5285 | } | ||
| 5286 | |||
| 5287 | if (!rc) | ||
| 5288 | return 0; | ||
| 5289 | |||
| 5290 | printk(MPT2SAS_ERR_FMT "discovery errors(%s): sas_address(0x%016llx), " | ||
| 5291 | "handle(0x%04x)\n", ioc->name, desc, | ||
| 5292 | (unsigned long long)sas_address, handle); | ||
| 5293 | return rc; | ||
| 5294 | } | ||
| 5295 | |||
| 5296 | static void | ||
| 5297 | _scsih_check_device(struct MPT2SAS_ADAPTER *ioc, u16 handle) | ||
| 5298 | { | ||
| 5299 | Mpi2ConfigReply_t mpi_reply; | ||
| 5300 | Mpi2SasDevicePage0_t sas_device_pg0; | ||
| 5301 | struct _sas_device *sas_device; | ||
| 5302 | u32 ioc_status; | ||
| 5303 | unsigned long flags; | ||
| 5304 | u64 sas_address; | ||
| 5305 | struct scsi_target *starget; | ||
| 5306 | struct MPT2SAS_TARGET *sas_target_priv_data; | ||
| 5307 | u32 device_info; | ||
| 5308 | |||
| 5309 | |||
| 5310 | if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, | ||
| 5311 | MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) | ||
| 5312 | return; | ||
| 5313 | |||
| 5314 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; | ||
| 5315 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) | ||
| 5316 | return; | ||
| 5317 | |||
| 5318 | /* check if this is end device */ | ||
| 5319 | device_info = le32_to_cpu(sas_device_pg0.DeviceInfo); | ||
| 5320 | if (!(_scsih_is_end_device(device_info))) | ||
| 5321 | return; | ||
| 5322 | |||
| 5323 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 5324 | sas_address = le64_to_cpu(sas_device_pg0.SASAddress); | ||
| 5325 | sas_device = __mpt2sas_get_sdev_by_addr(ioc, | ||
| 5326 | sas_address); | ||
| 5327 | |||
| 5328 | if (!sas_device) { | ||
| 5329 | printk(MPT2SAS_ERR_FMT "device is not present " | ||
| 5330 | "handle(0x%04x), no sas_device!!!\n", ioc->name, handle); | ||
| 5331 | goto out_unlock; | ||
| 5332 | } | ||
| 5333 | |||
| 5334 | if (unlikely(sas_device->handle != handle)) { | ||
| 5335 | starget = sas_device->starget; | ||
| 5336 | sas_target_priv_data = starget->hostdata; | ||
| 5337 | starget_printk(KERN_INFO, starget, "handle changed from(0x%04x)" | ||
| 5338 | " to (0x%04x)!!!\n", sas_device->handle, handle); | ||
| 5339 | sas_target_priv_data->handle = handle; | ||
| 5340 | sas_device->handle = handle; | ||
| 5341 | } | ||
| 5342 | |||
| 5343 | /* check if device is present */ | ||
| 5344 | if (!(le16_to_cpu(sas_device_pg0.Flags) & | ||
| 5345 | MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)) { | ||
| 5346 | printk(MPT2SAS_ERR_FMT "device is not present " | ||
| 5347 | "handle(0x%04x), flags!!!\n", ioc->name, handle); | ||
| 5348 | goto out_unlock; | ||
| 5349 | } | ||
| 5350 | |||
| 5351 | /* check if there were any issues with discovery */ | ||
| 5352 | if (_scsih_check_access_status(ioc, sas_address, handle, | ||
| 5353 | sas_device_pg0.AccessStatus)) | ||
| 5354 | goto out_unlock; | ||
| 5355 | |||
| 5356 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 5357 | _scsih_ublock_io_device(ioc, sas_address); | ||
| 5358 | if (sas_device) | ||
| 5359 | sas_device_put(sas_device); | ||
| 5360 | return; | ||
| 5361 | |||
| 5362 | out_unlock: | ||
| 5363 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 5364 | if (sas_device) | ||
| 5365 | sas_device_put(sas_device); | ||
| 5366 | } | ||
| 5367 | |||
| 5368 | /** | ||
| 5369 | * _scsih_add_device - creating sas device object | ||
| 5370 | * @ioc: per adapter object | ||
| 5371 | * @handle: sas device handle | ||
| 5372 | * @phy_num: phy number end device attached to | ||
| 5373 | * @is_pd: is this hidden raid component | ||
| 5374 | * | ||
| 5375 | * Creating end device object, stored in ioc->sas_device_list. | ||
| 5376 | * | ||
| 5377 | * Returns 0 for success, non-zero for failure. | ||
| 5378 | */ | ||
| 5379 | static int | ||
| 5380 | _scsih_add_device(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 phy_num, u8 is_pd) | ||
| 5381 | { | ||
| 5382 | Mpi2ConfigReply_t mpi_reply; | ||
| 5383 | Mpi2SasDevicePage0_t sas_device_pg0; | ||
| 5384 | Mpi2SasEnclosurePage0_t enclosure_pg0; | ||
| 5385 | struct _sas_device *sas_device; | ||
| 5386 | u32 ioc_status; | ||
| 5387 | __le64 sas_address; | ||
| 5388 | u32 device_info; | ||
| 5389 | |||
| 5390 | if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, | ||
| 5391 | MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { | ||
| 5392 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 5393 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 5394 | return -1; | ||
| 5395 | } | ||
| 5396 | |||
| 5397 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
| 5398 | MPI2_IOCSTATUS_MASK; | ||
| 5399 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { | ||
| 5400 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 5401 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 5402 | return -1; | ||
| 5403 | } | ||
| 5404 | |||
| 5405 | sas_address = le64_to_cpu(sas_device_pg0.SASAddress); | ||
| 5406 | |||
| 5407 | /* check if device is present */ | ||
| 5408 | if (!(le16_to_cpu(sas_device_pg0.Flags) & | ||
| 5409 | MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)) { | ||
| 5410 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 5411 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 5412 | printk(MPT2SAS_ERR_FMT "Flags = 0x%04x\n", | ||
| 5413 | ioc->name, le16_to_cpu(sas_device_pg0.Flags)); | ||
| 5414 | return -1; | ||
| 5415 | } | ||
| 5416 | |||
| 5417 | /* check if there were any issues with discovery */ | ||
| 5418 | if (_scsih_check_access_status(ioc, sas_address, handle, | ||
| 5419 | sas_device_pg0.AccessStatus)) | ||
| 5420 | return -1; | ||
| 5421 | |||
| 5422 | /* check if this is end device */ | ||
| 5423 | device_info = le32_to_cpu(sas_device_pg0.DeviceInfo); | ||
| 5424 | if (!(_scsih_is_end_device(device_info))) { | ||
| 5425 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 5426 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 5427 | return -1; | ||
| 5428 | } | ||
| 5429 | |||
| 5430 | sas_device = mpt2sas_get_sdev_by_addr(ioc, | ||
| 5431 | sas_address); | ||
| 5432 | |||
| 5433 | if (sas_device) { | ||
| 5434 | sas_device_put(sas_device); | ||
| 5435 | return 0; | ||
| 5436 | } | ||
| 5437 | |||
| 5438 | sas_device = kzalloc(sizeof(struct _sas_device), | ||
| 5439 | GFP_KERNEL); | ||
| 5440 | if (!sas_device) { | ||
| 5441 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 5442 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 5443 | return -1; | ||
| 5444 | } | ||
| 5445 | |||
| 5446 | kref_init(&sas_device->refcount); | ||
| 5447 | sas_device->handle = handle; | ||
| 5448 | if (_scsih_get_sas_address(ioc, le16_to_cpu | ||
| 5449 | (sas_device_pg0.ParentDevHandle), | ||
| 5450 | &sas_device->sas_address_parent) != 0) | ||
| 5451 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 5452 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 5453 | sas_device->enclosure_handle = | ||
| 5454 | le16_to_cpu(sas_device_pg0.EnclosureHandle); | ||
| 5455 | sas_device->slot = | ||
| 5456 | le16_to_cpu(sas_device_pg0.Slot); | ||
| 5457 | sas_device->device_info = device_info; | ||
| 5458 | sas_device->sas_address = sas_address; | ||
| 5459 | sas_device->phy = sas_device_pg0.PhyNum; | ||
| 5460 | |||
| 5461 | /* get enclosure_logical_id */ | ||
| 5462 | if (sas_device->enclosure_handle && !(mpt2sas_config_get_enclosure_pg0( | ||
| 5463 | ioc, &mpi_reply, &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE, | ||
| 5464 | sas_device->enclosure_handle))) | ||
| 5465 | sas_device->enclosure_logical_id = | ||
| 5466 | le64_to_cpu(enclosure_pg0.EnclosureLogicalID); | ||
| 5467 | |||
| 5468 | /* get device name */ | ||
| 5469 | sas_device->device_name = le64_to_cpu(sas_device_pg0.DeviceName); | ||
| 5470 | |||
| 5471 | if (ioc->wait_for_discovery_to_complete) | ||
| 5472 | _scsih_sas_device_init_add(ioc, sas_device); | ||
| 5473 | else | ||
| 5474 | _scsih_sas_device_add(ioc, sas_device); | ||
| 5475 | |||
| 5476 | sas_device_put(sas_device); | ||
| 5477 | return 0; | ||
| 5478 | } | ||
| 5479 | |||
| 5480 | /** | ||
| 5481 | * _scsih_remove_device - removing sas device object | ||
| 5482 | * @ioc: per adapter object | ||
| 5483 | * @sas_device_delete: the sas_device object | ||
| 5484 | * | ||
| 5485 | * Return nothing. | ||
| 5486 | */ | ||
| 5487 | static void | ||
| 5488 | _scsih_remove_device(struct MPT2SAS_ADAPTER *ioc, | ||
| 5489 | struct _sas_device *sas_device) | ||
| 5490 | { | ||
| 5491 | struct MPT2SAS_TARGET *sas_target_priv_data; | ||
| 5492 | |||
| 5493 | if ((ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM) && | ||
| 5494 | (sas_device->pfa_led_on)) { | ||
| 5495 | _scsih_turn_off_pfa_led(ioc, sas_device); | ||
| 5496 | sas_device->pfa_led_on = 0; | ||
| 5497 | } | ||
| 5498 | |||
| 5499 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter: " | ||
| 5500 | "handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__, | ||
| 5501 | sas_device->handle, (unsigned long long) | ||
| 5502 | sas_device->sas_address)); | ||
| 5503 | |||
| 5504 | if (sas_device->starget && sas_device->starget->hostdata) { | ||
| 5505 | sas_target_priv_data = sas_device->starget->hostdata; | ||
| 5506 | sas_target_priv_data->deleted = 1; | ||
| 5507 | _scsih_ublock_io_device(ioc, sas_device->sas_address); | ||
| 5508 | sas_target_priv_data->handle = | ||
| 5509 | MPT2SAS_INVALID_DEVICE_HANDLE; | ||
| 5510 | } | ||
| 5511 | |||
| 5512 | if (!ioc->hide_drives) | ||
| 5513 | mpt2sas_transport_port_remove(ioc, | ||
| 5514 | sas_device->sas_address, | ||
| 5515 | sas_device->sas_address_parent); | ||
| 5516 | |||
| 5517 | printk(MPT2SAS_INFO_FMT "removing handle(0x%04x), sas_addr" | ||
| 5518 | "(0x%016llx)\n", ioc->name, sas_device->handle, | ||
| 5519 | (unsigned long long) sas_device->sas_address); | ||
| 5520 | |||
| 5521 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: exit: " | ||
| 5522 | "handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__, | ||
| 5523 | sas_device->handle, (unsigned long long) | ||
| 5524 | sas_device->sas_address)); | ||
| 5525 | } | ||
| 5526 | /** | ||
| 5527 | * _scsih_device_remove_by_handle - removing device object by handle | ||
| 5528 | * @ioc: per adapter object | ||
| 5529 | * @handle: device handle | ||
| 5530 | * | ||
| 5531 | * Return nothing. | ||
| 5532 | */ | ||
| 5533 | static void | ||
| 5534 | _scsih_device_remove_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle) | ||
| 5535 | { | ||
| 5536 | struct _sas_device *sas_device; | ||
| 5537 | unsigned long flags; | ||
| 5538 | |||
| 5539 | if (ioc->shost_recovery) | ||
| 5540 | return; | ||
| 5541 | |||
| 5542 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 5543 | sas_device = __mpt2sas_get_sdev_by_handle(ioc, handle); | ||
| 5544 | if (sas_device) { | ||
| 5545 | list_del_init(&sas_device->list); | ||
| 5546 | sas_device_put(sas_device); | ||
| 5547 | } | ||
| 5548 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 5549 | |||
| 5550 | if (sas_device) { | ||
| 5551 | _scsih_remove_device(ioc, sas_device); | ||
| 5552 | sas_device_put(sas_device); | ||
| 5553 | } | ||
| 5554 | } | ||
| 5555 | |||
| 5556 | /** | ||
| 5557 | * mpt2sas_device_remove_by_sas_address - removing device object by sas address | ||
| 5558 | * @ioc: per adapter object | ||
| 5559 | * @sas_address: device sas_address | ||
| 5560 | * | ||
| 5561 | * Return nothing. | ||
| 5562 | */ | ||
| 5563 | void | ||
| 5564 | mpt2sas_device_remove_by_sas_address(struct MPT2SAS_ADAPTER *ioc, | ||
| 5565 | u64 sas_address) | ||
| 5566 | { | ||
| 5567 | struct _sas_device *sas_device; | ||
| 5568 | unsigned long flags; | ||
| 5569 | |||
| 5570 | if (ioc->shost_recovery) | ||
| 5571 | return; | ||
| 5572 | |||
| 5573 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 5574 | sas_device = __mpt2sas_get_sdev_by_addr(ioc, sas_address); | ||
| 5575 | if (sas_device) { | ||
| 5576 | list_del_init(&sas_device->list); | ||
| 5577 | sas_device_put(sas_device); | ||
| 5578 | } | ||
| 5579 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 5580 | |||
| 5581 | if (sas_device) { | ||
| 5582 | _scsih_remove_device(ioc, sas_device); | ||
| 5583 | sas_device_put(sas_device); | ||
| 5584 | } | ||
| 5585 | } | ||
| 5586 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | ||
| 5587 | /** | ||
| 5588 | * _scsih_sas_topology_change_event_debug - debug for topology event | ||
| 5589 | * @ioc: per adapter object | ||
| 5590 | * @event_data: event data payload | ||
| 5591 | * Context: user. | ||
| 5592 | */ | ||
| 5593 | static void | ||
| 5594 | _scsih_sas_topology_change_event_debug(struct MPT2SAS_ADAPTER *ioc, | ||
| 5595 | Mpi2EventDataSasTopologyChangeList_t *event_data) | ||
| 5596 | { | ||
| 5597 | int i; | ||
| 5598 | u16 handle; | ||
| 5599 | u16 reason_code; | ||
| 5600 | u8 phy_number; | ||
| 5601 | char *status_str = NULL; | ||
| 5602 | u8 link_rate, prev_link_rate; | ||
| 5603 | |||
| 5604 | switch (event_data->ExpStatus) { | ||
| 5605 | case MPI2_EVENT_SAS_TOPO_ES_ADDED: | ||
| 5606 | status_str = "add"; | ||
| 5607 | break; | ||
| 5608 | case MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING: | ||
| 5609 | status_str = "remove"; | ||
| 5610 | break; | ||
| 5611 | case MPI2_EVENT_SAS_TOPO_ES_RESPONDING: | ||
| 5612 | case 0: | ||
| 5613 | status_str = "responding"; | ||
| 5614 | break; | ||
| 5615 | case MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING: | ||
| 5616 | status_str = "remove delay"; | ||
| 5617 | break; | ||
| 5618 | default: | ||
| 5619 | status_str = "unknown status"; | ||
| 5620 | break; | ||
| 5621 | } | ||
| 5622 | printk(MPT2SAS_INFO_FMT "sas topology change: (%s)\n", | ||
| 5623 | ioc->name, status_str); | ||
| 5624 | printk(KERN_INFO "\thandle(0x%04x), enclosure_handle(0x%04x) " | ||
| 5625 | "start_phy(%02d), count(%d)\n", | ||
| 5626 | le16_to_cpu(event_data->ExpanderDevHandle), | ||
| 5627 | le16_to_cpu(event_data->EnclosureHandle), | ||
| 5628 | event_data->StartPhyNum, event_data->NumEntries); | ||
| 5629 | for (i = 0; i < event_data->NumEntries; i++) { | ||
| 5630 | handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle); | ||
| 5631 | if (!handle) | ||
| 5632 | continue; | ||
| 5633 | phy_number = event_data->StartPhyNum + i; | ||
| 5634 | reason_code = event_data->PHY[i].PhyStatus & | ||
| 5635 | MPI2_EVENT_SAS_TOPO_RC_MASK; | ||
| 5636 | switch (reason_code) { | ||
| 5637 | case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED: | ||
| 5638 | status_str = "target add"; | ||
| 5639 | break; | ||
| 5640 | case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING: | ||
| 5641 | status_str = "target remove"; | ||
| 5642 | break; | ||
| 5643 | case MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING: | ||
| 5644 | status_str = "delay target remove"; | ||
| 5645 | break; | ||
| 5646 | case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED: | ||
| 5647 | status_str = "link rate change"; | ||
| 5648 | break; | ||
| 5649 | case MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE: | ||
| 5650 | status_str = "target responding"; | ||
| 5651 | break; | ||
| 5652 | default: | ||
| 5653 | status_str = "unknown"; | ||
| 5654 | break; | ||
| 5655 | } | ||
| 5656 | link_rate = event_data->PHY[i].LinkRate >> 4; | ||
| 5657 | prev_link_rate = event_data->PHY[i].LinkRate & 0xF; | ||
| 5658 | printk(KERN_INFO "\tphy(%02d), attached_handle(0x%04x): %s:" | ||
| 5659 | " link rate: new(0x%02x), old(0x%02x)\n", phy_number, | ||
| 5660 | handle, status_str, link_rate, prev_link_rate); | ||
| 5661 | |||
| 5662 | } | ||
| 5663 | } | ||
| 5664 | #endif | ||
| 5665 | |||
| 5666 | /** | ||
| 5667 | * _scsih_sas_topology_change_event - handle topology changes | ||
| 5668 | * @ioc: per adapter object | ||
| 5669 | * @fw_event: The fw_event_work object | ||
| 5670 | * Context: user. | ||
| 5671 | * | ||
| 5672 | */ | ||
| 5673 | static void | ||
| 5674 | _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, | ||
| 5675 | struct fw_event_work *fw_event) | ||
| 5676 | { | ||
| 5677 | int i; | ||
| 5678 | u16 parent_handle, handle; | ||
| 5679 | u16 reason_code; | ||
| 5680 | u8 phy_number, max_phys; | ||
| 5681 | struct _sas_node *sas_expander; | ||
| 5682 | u64 sas_address; | ||
| 5683 | unsigned long flags; | ||
| 5684 | u8 link_rate, prev_link_rate; | ||
| 5685 | Mpi2EventDataSasTopologyChangeList_t *event_data = | ||
| 5686 | (Mpi2EventDataSasTopologyChangeList_t *) | ||
| 5687 | fw_event->event_data; | ||
| 5688 | |||
| 5689 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | ||
| 5690 | if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) | ||
| 5691 | _scsih_sas_topology_change_event_debug(ioc, event_data); | ||
| 5692 | #endif | ||
| 5693 | |||
| 5694 | if (ioc->remove_host || ioc->pci_error_recovery) | ||
| 5695 | return; | ||
| 5696 | |||
| 5697 | if (!ioc->sas_hba.num_phys) | ||
| 5698 | _scsih_sas_host_add(ioc); | ||
| 5699 | else | ||
| 5700 | _scsih_sas_host_refresh(ioc); | ||
| 5701 | |||
| 5702 | if (fw_event->ignore) { | ||
| 5703 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "ignoring expander " | ||
| 5704 | "event\n", ioc->name)); | ||
| 5705 | return; | ||
| 5706 | } | ||
| 5707 | |||
| 5708 | parent_handle = le16_to_cpu(event_data->ExpanderDevHandle); | ||
| 5709 | |||
| 5710 | /* handle expander add */ | ||
| 5711 | if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_ADDED) | ||
| 5712 | if (_scsih_expander_add(ioc, parent_handle) != 0) | ||
| 5713 | return; | ||
| 5714 | |||
| 5715 | spin_lock_irqsave(&ioc->sas_node_lock, flags); | ||
| 5716 | sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc, | ||
| 5717 | parent_handle); | ||
| 5718 | if (sas_expander) { | ||
| 5719 | sas_address = sas_expander->sas_address; | ||
| 5720 | max_phys = sas_expander->num_phys; | ||
| 5721 | } else if (parent_handle < ioc->sas_hba.num_phys) { | ||
| 5722 | sas_address = ioc->sas_hba.sas_address; | ||
| 5723 | max_phys = ioc->sas_hba.num_phys; | ||
| 5724 | } else { | ||
| 5725 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | ||
| 5726 | return; | ||
| 5727 | } | ||
| 5728 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | ||
| 5729 | |||
| 5730 | /* handle siblings events */ | ||
| 5731 | for (i = 0; i < event_data->NumEntries; i++) { | ||
| 5732 | if (fw_event->ignore) { | ||
| 5733 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "ignoring " | ||
| 5734 | "expander event\n", ioc->name)); | ||
| 5735 | return; | ||
| 5736 | } | ||
| 5737 | if (ioc->shost_recovery || ioc->remove_host || | ||
| 5738 | ioc->pci_error_recovery) | ||
| 5739 | return; | ||
| 5740 | phy_number = event_data->StartPhyNum + i; | ||
| 5741 | if (phy_number >= max_phys) | ||
| 5742 | continue; | ||
| 5743 | reason_code = event_data->PHY[i].PhyStatus & | ||
| 5744 | MPI2_EVENT_SAS_TOPO_RC_MASK; | ||
| 5745 | if ((event_data->PHY[i].PhyStatus & | ||
| 5746 | MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT) && (reason_code != | ||
| 5747 | MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING)) | ||
| 5748 | continue; | ||
| 5749 | handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle); | ||
| 5750 | if (!handle) | ||
| 5751 | continue; | ||
| 5752 | link_rate = event_data->PHY[i].LinkRate >> 4; | ||
| 5753 | prev_link_rate = event_data->PHY[i].LinkRate & 0xF; | ||
| 5754 | switch (reason_code) { | ||
| 5755 | case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED: | ||
| 5756 | |||
| 5757 | if (ioc->shost_recovery) | ||
| 5758 | break; | ||
| 5759 | |||
| 5760 | if (link_rate == prev_link_rate) | ||
| 5761 | break; | ||
| 5762 | |||
| 5763 | mpt2sas_transport_update_links(ioc, sas_address, | ||
| 5764 | handle, phy_number, link_rate); | ||
| 5765 | |||
| 5766 | if (link_rate < MPI2_SAS_NEG_LINK_RATE_1_5) | ||
| 5767 | break; | ||
| 5768 | |||
| 5769 | _scsih_check_device(ioc, handle); | ||
| 5770 | break; | ||
| 5771 | case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED: | ||
| 5772 | |||
| 5773 | if (ioc->shost_recovery) | ||
| 5774 | break; | ||
| 5775 | |||
| 5776 | mpt2sas_transport_update_links(ioc, sas_address, | ||
| 5777 | handle, phy_number, link_rate); | ||
| 5778 | |||
| 5779 | _scsih_add_device(ioc, handle, phy_number, 0); | ||
| 5780 | break; | ||
| 5781 | case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING: | ||
| 5782 | |||
| 5783 | _scsih_device_remove_by_handle(ioc, handle); | ||
| 5784 | break; | ||
| 5785 | } | ||
| 5786 | } | ||
| 5787 | |||
| 5788 | /* handle expander removal */ | ||
| 5789 | if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING && | ||
| 5790 | sas_expander) | ||
| 5791 | mpt2sas_expander_remove(ioc, sas_address); | ||
| 5792 | |||
| 5793 | } | ||
| 5794 | |||
| 5795 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | ||
| 5796 | /** | ||
| 5797 | * _scsih_sas_device_status_change_event_debug - debug for device event | ||
| 5798 | * @event_data: event data payload | ||
| 5799 | * Context: user. | ||
| 5800 | * | ||
| 5801 | * Return nothing. | ||
| 5802 | */ | ||
| 5803 | static void | ||
| 5804 | _scsih_sas_device_status_change_event_debug(struct MPT2SAS_ADAPTER *ioc, | ||
| 5805 | Mpi2EventDataSasDeviceStatusChange_t *event_data) | ||
| 5806 | { | ||
| 5807 | char *reason_str = NULL; | ||
| 5808 | |||
| 5809 | switch (event_data->ReasonCode) { | ||
| 5810 | case MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA: | ||
| 5811 | reason_str = "smart data"; | ||
| 5812 | break; | ||
| 5813 | case MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED: | ||
| 5814 | reason_str = "unsupported device discovered"; | ||
| 5815 | break; | ||
| 5816 | case MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET: | ||
| 5817 | reason_str = "internal device reset"; | ||
| 5818 | break; | ||
| 5819 | case MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL: | ||
| 5820 | reason_str = "internal task abort"; | ||
| 5821 | break; | ||
| 5822 | case MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL: | ||
| 5823 | reason_str = "internal task abort set"; | ||
| 5824 | break; | ||
| 5825 | case MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL: | ||
| 5826 | reason_str = "internal clear task set"; | ||
| 5827 | break; | ||
| 5828 | case MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL: | ||
| 5829 | reason_str = "internal query task"; | ||
| 5830 | break; | ||
| 5831 | case MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE: | ||
| 5832 | reason_str = "sata init failure"; | ||
| 5833 | break; | ||
| 5834 | case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET: | ||
| 5835 | reason_str = "internal device reset complete"; | ||
| 5836 | break; | ||
| 5837 | case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL: | ||
| 5838 | reason_str = "internal task abort complete"; | ||
| 5839 | break; | ||
| 5840 | case MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION: | ||
| 5841 | reason_str = "internal async notification"; | ||
| 5842 | break; | ||
| 5843 | case MPI2_EVENT_SAS_DEV_STAT_RC_EXPANDER_REDUCED_FUNCTIONALITY: | ||
| 5844 | reason_str = "expander reduced functionality"; | ||
| 5845 | break; | ||
| 5846 | case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_EXPANDER_REDUCED_FUNCTIONALITY: | ||
| 5847 | reason_str = "expander reduced functionality complete"; | ||
| 5848 | break; | ||
| 5849 | default: | ||
| 5850 | reason_str = "unknown reason"; | ||
| 5851 | break; | ||
| 5852 | } | ||
| 5853 | printk(MPT2SAS_INFO_FMT "device status change: (%s)\n" | ||
| 5854 | "\thandle(0x%04x), sas address(0x%016llx), tag(%d)", | ||
| 5855 | ioc->name, reason_str, le16_to_cpu(event_data->DevHandle), | ||
| 5856 | (unsigned long long)le64_to_cpu(event_data->SASAddress), | ||
| 5857 | le16_to_cpu(event_data->TaskTag)); | ||
| 5858 | if (event_data->ReasonCode == MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA) | ||
| 5859 | printk(MPT2SAS_INFO_FMT ", ASC(0x%x), ASCQ(0x%x)\n", ioc->name, | ||
| 5860 | event_data->ASC, event_data->ASCQ); | ||
| 5861 | printk(KERN_INFO "\n"); | ||
| 5862 | } | ||
| 5863 | #endif | ||
| 5864 | |||
| 5865 | /** | ||
| 5866 | * _scsih_sas_device_status_change_event - handle device status change | ||
| 5867 | * @ioc: per adapter object | ||
| 5868 | * @fw_event: The fw_event_work object | ||
| 5869 | * Context: user. | ||
| 5870 | * | ||
| 5871 | * Return nothing. | ||
| 5872 | */ | ||
| 5873 | static void | ||
| 5874 | _scsih_sas_device_status_change_event(struct MPT2SAS_ADAPTER *ioc, | ||
| 5875 | struct fw_event_work *fw_event) | ||
| 5876 | { | ||
| 5877 | struct MPT2SAS_TARGET *target_priv_data; | ||
| 5878 | struct _sas_device *sas_device; | ||
| 5879 | u64 sas_address; | ||
| 5880 | unsigned long flags; | ||
| 5881 | Mpi2EventDataSasDeviceStatusChange_t *event_data = | ||
| 5882 | (Mpi2EventDataSasDeviceStatusChange_t *) | ||
| 5883 | fw_event->event_data; | ||
| 5884 | |||
| 5885 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | ||
| 5886 | if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) | ||
| 5887 | _scsih_sas_device_status_change_event_debug(ioc, | ||
| 5888 | event_data); | ||
| 5889 | #endif | ||
| 5890 | |||
| 5891 | /* In MPI Revision K (0xC), the internal device reset complete was | ||
| 5892 | * implemented, so avoid setting tm_busy flag for older firmware. | ||
| 5893 | */ | ||
| 5894 | if ((ioc->facts.HeaderVersion >> 8) < 0xC) | ||
| 5895 | return; | ||
| 5896 | |||
| 5897 | if (event_data->ReasonCode != | ||
| 5898 | MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET && | ||
| 5899 | event_data->ReasonCode != | ||
| 5900 | MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET) | ||
| 5901 | return; | ||
| 5902 | |||
| 5903 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 5904 | sas_address = le64_to_cpu(event_data->SASAddress); | ||
| 5905 | sas_device = __mpt2sas_get_sdev_by_addr(ioc, | ||
| 5906 | sas_address); | ||
| 5907 | |||
| 5908 | if (!sas_device || !sas_device->starget) | ||
| 5909 | goto out; | ||
| 5910 | |||
| 5911 | target_priv_data = sas_device->starget->hostdata; | ||
| 5912 | if (!target_priv_data) | ||
| 5913 | goto out; | ||
| 5914 | |||
| 5915 | if (event_data->ReasonCode == | ||
| 5916 | MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET) | ||
| 5917 | target_priv_data->tm_busy = 1; | ||
| 5918 | else | ||
| 5919 | target_priv_data->tm_busy = 0; | ||
| 5920 | |||
| 5921 | out: | ||
| 5922 | if (sas_device) | ||
| 5923 | sas_device_put(sas_device); | ||
| 5924 | |||
| 5925 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 5926 | |||
| 5927 | } | ||
| 5928 | |||
| 5929 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | ||
| 5930 | /** | ||
| 5931 | * _scsih_sas_enclosure_dev_status_change_event_debug - debug for enclosure event | ||
| 5932 | * @ioc: per adapter object | ||
| 5933 | * @event_data: event data payload | ||
| 5934 | * Context: user. | ||
| 5935 | * | ||
| 5936 | * Return nothing. | ||
| 5937 | */ | ||
| 5938 | static void | ||
| 5939 | _scsih_sas_enclosure_dev_status_change_event_debug(struct MPT2SAS_ADAPTER *ioc, | ||
| 5940 | Mpi2EventDataSasEnclDevStatusChange_t *event_data) | ||
| 5941 | { | ||
| 5942 | char *reason_str = NULL; | ||
| 5943 | |||
| 5944 | switch (event_data->ReasonCode) { | ||
| 5945 | case MPI2_EVENT_SAS_ENCL_RC_ADDED: | ||
| 5946 | reason_str = "enclosure add"; | ||
| 5947 | break; | ||
| 5948 | case MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING: | ||
| 5949 | reason_str = "enclosure remove"; | ||
| 5950 | break; | ||
| 5951 | default: | ||
| 5952 | reason_str = "unknown reason"; | ||
| 5953 | break; | ||
| 5954 | } | ||
| 5955 | |||
| 5956 | printk(MPT2SAS_INFO_FMT "enclosure status change: (%s)\n" | ||
| 5957 | "\thandle(0x%04x), enclosure logical id(0x%016llx)" | ||
| 5958 | " number slots(%d)\n", ioc->name, reason_str, | ||
| 5959 | le16_to_cpu(event_data->EnclosureHandle), | ||
| 5960 | (unsigned long long)le64_to_cpu(event_data->EnclosureLogicalID), | ||
| 5961 | le16_to_cpu(event_data->StartSlot)); | ||
| 5962 | } | ||
| 5963 | #endif | ||
| 5964 | |||
| 5965 | /** | ||
| 5966 | * _scsih_sas_enclosure_dev_status_change_event - handle enclosure events | ||
| 5967 | * @ioc: per adapter object | ||
| 5968 | * @fw_event: The fw_event_work object | ||
| 5969 | * Context: user. | ||
| 5970 | * | ||
| 5971 | * Return nothing. | ||
| 5972 | */ | ||
| 5973 | static void | ||
| 5974 | _scsih_sas_enclosure_dev_status_change_event(struct MPT2SAS_ADAPTER *ioc, | ||
| 5975 | struct fw_event_work *fw_event) | ||
| 5976 | { | ||
| 5977 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | ||
| 5978 | if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) | ||
| 5979 | _scsih_sas_enclosure_dev_status_change_event_debug(ioc, | ||
| 5980 | (Mpi2EventDataSasEnclDevStatusChange_t *) | ||
| 5981 | fw_event->event_data); | ||
| 5982 | #endif | ||
| 5983 | } | ||
| 5984 | |||
| 5985 | /** | ||
| 5986 | * _scsih_sas_broadcast_primitive_event - handle broadcast events | ||
| 5987 | * @ioc: per adapter object | ||
| 5988 | * @fw_event: The fw_event_work object | ||
| 5989 | * Context: user. | ||
| 5990 | * | ||
| 5991 | * Return nothing. | ||
| 5992 | */ | ||
| 5993 | static void | ||
| 5994 | _scsih_sas_broadcast_primitive_event(struct MPT2SAS_ADAPTER *ioc, | ||
| 5995 | struct fw_event_work *fw_event) | ||
| 5996 | { | ||
| 5997 | struct scsi_cmnd *scmd; | ||
| 5998 | struct scsi_device *sdev; | ||
| 5999 | u16 smid, handle; | ||
| 6000 | u32 lun; | ||
| 6001 | struct MPT2SAS_DEVICE *sas_device_priv_data; | ||
| 6002 | u32 termination_count; | ||
| 6003 | u32 query_count; | ||
| 6004 | Mpi2SCSITaskManagementReply_t *mpi_reply; | ||
| 6005 | Mpi2EventDataSasBroadcastPrimitive_t *event_data = | ||
| 6006 | (Mpi2EventDataSasBroadcastPrimitive_t *) | ||
| 6007 | fw_event->event_data; | ||
| 6008 | u16 ioc_status; | ||
| 6009 | unsigned long flags; | ||
| 6010 | int r; | ||
| 6011 | u8 max_retries = 0; | ||
| 6012 | u8 task_abort_retries; | ||
| 6013 | |||
| 6014 | mutex_lock(&ioc->tm_cmds.mutex); | ||
| 6015 | pr_info(MPT2SAS_FMT | ||
| 6016 | "%s: enter: phy number(%d), width(%d)\n", | ||
| 6017 | ioc->name, __func__, event_data->PhyNum, | ||
| 6018 | event_data->PortWidth); | ||
| 6019 | |||
| 6020 | _scsih_block_io_all_device(ioc); | ||
| 6021 | |||
| 6022 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | ||
| 6023 | mpi_reply = ioc->tm_cmds.reply; | ||
| 6024 | broadcast_aen_retry: | ||
| 6025 | |||
| 6026 | /* sanity checks for retrying this loop */ | ||
| 6027 | if (max_retries++ == 5) { | ||
| 6028 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: giving up\n", | ||
| 6029 | ioc->name, __func__)); | ||
| 6030 | goto out; | ||
| 6031 | } else if (max_retries > 1) | ||
| 6032 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: %d retry\n", | ||
| 6033 | ioc->name, __func__, max_retries - 1)); | ||
| 6034 | |||
| 6035 | termination_count = 0; | ||
| 6036 | query_count = 0; | ||
| 6037 | for (smid = 1; smid <= ioc->scsiio_depth; smid++) { | ||
| 6038 | if (ioc->shost_recovery) | ||
| 6039 | goto out; | ||
| 6040 | scmd = _scsih_scsi_lookup_get(ioc, smid); | ||
| 6041 | if (!scmd) | ||
| 6042 | continue; | ||
| 6043 | sdev = scmd->device; | ||
| 6044 | sas_device_priv_data = sdev->hostdata; | ||
| 6045 | if (!sas_device_priv_data || !sas_device_priv_data->sas_target) | ||
| 6046 | continue; | ||
| 6047 | /* skip hidden raid components */ | ||
| 6048 | if (sas_device_priv_data->sas_target->flags & | ||
| 6049 | MPT_TARGET_FLAGS_RAID_COMPONENT) | ||
| 6050 | continue; | ||
| 6051 | /* skip volumes */ | ||
| 6052 | if (sas_device_priv_data->sas_target->flags & | ||
| 6053 | MPT_TARGET_FLAGS_VOLUME) | ||
| 6054 | continue; | ||
| 6055 | |||
| 6056 | handle = sas_device_priv_data->sas_target->handle; | ||
| 6057 | lun = sas_device_priv_data->lun; | ||
| 6058 | query_count++; | ||
| 6059 | |||
| 6060 | if (ioc->shost_recovery) | ||
| 6061 | goto out; | ||
| 6062 | |||
| 6063 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | ||
| 6064 | r = mpt2sas_scsih_issue_tm(ioc, handle, 0, 0, lun, | ||
| 6065 | MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30, | ||
| 6066 | TM_MUTEX_OFF); | ||
| 6067 | if (r == FAILED) { | ||
| 6068 | sdev_printk(KERN_WARNING, sdev, | ||
| 6069 | "mpt2sas_scsih_issue_tm: FAILED when sending " | ||
| 6070 | "QUERY_TASK: scmd(%p)\n", scmd); | ||
| 6071 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | ||
| 6072 | goto broadcast_aen_retry; | ||
| 6073 | } | ||
| 6074 | ioc_status = le16_to_cpu(mpi_reply->IOCStatus) | ||
| 6075 | & MPI2_IOCSTATUS_MASK; | ||
| 6076 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { | ||
| 6077 | sdev_printk(KERN_WARNING, sdev, "query task: FAILED " | ||
| 6078 | "with IOCSTATUS(0x%04x), scmd(%p)\n", ioc_status, | ||
| 6079 | scmd); | ||
| 6080 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | ||
| 6081 | goto broadcast_aen_retry; | ||
| 6082 | } | ||
| 6083 | |||
| 6084 | /* see if IO is still owned by IOC and target */ | ||
| 6085 | if (mpi_reply->ResponseCode == | ||
| 6086 | MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED || | ||
| 6087 | mpi_reply->ResponseCode == | ||
| 6088 | MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC) { | ||
| 6089 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | ||
| 6090 | continue; | ||
| 6091 | } | ||
| 6092 | task_abort_retries = 0; | ||
| 6093 | tm_retry: | ||
| 6094 | if (task_abort_retries++ == 60) { | ||
| 6095 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 6096 | "%s: ABORT_TASK: giving up\n", ioc->name, | ||
| 6097 | __func__)); | ||
| 6098 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | ||
| 6099 | goto broadcast_aen_retry; | ||
| 6100 | } | ||
| 6101 | |||
| 6102 | if (ioc->shost_recovery) | ||
| 6103 | goto out_no_lock; | ||
| 6104 | |||
| 6105 | r = mpt2sas_scsih_issue_tm(ioc, handle, sdev->channel, sdev->id, | ||
| 6106 | sdev->lun, MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30, | ||
| 6107 | TM_MUTEX_OFF); | ||
| 6108 | if (r == FAILED) { | ||
| 6109 | sdev_printk(KERN_WARNING, sdev, | ||
| 6110 | "mpt2sas_scsih_issue_tm: ABORT_TASK: FAILED : " | ||
| 6111 | "scmd(%p)\n", scmd); | ||
| 6112 | goto tm_retry; | ||
| 6113 | } | ||
| 6114 | |||
| 6115 | if (task_abort_retries > 1) | ||
| 6116 | sdev_printk(KERN_WARNING, sdev, | ||
| 6117 | "mpt2sas_scsih_issue_tm: ABORT_TASK: RETRIES (%d):" | ||
| 6118 | " scmd(%p)\n", | ||
| 6119 | task_abort_retries - 1, scmd); | ||
| 6120 | |||
| 6121 | termination_count += le32_to_cpu(mpi_reply->TerminationCount); | ||
| 6122 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | ||
| 6123 | } | ||
| 6124 | |||
| 6125 | if (ioc->broadcast_aen_pending) { | ||
| 6126 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: loop back due to" | ||
| 6127 | " pending AEN\n", ioc->name, __func__)); | ||
| 6128 | ioc->broadcast_aen_pending = 0; | ||
| 6129 | goto broadcast_aen_retry; | ||
| 6130 | } | ||
| 6131 | |||
| 6132 | out: | ||
| 6133 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | ||
| 6134 | out_no_lock: | ||
| 6135 | |||
| 6136 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 6137 | "%s - exit, query_count = %d termination_count = %d\n", | ||
| 6138 | ioc->name, __func__, query_count, termination_count)); | ||
| 6139 | |||
| 6140 | ioc->broadcast_aen_busy = 0; | ||
| 6141 | if (!ioc->shost_recovery) | ||
| 6142 | _scsih_ublock_io_all_device(ioc); | ||
| 6143 | mutex_unlock(&ioc->tm_cmds.mutex); | ||
| 6144 | } | ||
| 6145 | |||
| 6146 | /** | ||
| 6147 | * _scsih_sas_discovery_event - handle discovery events | ||
| 6148 | * @ioc: per adapter object | ||
| 6149 | * @fw_event: The fw_event_work object | ||
| 6150 | * Context: user. | ||
| 6151 | * | ||
| 6152 | * Return nothing. | ||
| 6153 | */ | ||
| 6154 | static void | ||
| 6155 | _scsih_sas_discovery_event(struct MPT2SAS_ADAPTER *ioc, | ||
| 6156 | struct fw_event_work *fw_event) | ||
| 6157 | { | ||
| 6158 | Mpi2EventDataSasDiscovery_t *event_data = | ||
| 6159 | (Mpi2EventDataSasDiscovery_t *) | ||
| 6160 | fw_event->event_data; | ||
| 6161 | |||
| 6162 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | ||
| 6163 | if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) { | ||
| 6164 | printk(MPT2SAS_INFO_FMT "discovery event: (%s)", ioc->name, | ||
| 6165 | (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED) ? | ||
| 6166 | "start" : "stop"); | ||
| 6167 | if (event_data->DiscoveryStatus) | ||
| 6168 | printk("discovery_status(0x%08x)", | ||
| 6169 | le32_to_cpu(event_data->DiscoveryStatus)); | ||
| 6170 | printk("\n"); | ||
| 6171 | } | ||
| 6172 | #endif | ||
| 6173 | |||
| 6174 | if (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED && | ||
| 6175 | !ioc->sas_hba.num_phys) { | ||
| 6176 | if (disable_discovery > 0 && ioc->shost_recovery) { | ||
| 6177 | /* Wait for the reset to complete */ | ||
| 6178 | while (ioc->shost_recovery) | ||
| 6179 | ssleep(1); | ||
| 6180 | } | ||
| 6181 | _scsih_sas_host_add(ioc); | ||
| 6182 | } | ||
| 6183 | } | ||
| 6184 | |||
| 6185 | /** | ||
| 6186 | * _scsih_reprobe_lun - reprobing lun | ||
| 6187 | * @sdev: scsi device struct | ||
| 6188 | * @no_uld_attach: sdev->no_uld_attach flag setting | ||
| 6189 | * | ||
| 6190 | **/ | ||
| 6191 | static void | ||
| 6192 | _scsih_reprobe_lun(struct scsi_device *sdev, void *no_uld_attach) | ||
| 6193 | { | ||
| 6194 | int rc; | ||
| 6195 | |||
| 6196 | sdev->no_uld_attach = no_uld_attach ? 1 : 0; | ||
| 6197 | sdev_printk(KERN_INFO, sdev, "%s raid component\n", | ||
| 6198 | sdev->no_uld_attach ? "hidding" : "exposing"); | ||
| 6199 | rc = scsi_device_reprobe(sdev); | ||
| 6200 | } | ||
| 6201 | |||
| 6202 | /** | ||
| 6203 | * _scsih_sas_volume_add - add new volume | ||
| 6204 | * @ioc: per adapter object | ||
| 6205 | * @element: IR config element data | ||
| 6206 | * Context: user. | ||
| 6207 | * | ||
| 6208 | * Return nothing. | ||
| 6209 | */ | ||
| 6210 | static void | ||
| 6211 | _scsih_sas_volume_add(struct MPT2SAS_ADAPTER *ioc, | ||
| 6212 | Mpi2EventIrConfigElement_t *element) | ||
| 6213 | { | ||
| 6214 | struct _raid_device *raid_device; | ||
| 6215 | unsigned long flags; | ||
| 6216 | u64 wwid; | ||
| 6217 | u16 handle = le16_to_cpu(element->VolDevHandle); | ||
| 6218 | int rc; | ||
| 6219 | |||
| 6220 | mpt2sas_config_get_volume_wwid(ioc, handle, &wwid); | ||
| 6221 | if (!wwid) { | ||
| 6222 | printk(MPT2SAS_ERR_FMT | ||
| 6223 | "failure at %s:%d/%s()!\n", ioc->name, | ||
| 6224 | __FILE__, __LINE__, __func__); | ||
| 6225 | return; | ||
| 6226 | } | ||
| 6227 | |||
| 6228 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | ||
| 6229 | raid_device = _scsih_raid_device_find_by_wwid(ioc, wwid); | ||
| 6230 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); | ||
| 6231 | |||
| 6232 | if (raid_device) | ||
| 6233 | return; | ||
| 6234 | |||
| 6235 | raid_device = kzalloc(sizeof(struct _raid_device), GFP_KERNEL); | ||
| 6236 | if (!raid_device) { | ||
| 6237 | printk(MPT2SAS_ERR_FMT | ||
| 6238 | "failure at %s:%d/%s()!\n", ioc->name, | ||
| 6239 | __FILE__, __LINE__, __func__); | ||
| 6240 | return; | ||
| 6241 | } | ||
| 6242 | |||
| 6243 | raid_device->id = ioc->sas_id++; | ||
| 6244 | raid_device->channel = RAID_CHANNEL; | ||
| 6245 | raid_device->handle = handle; | ||
| 6246 | raid_device->wwid = wwid; | ||
| 6247 | _scsih_raid_device_add(ioc, raid_device); | ||
| 6248 | if (!ioc->wait_for_discovery_to_complete) { | ||
| 6249 | rc = scsi_add_device(ioc->shost, RAID_CHANNEL, | ||
| 6250 | raid_device->id, 0); | ||
| 6251 | if (rc) | ||
| 6252 | _scsih_raid_device_remove(ioc, raid_device); | ||
| 6253 | } else { | ||
| 6254 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | ||
| 6255 | _scsih_determine_boot_device(ioc, raid_device, 1); | ||
| 6256 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); | ||
| 6257 | } | ||
| 6258 | } | ||
| 6259 | |||
| 6260 | /** | ||
| 6261 | * _scsih_sas_volume_delete - delete volume | ||
| 6262 | * @ioc: per adapter object | ||
| 6263 | * @handle: volume device handle | ||
| 6264 | * Context: user. | ||
| 6265 | * | ||
| 6266 | * Return nothing. | ||
| 6267 | */ | ||
| 6268 | static void | ||
| 6269 | _scsih_sas_volume_delete(struct MPT2SAS_ADAPTER *ioc, u16 handle) | ||
| 6270 | { | ||
| 6271 | struct _raid_device *raid_device; | ||
| 6272 | unsigned long flags; | ||
| 6273 | struct MPT2SAS_TARGET *sas_target_priv_data; | ||
| 6274 | struct scsi_target *starget = NULL; | ||
| 6275 | |||
| 6276 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | ||
| 6277 | raid_device = _scsih_raid_device_find_by_handle(ioc, handle); | ||
| 6278 | if (raid_device) { | ||
| 6279 | if (raid_device->starget) { | ||
| 6280 | starget = raid_device->starget; | ||
| 6281 | sas_target_priv_data = starget->hostdata; | ||
| 6282 | sas_target_priv_data->deleted = 1; | ||
| 6283 | } | ||
| 6284 | printk(MPT2SAS_INFO_FMT "removing handle(0x%04x), wwid" | ||
| 6285 | "(0x%016llx)\n", ioc->name, raid_device->handle, | ||
| 6286 | (unsigned long long) raid_device->wwid); | ||
| 6287 | list_del(&raid_device->list); | ||
| 6288 | kfree(raid_device); | ||
| 6289 | } | ||
| 6290 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); | ||
| 6291 | if (starget) | ||
| 6292 | scsi_remove_target(&starget->dev); | ||
| 6293 | } | ||
| 6294 | |||
| 6295 | /** | ||
| 6296 | * _scsih_sas_pd_expose - expose pd component to /dev/sdX | ||
| 6297 | * @ioc: per adapter object | ||
| 6298 | * @element: IR config element data | ||
| 6299 | * Context: user. | ||
| 6300 | * | ||
| 6301 | * Return nothing. | ||
| 6302 | */ | ||
| 6303 | static void | ||
| 6304 | _scsih_sas_pd_expose(struct MPT2SAS_ADAPTER *ioc, | ||
| 6305 | Mpi2EventIrConfigElement_t *element) | ||
| 6306 | { | ||
| 6307 | struct _sas_device *sas_device; | ||
| 6308 | struct scsi_target *starget = NULL; | ||
| 6309 | struct MPT2SAS_TARGET *sas_target_priv_data; | ||
| 6310 | unsigned long flags; | ||
| 6311 | u16 handle = le16_to_cpu(element->PhysDiskDevHandle); | ||
| 6312 | |||
| 6313 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 6314 | sas_device = __mpt2sas_get_sdev_by_handle(ioc, handle); | ||
| 6315 | if (sas_device) { | ||
| 6316 | sas_device->volume_handle = 0; | ||
| 6317 | sas_device->volume_wwid = 0; | ||
| 6318 | clear_bit(handle, ioc->pd_handles); | ||
| 6319 | if (sas_device->starget && sas_device->starget->hostdata) { | ||
| 6320 | starget = sas_device->starget; | ||
| 6321 | sas_target_priv_data = starget->hostdata; | ||
| 6322 | sas_target_priv_data->flags &= | ||
| 6323 | ~MPT_TARGET_FLAGS_RAID_COMPONENT; | ||
| 6324 | } | ||
| 6325 | } | ||
| 6326 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 6327 | if (!sas_device) | ||
| 6328 | return; | ||
| 6329 | |||
| 6330 | /* exposing raid component */ | ||
| 6331 | if (starget) | ||
| 6332 | starget_for_each_device(starget, NULL, _scsih_reprobe_lun); | ||
| 6333 | |||
| 6334 | sas_device_put(sas_device); | ||
| 6335 | } | ||
| 6336 | |||
| 6337 | /** | ||
| 6338 | * _scsih_sas_pd_hide - hide pd component from /dev/sdX | ||
| 6339 | * @ioc: per adapter object | ||
| 6340 | * @element: IR config element data | ||
| 6341 | * Context: user. | ||
| 6342 | * | ||
| 6343 | * Return nothing. | ||
| 6344 | */ | ||
| 6345 | static void | ||
| 6346 | _scsih_sas_pd_hide(struct MPT2SAS_ADAPTER *ioc, | ||
| 6347 | Mpi2EventIrConfigElement_t *element) | ||
| 6348 | { | ||
| 6349 | struct _sas_device *sas_device; | ||
| 6350 | struct scsi_target *starget = NULL; | ||
| 6351 | struct MPT2SAS_TARGET *sas_target_priv_data; | ||
| 6352 | unsigned long flags; | ||
| 6353 | u16 handle = le16_to_cpu(element->PhysDiskDevHandle); | ||
| 6354 | u16 volume_handle = 0; | ||
| 6355 | u64 volume_wwid = 0; | ||
| 6356 | |||
| 6357 | mpt2sas_config_get_volume_handle(ioc, handle, &volume_handle); | ||
| 6358 | if (volume_handle) | ||
| 6359 | mpt2sas_config_get_volume_wwid(ioc, volume_handle, | ||
| 6360 | &volume_wwid); | ||
| 6361 | |||
| 6362 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 6363 | sas_device = __mpt2sas_get_sdev_by_handle(ioc, handle); | ||
| 6364 | if (sas_device) { | ||
| 6365 | set_bit(handle, ioc->pd_handles); | ||
| 6366 | if (sas_device->starget && sas_device->starget->hostdata) { | ||
| 6367 | starget = sas_device->starget; | ||
| 6368 | sas_target_priv_data = starget->hostdata; | ||
| 6369 | sas_target_priv_data->flags |= | ||
| 6370 | MPT_TARGET_FLAGS_RAID_COMPONENT; | ||
| 6371 | sas_device->volume_handle = volume_handle; | ||
| 6372 | sas_device->volume_wwid = volume_wwid; | ||
| 6373 | } | ||
| 6374 | } | ||
| 6375 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 6376 | if (!sas_device) | ||
| 6377 | return; | ||
| 6378 | |||
| 6379 | /* hiding raid component */ | ||
| 6380 | if (starget) | ||
| 6381 | starget_for_each_device(starget, (void *)1, _scsih_reprobe_lun); | ||
| 6382 | |||
| 6383 | sas_device_put(sas_device); | ||
| 6384 | } | ||
| 6385 | |||
| 6386 | /** | ||
| 6387 | * _scsih_sas_pd_delete - delete pd component | ||
| 6388 | * @ioc: per adapter object | ||
| 6389 | * @element: IR config element data | ||
| 6390 | * Context: user. | ||
| 6391 | * | ||
| 6392 | * Return nothing. | ||
| 6393 | */ | ||
| 6394 | static void | ||
| 6395 | _scsih_sas_pd_delete(struct MPT2SAS_ADAPTER *ioc, | ||
| 6396 | Mpi2EventIrConfigElement_t *element) | ||
| 6397 | { | ||
| 6398 | u16 handle = le16_to_cpu(element->PhysDiskDevHandle); | ||
| 6399 | |||
| 6400 | _scsih_device_remove_by_handle(ioc, handle); | ||
| 6401 | } | ||
| 6402 | |||
| 6403 | /** | ||
| 6404 | * _scsih_sas_pd_add - remove pd component | ||
| 6405 | * @ioc: per adapter object | ||
| 6406 | * @element: IR config element data | ||
| 6407 | * Context: user. | ||
| 6408 | * | ||
| 6409 | * Return nothing. | ||
| 6410 | */ | ||
| 6411 | static void | ||
| 6412 | _scsih_sas_pd_add(struct MPT2SAS_ADAPTER *ioc, | ||
| 6413 | Mpi2EventIrConfigElement_t *element) | ||
| 6414 | { | ||
| 6415 | struct _sas_device *sas_device; | ||
| 6416 | u16 handle = le16_to_cpu(element->PhysDiskDevHandle); | ||
| 6417 | Mpi2ConfigReply_t mpi_reply; | ||
| 6418 | Mpi2SasDevicePage0_t sas_device_pg0; | ||
| 6419 | u32 ioc_status; | ||
| 6420 | u64 sas_address; | ||
| 6421 | u16 parent_handle; | ||
| 6422 | |||
| 6423 | set_bit(handle, ioc->pd_handles); | ||
| 6424 | |||
| 6425 | sas_device = mpt2sas_get_sdev_by_handle(ioc, handle); | ||
| 6426 | if (sas_device) { | ||
| 6427 | sas_device_put(sas_device); | ||
| 6428 | return; | ||
| 6429 | } | ||
| 6430 | |||
| 6431 | if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, | ||
| 6432 | MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { | ||
| 6433 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 6434 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 6435 | return; | ||
| 6436 | } | ||
| 6437 | |||
| 6438 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
| 6439 | MPI2_IOCSTATUS_MASK; | ||
| 6440 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { | ||
| 6441 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 6442 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 6443 | return; | ||
| 6444 | } | ||
| 6445 | |||
| 6446 | parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle); | ||
| 6447 | if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) | ||
| 6448 | mpt2sas_transport_update_links(ioc, sas_address, handle, | ||
| 6449 | sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5); | ||
| 6450 | |||
| 6451 | _scsih_add_device(ioc, handle, 0, 1); | ||
| 6452 | } | ||
| 6453 | |||
| 6454 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | ||
| 6455 | /** | ||
| 6456 | * _scsih_sas_ir_config_change_event_debug - debug for IR Config Change events | ||
| 6457 | * @ioc: per adapter object | ||
| 6458 | * @event_data: event data payload | ||
| 6459 | * Context: user. | ||
| 6460 | * | ||
| 6461 | * Return nothing. | ||
| 6462 | */ | ||
| 6463 | static void | ||
| 6464 | _scsih_sas_ir_config_change_event_debug(struct MPT2SAS_ADAPTER *ioc, | ||
| 6465 | Mpi2EventDataIrConfigChangeList_t *event_data) | ||
| 6466 | { | ||
| 6467 | Mpi2EventIrConfigElement_t *element; | ||
| 6468 | u8 element_type; | ||
| 6469 | int i; | ||
| 6470 | char *reason_str = NULL, *element_str = NULL; | ||
| 6471 | |||
| 6472 | element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; | ||
| 6473 | |||
| 6474 | printk(MPT2SAS_INFO_FMT "raid config change: (%s), elements(%d)\n", | ||
| 6475 | ioc->name, (le32_to_cpu(event_data->Flags) & | ||
| 6476 | MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? | ||
| 6477 | "foreign" : "native", event_data->NumElements); | ||
| 6478 | for (i = 0; i < event_data->NumElements; i++, element++) { | ||
| 6479 | switch (element->ReasonCode) { | ||
| 6480 | case MPI2_EVENT_IR_CHANGE_RC_ADDED: | ||
| 6481 | reason_str = "add"; | ||
| 6482 | break; | ||
| 6483 | case MPI2_EVENT_IR_CHANGE_RC_REMOVED: | ||
| 6484 | reason_str = "remove"; | ||
| 6485 | break; | ||
| 6486 | case MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE: | ||
| 6487 | reason_str = "no change"; | ||
| 6488 | break; | ||
| 6489 | case MPI2_EVENT_IR_CHANGE_RC_HIDE: | ||
| 6490 | reason_str = "hide"; | ||
| 6491 | break; | ||
| 6492 | case MPI2_EVENT_IR_CHANGE_RC_UNHIDE: | ||
| 6493 | reason_str = "unhide"; | ||
| 6494 | break; | ||
| 6495 | case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED: | ||
| 6496 | reason_str = "volume_created"; | ||
| 6497 | break; | ||
| 6498 | case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED: | ||
| 6499 | reason_str = "volume_deleted"; | ||
| 6500 | break; | ||
| 6501 | case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED: | ||
| 6502 | reason_str = "pd_created"; | ||
| 6503 | break; | ||
| 6504 | case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED: | ||
| 6505 | reason_str = "pd_deleted"; | ||
| 6506 | break; | ||
| 6507 | default: | ||
| 6508 | reason_str = "unknown reason"; | ||
| 6509 | break; | ||
| 6510 | } | ||
| 6511 | element_type = le16_to_cpu(element->ElementFlags) & | ||
| 6512 | MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK; | ||
| 6513 | switch (element_type) { | ||
| 6514 | case MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT: | ||
| 6515 | element_str = "volume"; | ||
| 6516 | break; | ||
| 6517 | case MPI2_EVENT_IR_CHANGE_EFLAGS_VOLPHYSDISK_ELEMENT: | ||
| 6518 | element_str = "phys disk"; | ||
| 6519 | break; | ||
| 6520 | case MPI2_EVENT_IR_CHANGE_EFLAGS_HOTSPARE_ELEMENT: | ||
| 6521 | element_str = "hot spare"; | ||
| 6522 | break; | ||
| 6523 | default: | ||
| 6524 | element_str = "unknown element"; | ||
| 6525 | break; | ||
| 6526 | } | ||
| 6527 | printk(KERN_INFO "\t(%s:%s), vol handle(0x%04x), " | ||
| 6528 | "pd handle(0x%04x), pd num(0x%02x)\n", element_str, | ||
| 6529 | reason_str, le16_to_cpu(element->VolDevHandle), | ||
| 6530 | le16_to_cpu(element->PhysDiskDevHandle), | ||
| 6531 | element->PhysDiskNum); | ||
| 6532 | } | ||
| 6533 | } | ||
| 6534 | #endif | ||
| 6535 | |||
| 6536 | /** | ||
| 6537 | * _scsih_sas_ir_config_change_event - handle ir configuration change events | ||
| 6538 | * @ioc: per adapter object | ||
| 6539 | * @fw_event: The fw_event_work object | ||
| 6540 | * Context: user. | ||
| 6541 | * | ||
| 6542 | * Return nothing. | ||
| 6543 | */ | ||
| 6544 | static void | ||
| 6545 | _scsih_sas_ir_config_change_event(struct MPT2SAS_ADAPTER *ioc, | ||
| 6546 | struct fw_event_work *fw_event) | ||
| 6547 | { | ||
| 6548 | Mpi2EventIrConfigElement_t *element; | ||
| 6549 | int i; | ||
| 6550 | u8 foreign_config; | ||
| 6551 | Mpi2EventDataIrConfigChangeList_t *event_data = | ||
| 6552 | (Mpi2EventDataIrConfigChangeList_t *) | ||
| 6553 | fw_event->event_data; | ||
| 6554 | |||
| 6555 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | ||
| 6556 | if ((ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) | ||
| 6557 | && !ioc->hide_ir_msg) | ||
| 6558 | _scsih_sas_ir_config_change_event_debug(ioc, event_data); | ||
| 6559 | |||
| 6560 | #endif | ||
| 6561 | |||
| 6562 | if (ioc->shost_recovery) | ||
| 6563 | return; | ||
| 6564 | |||
| 6565 | foreign_config = (le32_to_cpu(event_data->Flags) & | ||
| 6566 | MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0; | ||
| 6567 | |||
| 6568 | element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; | ||
| 6569 | for (i = 0; i < event_data->NumElements; i++, element++) { | ||
| 6570 | |||
| 6571 | switch (element->ReasonCode) { | ||
| 6572 | case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED: | ||
| 6573 | case MPI2_EVENT_IR_CHANGE_RC_ADDED: | ||
| 6574 | if (!foreign_config) | ||
| 6575 | _scsih_sas_volume_add(ioc, element); | ||
| 6576 | break; | ||
| 6577 | case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED: | ||
| 6578 | case MPI2_EVENT_IR_CHANGE_RC_REMOVED: | ||
| 6579 | if (!foreign_config) | ||
| 6580 | _scsih_sas_volume_delete(ioc, | ||
| 6581 | le16_to_cpu(element->VolDevHandle)); | ||
| 6582 | break; | ||
| 6583 | case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED: | ||
| 6584 | if (!ioc->is_warpdrive) | ||
| 6585 | _scsih_sas_pd_hide(ioc, element); | ||
| 6586 | break; | ||
| 6587 | case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED: | ||
| 6588 | if (!ioc->is_warpdrive) | ||
| 6589 | _scsih_sas_pd_expose(ioc, element); | ||
| 6590 | break; | ||
| 6591 | case MPI2_EVENT_IR_CHANGE_RC_HIDE: | ||
| 6592 | if (!ioc->is_warpdrive) | ||
| 6593 | _scsih_sas_pd_add(ioc, element); | ||
| 6594 | break; | ||
| 6595 | case MPI2_EVENT_IR_CHANGE_RC_UNHIDE: | ||
| 6596 | if (!ioc->is_warpdrive) | ||
| 6597 | _scsih_sas_pd_delete(ioc, element); | ||
| 6598 | break; | ||
| 6599 | } | ||
| 6600 | } | ||
| 6601 | } | ||
| 6602 | |||
| 6603 | /** | ||
| 6604 | * _scsih_sas_ir_volume_event - IR volume event | ||
| 6605 | * @ioc: per adapter object | ||
| 6606 | * @fw_event: The fw_event_work object | ||
| 6607 | * Context: user. | ||
| 6608 | * | ||
| 6609 | * Return nothing. | ||
| 6610 | */ | ||
| 6611 | static void | ||
| 6612 | _scsih_sas_ir_volume_event(struct MPT2SAS_ADAPTER *ioc, | ||
| 6613 | struct fw_event_work *fw_event) | ||
| 6614 | { | ||
| 6615 | u64 wwid; | ||
| 6616 | unsigned long flags; | ||
| 6617 | struct _raid_device *raid_device; | ||
| 6618 | u16 handle; | ||
| 6619 | u32 state; | ||
| 6620 | int rc; | ||
| 6621 | Mpi2EventDataIrVolume_t *event_data = | ||
| 6622 | (Mpi2EventDataIrVolume_t *) | ||
| 6623 | fw_event->event_data; | ||
| 6624 | |||
| 6625 | if (ioc->shost_recovery) | ||
| 6626 | return; | ||
| 6627 | |||
| 6628 | if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED) | ||
| 6629 | return; | ||
| 6630 | |||
| 6631 | handle = le16_to_cpu(event_data->VolDevHandle); | ||
| 6632 | state = le32_to_cpu(event_data->NewValue); | ||
| 6633 | if (!ioc->hide_ir_msg) | ||
| 6634 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: handle(0x%04x), " | ||
| 6635 | "old(0x%08x), new(0x%08x)\n", ioc->name, __func__, handle, | ||
| 6636 | le32_to_cpu(event_data->PreviousValue), state)); | ||
| 6637 | |||
| 6638 | switch (state) { | ||
| 6639 | case MPI2_RAID_VOL_STATE_MISSING: | ||
| 6640 | case MPI2_RAID_VOL_STATE_FAILED: | ||
| 6641 | _scsih_sas_volume_delete(ioc, handle); | ||
| 6642 | break; | ||
| 6643 | |||
| 6644 | case MPI2_RAID_VOL_STATE_ONLINE: | ||
| 6645 | case MPI2_RAID_VOL_STATE_DEGRADED: | ||
| 6646 | case MPI2_RAID_VOL_STATE_OPTIMAL: | ||
| 6647 | |||
| 6648 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | ||
| 6649 | raid_device = _scsih_raid_device_find_by_handle(ioc, handle); | ||
| 6650 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); | ||
| 6651 | |||
| 6652 | if (raid_device) | ||
| 6653 | break; | ||
| 6654 | |||
| 6655 | mpt2sas_config_get_volume_wwid(ioc, handle, &wwid); | ||
| 6656 | if (!wwid) { | ||
| 6657 | printk(MPT2SAS_ERR_FMT | ||
| 6658 | "failure at %s:%d/%s()!\n", ioc->name, | ||
| 6659 | __FILE__, __LINE__, __func__); | ||
| 6660 | break; | ||
| 6661 | } | ||
| 6662 | |||
| 6663 | raid_device = kzalloc(sizeof(struct _raid_device), GFP_KERNEL); | ||
| 6664 | if (!raid_device) { | ||
| 6665 | printk(MPT2SAS_ERR_FMT | ||
| 6666 | "failure at %s:%d/%s()!\n", ioc->name, | ||
| 6667 | __FILE__, __LINE__, __func__); | ||
| 6668 | break; | ||
| 6669 | } | ||
| 6670 | |||
| 6671 | raid_device->id = ioc->sas_id++; | ||
| 6672 | raid_device->channel = RAID_CHANNEL; | ||
| 6673 | raid_device->handle = handle; | ||
| 6674 | raid_device->wwid = wwid; | ||
| 6675 | _scsih_raid_device_add(ioc, raid_device); | ||
| 6676 | rc = scsi_add_device(ioc->shost, RAID_CHANNEL, | ||
| 6677 | raid_device->id, 0); | ||
| 6678 | if (rc) | ||
| 6679 | _scsih_raid_device_remove(ioc, raid_device); | ||
| 6680 | break; | ||
| 6681 | |||
| 6682 | case MPI2_RAID_VOL_STATE_INITIALIZING: | ||
| 6683 | default: | ||
| 6684 | break; | ||
| 6685 | } | ||
| 6686 | } | ||
| 6687 | |||
| 6688 | /** | ||
| 6689 | * _scsih_sas_ir_physical_disk_event - PD event | ||
| 6690 | * @ioc: per adapter object | ||
| 6691 | * @fw_event: The fw_event_work object | ||
| 6692 | * Context: user. | ||
| 6693 | * | ||
| 6694 | * Return nothing. | ||
| 6695 | */ | ||
| 6696 | static void | ||
| 6697 | _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, | ||
| 6698 | struct fw_event_work *fw_event) | ||
| 6699 | { | ||
| 6700 | u16 handle, parent_handle; | ||
| 6701 | u32 state; | ||
| 6702 | struct _sas_device *sas_device; | ||
| 6703 | Mpi2ConfigReply_t mpi_reply; | ||
| 6704 | Mpi2SasDevicePage0_t sas_device_pg0; | ||
| 6705 | u32 ioc_status; | ||
| 6706 | Mpi2EventDataIrPhysicalDisk_t *event_data = | ||
| 6707 | (Mpi2EventDataIrPhysicalDisk_t *) | ||
| 6708 | fw_event->event_data; | ||
| 6709 | u64 sas_address; | ||
| 6710 | |||
| 6711 | if (ioc->shost_recovery) | ||
| 6712 | return; | ||
| 6713 | |||
| 6714 | if (event_data->ReasonCode != MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED) | ||
| 6715 | return; | ||
| 6716 | |||
| 6717 | handle = le16_to_cpu(event_data->PhysDiskDevHandle); | ||
| 6718 | state = le32_to_cpu(event_data->NewValue); | ||
| 6719 | |||
| 6720 | if (!ioc->hide_ir_msg) | ||
| 6721 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: handle(0x%04x), " | ||
| 6722 | "old(0x%08x), new(0x%08x)\n", ioc->name, __func__, handle, | ||
| 6723 | le32_to_cpu(event_data->PreviousValue), state)); | ||
| 6724 | |||
| 6725 | switch (state) { | ||
| 6726 | case MPI2_RAID_PD_STATE_ONLINE: | ||
| 6727 | case MPI2_RAID_PD_STATE_DEGRADED: | ||
| 6728 | case MPI2_RAID_PD_STATE_REBUILDING: | ||
| 6729 | case MPI2_RAID_PD_STATE_OPTIMAL: | ||
| 6730 | case MPI2_RAID_PD_STATE_HOT_SPARE: | ||
| 6731 | |||
| 6732 | if (!ioc->is_warpdrive) | ||
| 6733 | set_bit(handle, ioc->pd_handles); | ||
| 6734 | |||
| 6735 | sas_device = mpt2sas_get_sdev_by_handle(ioc, handle); | ||
| 6736 | if (sas_device) { | ||
| 6737 | sas_device_put(sas_device); | ||
| 6738 | return; | ||
| 6739 | } | ||
| 6740 | |||
| 6741 | if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, | ||
| 6742 | &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, | ||
| 6743 | handle))) { | ||
| 6744 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 6745 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 6746 | return; | ||
| 6747 | } | ||
| 6748 | |||
| 6749 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
| 6750 | MPI2_IOCSTATUS_MASK; | ||
| 6751 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { | ||
| 6752 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 6753 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 6754 | return; | ||
| 6755 | } | ||
| 6756 | |||
| 6757 | parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle); | ||
| 6758 | if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) | ||
| 6759 | mpt2sas_transport_update_links(ioc, sas_address, handle, | ||
| 6760 | sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5); | ||
| 6761 | |||
| 6762 | _scsih_add_device(ioc, handle, 0, 1); | ||
| 6763 | |||
| 6764 | break; | ||
| 6765 | |||
| 6766 | case MPI2_RAID_PD_STATE_OFFLINE: | ||
| 6767 | case MPI2_RAID_PD_STATE_NOT_CONFIGURED: | ||
| 6768 | case MPI2_RAID_PD_STATE_NOT_COMPATIBLE: | ||
| 6769 | default: | ||
| 6770 | break; | ||
| 6771 | } | ||
| 6772 | } | ||
| 6773 | |||
| 6774 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | ||
| 6775 | /** | ||
| 6776 | * _scsih_sas_ir_operation_status_event_debug - debug for IR op event | ||
| 6777 | * @ioc: per adapter object | ||
| 6778 | * @event_data: event data payload | ||
| 6779 | * Context: user. | ||
| 6780 | * | ||
| 6781 | * Return nothing. | ||
| 6782 | */ | ||
| 6783 | static void | ||
| 6784 | _scsih_sas_ir_operation_status_event_debug(struct MPT2SAS_ADAPTER *ioc, | ||
| 6785 | Mpi2EventDataIrOperationStatus_t *event_data) | ||
| 6786 | { | ||
| 6787 | char *reason_str = NULL; | ||
| 6788 | |||
| 6789 | switch (event_data->RAIDOperation) { | ||
| 6790 | case MPI2_EVENT_IR_RAIDOP_RESYNC: | ||
| 6791 | reason_str = "resync"; | ||
| 6792 | break; | ||
| 6793 | case MPI2_EVENT_IR_RAIDOP_ONLINE_CAP_EXPANSION: | ||
| 6794 | reason_str = "online capacity expansion"; | ||
| 6795 | break; | ||
| 6796 | case MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK: | ||
| 6797 | reason_str = "consistency check"; | ||
| 6798 | break; | ||
| 6799 | case MPI2_EVENT_IR_RAIDOP_BACKGROUND_INIT: | ||
| 6800 | reason_str = "background init"; | ||
| 6801 | break; | ||
| 6802 | case MPI2_EVENT_IR_RAIDOP_MAKE_DATA_CONSISTENT: | ||
| 6803 | reason_str = "make data consistent"; | ||
| 6804 | break; | ||
| 6805 | } | ||
| 6806 | |||
| 6807 | if (!reason_str) | ||
| 6808 | return; | ||
| 6809 | |||
| 6810 | printk(MPT2SAS_INFO_FMT "raid operational status: (%s)" | ||
| 6811 | "\thandle(0x%04x), percent complete(%d)\n", | ||
| 6812 | ioc->name, reason_str, | ||
| 6813 | le16_to_cpu(event_data->VolDevHandle), | ||
| 6814 | event_data->PercentComplete); | ||
| 6815 | } | ||
| 6816 | #endif | ||
| 6817 | |||
| 6818 | /** | ||
| 6819 | * _scsih_sas_ir_operation_status_event - handle RAID operation events | ||
| 6820 | * @ioc: per adapter object | ||
| 6821 | * @fw_event: The fw_event_work object | ||
| 6822 | * Context: user. | ||
| 6823 | * | ||
| 6824 | * Return nothing. | ||
| 6825 | */ | ||
| 6826 | static void | ||
| 6827 | _scsih_sas_ir_operation_status_event(struct MPT2SAS_ADAPTER *ioc, | ||
| 6828 | struct fw_event_work *fw_event) | ||
| 6829 | { | ||
| 6830 | Mpi2EventDataIrOperationStatus_t *event_data = | ||
| 6831 | (Mpi2EventDataIrOperationStatus_t *) | ||
| 6832 | fw_event->event_data; | ||
| 6833 | static struct _raid_device *raid_device; | ||
| 6834 | unsigned long flags; | ||
| 6835 | u16 handle; | ||
| 6836 | |||
| 6837 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | ||
| 6838 | if ((ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) | ||
| 6839 | && !ioc->hide_ir_msg) | ||
| 6840 | _scsih_sas_ir_operation_status_event_debug(ioc, | ||
| 6841 | event_data); | ||
| 6842 | #endif | ||
| 6843 | |||
| 6844 | /* code added for raid transport support */ | ||
| 6845 | if (event_data->RAIDOperation == MPI2_EVENT_IR_RAIDOP_RESYNC) { | ||
| 6846 | |||
| 6847 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | ||
| 6848 | handle = le16_to_cpu(event_data->VolDevHandle); | ||
| 6849 | raid_device = _scsih_raid_device_find_by_handle(ioc, handle); | ||
| 6850 | if (raid_device) | ||
| 6851 | raid_device->percent_complete = | ||
| 6852 | event_data->PercentComplete; | ||
| 6853 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); | ||
| 6854 | } | ||
| 6855 | } | ||
| 6856 | |||
| 6857 | /** | ||
| 6858 | * _scsih_prep_device_scan - initialize parameters prior to device scan | ||
| 6859 | * @ioc: per adapter object | ||
| 6860 | * | ||
| 6861 | * Set the deleted flag prior to device scan. If the device is found during | ||
| 6862 | * the scan, then we clear the deleted flag. | ||
| 6863 | */ | ||
| 6864 | static void | ||
| 6865 | _scsih_prep_device_scan(struct MPT2SAS_ADAPTER *ioc) | ||
| 6866 | { | ||
| 6867 | struct MPT2SAS_DEVICE *sas_device_priv_data; | ||
| 6868 | struct scsi_device *sdev; | ||
| 6869 | |||
| 6870 | shost_for_each_device(sdev, ioc->shost) { | ||
| 6871 | sas_device_priv_data = sdev->hostdata; | ||
| 6872 | if (sas_device_priv_data && sas_device_priv_data->sas_target) | ||
| 6873 | sas_device_priv_data->sas_target->deleted = 1; | ||
| 6874 | } | ||
| 6875 | } | ||
| 6876 | |||
| 6877 | /** | ||
| 6878 | * _scsih_mark_responding_sas_device - mark a sas_devices as responding | ||
| 6879 | * @ioc: per adapter object | ||
| 6880 | * @sas_address: sas address | ||
| 6881 | * @slot: enclosure slot id | ||
| 6882 | * @handle: device handle | ||
| 6883 | * | ||
| 6884 | * After host reset, find out whether devices are still responding. | ||
| 6885 | * Used in _scsi_remove_unresponsive_sas_devices. | ||
| 6886 | * | ||
| 6887 | * Return nothing. | ||
| 6888 | */ | ||
| 6889 | static void | ||
| 6890 | _scsih_mark_responding_sas_device(struct MPT2SAS_ADAPTER *ioc, u64 sas_address, | ||
| 6891 | u16 slot, u16 handle) | ||
| 6892 | { | ||
| 6893 | struct MPT2SAS_TARGET *sas_target_priv_data = NULL; | ||
| 6894 | struct scsi_target *starget; | ||
| 6895 | struct _sas_device *sas_device; | ||
| 6896 | unsigned long flags; | ||
| 6897 | |||
| 6898 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 6899 | list_for_each_entry(sas_device, &ioc->sas_device_list, list) { | ||
| 6900 | if (sas_device->sas_address == sas_address && | ||
| 6901 | sas_device->slot == slot) { | ||
| 6902 | sas_device->responding = 1; | ||
| 6903 | starget = sas_device->starget; | ||
| 6904 | if (starget && starget->hostdata) { | ||
| 6905 | sas_target_priv_data = starget->hostdata; | ||
| 6906 | sas_target_priv_data->tm_busy = 0; | ||
| 6907 | sas_target_priv_data->deleted = 0; | ||
| 6908 | } else | ||
| 6909 | sas_target_priv_data = NULL; | ||
| 6910 | if (starget) | ||
| 6911 | starget_printk(KERN_INFO, starget, | ||
| 6912 | "handle(0x%04x), sas_addr(0x%016llx), " | ||
| 6913 | "enclosure logical id(0x%016llx), " | ||
| 6914 | "slot(%d)\n", handle, | ||
| 6915 | (unsigned long long)sas_device->sas_address, | ||
| 6916 | (unsigned long long) | ||
| 6917 | sas_device->enclosure_logical_id, | ||
| 6918 | sas_device->slot); | ||
| 6919 | if (sas_device->handle == handle) | ||
| 6920 | goto out; | ||
| 6921 | printk(KERN_INFO "\thandle changed from(0x%04x)!!!\n", | ||
| 6922 | sas_device->handle); | ||
| 6923 | sas_device->handle = handle; | ||
| 6924 | if (sas_target_priv_data) | ||
| 6925 | sas_target_priv_data->handle = handle; | ||
| 6926 | goto out; | ||
| 6927 | } | ||
| 6928 | } | ||
| 6929 | out: | ||
| 6930 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 6931 | } | ||
| 6932 | |||
| 6933 | /** | ||
| 6934 | * _scsih_search_responding_sas_devices - | ||
| 6935 | * @ioc: per adapter object | ||
| 6936 | * | ||
| 6937 | * After host reset, find out whether devices are still responding. | ||
| 6938 | * If not remove. | ||
| 6939 | * | ||
| 6940 | * Return nothing. | ||
| 6941 | */ | ||
| 6942 | static void | ||
| 6943 | _scsih_search_responding_sas_devices(struct MPT2SAS_ADAPTER *ioc) | ||
| 6944 | { | ||
| 6945 | Mpi2SasDevicePage0_t sas_device_pg0; | ||
| 6946 | Mpi2ConfigReply_t mpi_reply; | ||
| 6947 | u16 ioc_status; | ||
| 6948 | __le64 sas_address; | ||
| 6949 | u16 handle; | ||
| 6950 | u32 device_info; | ||
| 6951 | u16 slot; | ||
| 6952 | |||
| 6953 | printk(MPT2SAS_INFO_FMT "search for end-devices: start\n", ioc->name); | ||
| 6954 | |||
| 6955 | if (list_empty(&ioc->sas_device_list)) | ||
| 6956 | goto out; | ||
| 6957 | |||
| 6958 | handle = 0xFFFF; | ||
| 6959 | while (!(mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, | ||
| 6960 | &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE, | ||
| 6961 | handle))) { | ||
| 6962 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
| 6963 | MPI2_IOCSTATUS_MASK; | ||
| 6964 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) | ||
| 6965 | break; | ||
| 6966 | handle = le16_to_cpu(sas_device_pg0.DevHandle); | ||
| 6967 | device_info = le32_to_cpu(sas_device_pg0.DeviceInfo); | ||
| 6968 | if (!(_scsih_is_end_device(device_info))) | ||
| 6969 | continue; | ||
| 6970 | sas_address = le64_to_cpu(sas_device_pg0.SASAddress); | ||
| 6971 | slot = le16_to_cpu(sas_device_pg0.Slot); | ||
| 6972 | _scsih_mark_responding_sas_device(ioc, sas_address, slot, | ||
| 6973 | handle); | ||
| 6974 | } | ||
| 6975 | out: | ||
| 6976 | printk(MPT2SAS_INFO_FMT "search for end-devices: complete\n", | ||
| 6977 | ioc->name); | ||
| 6978 | } | ||
| 6979 | |||
| 6980 | /** | ||
| 6981 | * _scsih_mark_responding_raid_device - mark a raid_device as responding | ||
| 6982 | * @ioc: per adapter object | ||
| 6983 | * @wwid: world wide identifier for raid volume | ||
| 6984 | * @handle: device handle | ||
| 6985 | * | ||
| 6986 | * After host reset, find out whether devices are still responding. | ||
| 6987 | * Used in _scsi_remove_unresponsive_raid_devices. | ||
| 6988 | * | ||
| 6989 | * Return nothing. | ||
| 6990 | */ | ||
| 6991 | static void | ||
| 6992 | _scsih_mark_responding_raid_device(struct MPT2SAS_ADAPTER *ioc, u64 wwid, | ||
| 6993 | u16 handle) | ||
| 6994 | { | ||
| 6995 | struct MPT2SAS_TARGET *sas_target_priv_data; | ||
| 6996 | struct scsi_target *starget; | ||
| 6997 | struct _raid_device *raid_device; | ||
| 6998 | unsigned long flags; | ||
| 6999 | |||
| 7000 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | ||
| 7001 | list_for_each_entry(raid_device, &ioc->raid_device_list, list) { | ||
| 7002 | if (raid_device->wwid == wwid && raid_device->starget) { | ||
| 7003 | starget = raid_device->starget; | ||
| 7004 | if (starget && starget->hostdata) { | ||
| 7005 | sas_target_priv_data = starget->hostdata; | ||
| 7006 | sas_target_priv_data->deleted = 0; | ||
| 7007 | } else | ||
| 7008 | sas_target_priv_data = NULL; | ||
| 7009 | raid_device->responding = 1; | ||
| 7010 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); | ||
| 7011 | starget_printk(KERN_INFO, raid_device->starget, | ||
| 7012 | "handle(0x%04x), wwid(0x%016llx)\n", handle, | ||
| 7013 | (unsigned long long)raid_device->wwid); | ||
| 7014 | /* | ||
| 7015 | * WARPDRIVE: The handles of the PDs might have changed | ||
| 7016 | * across the host reset so re-initialize the | ||
| 7017 | * required data for Direct IO | ||
| 7018 | */ | ||
| 7019 | _scsih_init_warpdrive_properties(ioc, raid_device); | ||
| 7020 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | ||
| 7021 | if (raid_device->handle == handle) { | ||
| 7022 | spin_unlock_irqrestore(&ioc->raid_device_lock, | ||
| 7023 | flags); | ||
| 7024 | return; | ||
| 7025 | } | ||
| 7026 | printk(KERN_INFO "\thandle changed from(0x%04x)!!!\n", | ||
| 7027 | raid_device->handle); | ||
| 7028 | raid_device->handle = handle; | ||
| 7029 | if (sas_target_priv_data) | ||
| 7030 | sas_target_priv_data->handle = handle; | ||
| 7031 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); | ||
| 7032 | return; | ||
| 7033 | } | ||
| 7034 | } | ||
| 7035 | |||
| 7036 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); | ||
| 7037 | } | ||
| 7038 | |||
| 7039 | /** | ||
| 7040 | * _scsih_search_responding_raid_devices - | ||
| 7041 | * @ioc: per adapter object | ||
| 7042 | * | ||
| 7043 | * After host reset, find out whether devices are still responding. | ||
| 7044 | * If not remove. | ||
| 7045 | * | ||
| 7046 | * Return nothing. | ||
| 7047 | */ | ||
| 7048 | static void | ||
| 7049 | _scsih_search_responding_raid_devices(struct MPT2SAS_ADAPTER *ioc) | ||
| 7050 | { | ||
| 7051 | Mpi2RaidVolPage1_t volume_pg1; | ||
| 7052 | Mpi2RaidVolPage0_t volume_pg0; | ||
| 7053 | Mpi2RaidPhysDiskPage0_t pd_pg0; | ||
| 7054 | Mpi2ConfigReply_t mpi_reply; | ||
| 7055 | u16 ioc_status; | ||
| 7056 | u16 handle; | ||
| 7057 | u8 phys_disk_num; | ||
| 7058 | |||
| 7059 | if (!ioc->ir_firmware) | ||
| 7060 | return; | ||
| 7061 | |||
| 7062 | printk(MPT2SAS_INFO_FMT "search for raid volumes: start\n", | ||
| 7063 | ioc->name); | ||
| 7064 | |||
| 7065 | if (list_empty(&ioc->raid_device_list)) | ||
| 7066 | goto out; | ||
| 7067 | |||
| 7068 | handle = 0xFFFF; | ||
| 7069 | while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply, | ||
| 7070 | &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) { | ||
| 7071 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
| 7072 | MPI2_IOCSTATUS_MASK; | ||
| 7073 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) | ||
| 7074 | break; | ||
| 7075 | handle = le16_to_cpu(volume_pg1.DevHandle); | ||
| 7076 | |||
| 7077 | if (mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, | ||
| 7078 | &volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle, | ||
| 7079 | sizeof(Mpi2RaidVolPage0_t))) | ||
| 7080 | continue; | ||
| 7081 | |||
| 7082 | if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL || | ||
| 7083 | volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE || | ||
| 7084 | volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED) | ||
| 7085 | _scsih_mark_responding_raid_device(ioc, | ||
| 7086 | le64_to_cpu(volume_pg1.WWID), handle); | ||
| 7087 | } | ||
| 7088 | |||
| 7089 | /* refresh the pd_handles */ | ||
| 7090 | if (!ioc->is_warpdrive) { | ||
| 7091 | phys_disk_num = 0xFF; | ||
| 7092 | memset(ioc->pd_handles, 0, ioc->pd_handles_sz); | ||
| 7093 | while (!(mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply, | ||
| 7094 | &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM, | ||
| 7095 | phys_disk_num))) { | ||
| 7096 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
| 7097 | MPI2_IOCSTATUS_MASK; | ||
| 7098 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) | ||
| 7099 | break; | ||
| 7100 | phys_disk_num = pd_pg0.PhysDiskNum; | ||
| 7101 | handle = le16_to_cpu(pd_pg0.DevHandle); | ||
| 7102 | set_bit(handle, ioc->pd_handles); | ||
| 7103 | } | ||
| 7104 | } | ||
| 7105 | out: | ||
| 7106 | printk(MPT2SAS_INFO_FMT "search for responding raid volumes: " | ||
| 7107 | "complete\n", ioc->name); | ||
| 7108 | } | ||
| 7109 | |||
| 7110 | /** | ||
| 7111 | * _scsih_mark_responding_expander - mark a expander as responding | ||
| 7112 | * @ioc: per adapter object | ||
| 7113 | * @sas_address: sas address | ||
| 7114 | * @handle: | ||
| 7115 | * | ||
| 7116 | * After host reset, find out whether devices are still responding. | ||
| 7117 | * Used in _scsi_remove_unresponsive_expanders. | ||
| 7118 | * | ||
| 7119 | * Return nothing. | ||
| 7120 | */ | ||
| 7121 | static void | ||
| 7122 | _scsih_mark_responding_expander(struct MPT2SAS_ADAPTER *ioc, u64 sas_address, | ||
| 7123 | u16 handle) | ||
| 7124 | { | ||
| 7125 | struct _sas_node *sas_expander; | ||
| 7126 | unsigned long flags; | ||
| 7127 | int i; | ||
| 7128 | |||
| 7129 | spin_lock_irqsave(&ioc->sas_node_lock, flags); | ||
| 7130 | list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) { | ||
| 7131 | if (sas_expander->sas_address != sas_address) | ||
| 7132 | continue; | ||
| 7133 | sas_expander->responding = 1; | ||
| 7134 | if (sas_expander->handle == handle) | ||
| 7135 | goto out; | ||
| 7136 | printk(KERN_INFO "\texpander(0x%016llx): handle changed" | ||
| 7137 | " from(0x%04x) to (0x%04x)!!!\n", | ||
| 7138 | (unsigned long long)sas_expander->sas_address, | ||
| 7139 | sas_expander->handle, handle); | ||
| 7140 | sas_expander->handle = handle; | ||
| 7141 | for (i = 0 ; i < sas_expander->num_phys ; i++) | ||
| 7142 | sas_expander->phy[i].handle = handle; | ||
| 7143 | goto out; | ||
| 7144 | } | ||
| 7145 | out: | ||
| 7146 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | ||
| 7147 | } | ||
| 7148 | |||
| 7149 | /** | ||
| 7150 | * _scsih_search_responding_expanders - | ||
| 7151 | * @ioc: per adapter object | ||
| 7152 | * | ||
| 7153 | * After host reset, find out whether devices are still responding. | ||
| 7154 | * If not remove. | ||
| 7155 | * | ||
| 7156 | * Return nothing. | ||
| 7157 | */ | ||
| 7158 | static void | ||
| 7159 | _scsih_search_responding_expanders(struct MPT2SAS_ADAPTER *ioc) | ||
| 7160 | { | ||
| 7161 | Mpi2ExpanderPage0_t expander_pg0; | ||
| 7162 | Mpi2ConfigReply_t mpi_reply; | ||
| 7163 | u16 ioc_status; | ||
| 7164 | u64 sas_address; | ||
| 7165 | u16 handle; | ||
| 7166 | |||
| 7167 | printk(MPT2SAS_INFO_FMT "search for expanders: start\n", ioc->name); | ||
| 7168 | |||
| 7169 | if (list_empty(&ioc->sas_expander_list)) | ||
| 7170 | goto out; | ||
| 7171 | |||
| 7172 | handle = 0xFFFF; | ||
| 7173 | while (!(mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0, | ||
| 7174 | MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL, handle))) { | ||
| 7175 | |||
| 7176 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
| 7177 | MPI2_IOCSTATUS_MASK; | ||
| 7178 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) | ||
| 7179 | break; | ||
| 7180 | |||
| 7181 | handle = le16_to_cpu(expander_pg0.DevHandle); | ||
| 7182 | sas_address = le64_to_cpu(expander_pg0.SASAddress); | ||
| 7183 | printk(KERN_INFO "\texpander present: handle(0x%04x), " | ||
| 7184 | "sas_addr(0x%016llx)\n", handle, | ||
| 7185 | (unsigned long long)sas_address); | ||
| 7186 | _scsih_mark_responding_expander(ioc, sas_address, handle); | ||
| 7187 | } | ||
| 7188 | |||
| 7189 | out: | ||
| 7190 | printk(MPT2SAS_INFO_FMT "search for expanders: complete\n", ioc->name); | ||
| 7191 | } | ||
| 7192 | |||
| 7193 | /** | ||
| 7194 | * _scsih_remove_unresponding_sas_devices - removing unresponding devices | ||
| 7195 | * @ioc: per adapter object | ||
| 7196 | * | ||
| 7197 | * Return nothing. | ||
| 7198 | */ | ||
| 7199 | static void | ||
| 7200 | _scsih_remove_unresponding_sas_devices(struct MPT2SAS_ADAPTER *ioc) | ||
| 7201 | { | ||
| 7202 | struct _sas_device *sas_device, *sas_device_next; | ||
| 7203 | struct _sas_node *sas_expander, *sas_expander_next; | ||
| 7204 | struct _raid_device *raid_device, *raid_device_next; | ||
| 7205 | struct list_head tmp_list; | ||
| 7206 | unsigned long flags; | ||
| 7207 | LIST_HEAD(head); | ||
| 7208 | |||
| 7209 | printk(MPT2SAS_INFO_FMT "removing unresponding devices: start\n", | ||
| 7210 | ioc->name); | ||
| 7211 | |||
| 7212 | /* removing unresponding end devices */ | ||
| 7213 | printk(MPT2SAS_INFO_FMT "removing unresponding devices: end-devices\n", | ||
| 7214 | ioc->name); | ||
| 7215 | |||
| 7216 | /* | ||
| 7217 | * Iterate, pulling off devices marked as non-responding. We become the | ||
| 7218 | * owner for the reference the list had on any object we prune. | ||
| 7219 | */ | ||
| 7220 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 7221 | list_for_each_entry_safe(sas_device, sas_device_next, | ||
| 7222 | &ioc->sas_device_list, list) { | ||
| 7223 | if (!sas_device->responding) | ||
| 7224 | list_move_tail(&sas_device->list, &head); | ||
| 7225 | else | ||
| 7226 | sas_device->responding = 0; | ||
| 7227 | } | ||
| 7228 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 7229 | |||
| 7230 | /* | ||
| 7231 | * Now, uninitialize and remove the unresponding devices we pruned. | ||
| 7232 | */ | ||
| 7233 | list_for_each_entry_safe(sas_device, sas_device_next, &head, list) { | ||
| 7234 | _scsih_remove_device(ioc, sas_device); | ||
| 7235 | list_del_init(&sas_device->list); | ||
| 7236 | sas_device_put(sas_device); | ||
| 7237 | } | ||
| 7238 | |||
| 7239 | /* removing unresponding volumes */ | ||
| 7240 | if (ioc->ir_firmware) { | ||
| 7241 | printk(MPT2SAS_INFO_FMT "removing unresponding devices: " | ||
| 7242 | "volumes\n", ioc->name); | ||
| 7243 | list_for_each_entry_safe(raid_device, raid_device_next, | ||
| 7244 | &ioc->raid_device_list, list) { | ||
| 7245 | if (!raid_device->responding) | ||
| 7246 | _scsih_sas_volume_delete(ioc, | ||
| 7247 | raid_device->handle); | ||
| 7248 | else | ||
| 7249 | raid_device->responding = 0; | ||
| 7250 | } | ||
| 7251 | } | ||
| 7252 | /* removing unresponding expanders */ | ||
| 7253 | printk(MPT2SAS_INFO_FMT "removing unresponding devices: expanders\n", | ||
| 7254 | ioc->name); | ||
| 7255 | spin_lock_irqsave(&ioc->sas_node_lock, flags); | ||
| 7256 | INIT_LIST_HEAD(&tmp_list); | ||
| 7257 | list_for_each_entry_safe(sas_expander, sas_expander_next, | ||
| 7258 | &ioc->sas_expander_list, list) { | ||
| 7259 | if (!sas_expander->responding) | ||
| 7260 | list_move_tail(&sas_expander->list, &tmp_list); | ||
| 7261 | else | ||
| 7262 | sas_expander->responding = 0; | ||
| 7263 | } | ||
| 7264 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | ||
| 7265 | list_for_each_entry_safe(sas_expander, sas_expander_next, &tmp_list, | ||
| 7266 | list) { | ||
| 7267 | list_del(&sas_expander->list); | ||
| 7268 | _scsih_expander_node_remove(ioc, sas_expander); | ||
| 7269 | } | ||
| 7270 | printk(MPT2SAS_INFO_FMT "removing unresponding devices: complete\n", | ||
| 7271 | ioc->name); | ||
| 7272 | /* unblock devices */ | ||
| 7273 | _scsih_ublock_io_all_device(ioc); | ||
| 7274 | } | ||
| 7275 | |||
| 7276 | static void | ||
| 7277 | _scsih_refresh_expander_links(struct MPT2SAS_ADAPTER *ioc, | ||
| 7278 | struct _sas_node *sas_expander, u16 handle) | ||
| 7279 | { | ||
| 7280 | Mpi2ExpanderPage1_t expander_pg1; | ||
| 7281 | Mpi2ConfigReply_t mpi_reply; | ||
| 7282 | int i; | ||
| 7283 | |||
| 7284 | for (i = 0 ; i < sas_expander->num_phys ; i++) { | ||
| 7285 | if ((mpt2sas_config_get_expander_pg1(ioc, &mpi_reply, | ||
| 7286 | &expander_pg1, i, handle))) { | ||
| 7287 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 7288 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 7289 | return; | ||
| 7290 | } | ||
| 7291 | |||
| 7292 | mpt2sas_transport_update_links(ioc, sas_expander->sas_address, | ||
| 7293 | le16_to_cpu(expander_pg1.AttachedDevHandle), i, | ||
| 7294 | expander_pg1.NegotiatedLinkRate >> 4); | ||
| 7295 | } | ||
| 7296 | } | ||
| 7297 | |||
| 7298 | /** | ||
| 7299 | * _scsih_scan_for_devices_after_reset - scan for devices after host reset | ||
| 7300 | * @ioc: per adapter object | ||
| 7301 | * | ||
| 7302 | * Return nothing. | ||
| 7303 | */ | ||
| 7304 | static void | ||
| 7305 | _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc) | ||
| 7306 | { | ||
| 7307 | Mpi2ExpanderPage0_t expander_pg0; | ||
| 7308 | Mpi2SasDevicePage0_t sas_device_pg0; | ||
| 7309 | Mpi2RaidVolPage1_t volume_pg1; | ||
| 7310 | Mpi2RaidVolPage0_t volume_pg0; | ||
| 7311 | Mpi2RaidPhysDiskPage0_t pd_pg0; | ||
| 7312 | Mpi2EventIrConfigElement_t element; | ||
| 7313 | Mpi2ConfigReply_t mpi_reply; | ||
| 7314 | u8 phys_disk_num; | ||
| 7315 | u16 ioc_status; | ||
| 7316 | u16 handle, parent_handle; | ||
| 7317 | u64 sas_address; | ||
| 7318 | struct _sas_device *sas_device; | ||
| 7319 | struct _sas_node *expander_device; | ||
| 7320 | static struct _raid_device *raid_device; | ||
| 7321 | u8 retry_count; | ||
| 7322 | unsigned long flags; | ||
| 7323 | |||
| 7324 | printk(MPT2SAS_INFO_FMT "scan devices: start\n", ioc->name); | ||
| 7325 | |||
| 7326 | _scsih_sas_host_refresh(ioc); | ||
| 7327 | |||
| 7328 | printk(MPT2SAS_INFO_FMT "\tscan devices: expanders start\n", | ||
| 7329 | ioc->name); | ||
| 7330 | /* expanders */ | ||
| 7331 | handle = 0xFFFF; | ||
| 7332 | while (!(mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0, | ||
| 7333 | MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL, handle))) { | ||
| 7334 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
| 7335 | MPI2_IOCSTATUS_MASK; | ||
| 7336 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { | ||
| 7337 | printk(MPT2SAS_INFO_FMT "\tbreak from expander scan: " | ||
| 7338 | "ioc_status(0x%04x), loginfo(0x%08x)\n", | ||
| 7339 | ioc->name, ioc_status, | ||
| 7340 | le32_to_cpu(mpi_reply.IOCLogInfo)); | ||
| 7341 | break; | ||
| 7342 | } | ||
| 7343 | handle = le16_to_cpu(expander_pg0.DevHandle); | ||
| 7344 | spin_lock_irqsave(&ioc->sas_node_lock, flags); | ||
| 7345 | expander_device = mpt2sas_scsih_expander_find_by_sas_address( | ||
| 7346 | ioc, le64_to_cpu(expander_pg0.SASAddress)); | ||
| 7347 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | ||
| 7348 | if (expander_device) | ||
| 7349 | _scsih_refresh_expander_links(ioc, expander_device, | ||
| 7350 | handle); | ||
| 7351 | else { | ||
| 7352 | printk(MPT2SAS_INFO_FMT "\tBEFORE adding expander: " | ||
| 7353 | "handle (0x%04x), sas_addr(0x%016llx)\n", | ||
| 7354 | ioc->name, handle, (unsigned long long) | ||
| 7355 | le64_to_cpu(expander_pg0.SASAddress)); | ||
| 7356 | _scsih_expander_add(ioc, handle); | ||
| 7357 | printk(MPT2SAS_INFO_FMT "\tAFTER adding expander: " | ||
| 7358 | "handle (0x%04x), sas_addr(0x%016llx)\n", | ||
| 7359 | ioc->name, handle, (unsigned long long) | ||
| 7360 | le64_to_cpu(expander_pg0.SASAddress)); | ||
| 7361 | } | ||
| 7362 | } | ||
| 7363 | |||
| 7364 | printk(MPT2SAS_INFO_FMT "\tscan devices: expanders complete\n", | ||
| 7365 | ioc->name); | ||
| 7366 | |||
| 7367 | if (!ioc->ir_firmware) | ||
| 7368 | goto skip_to_sas; | ||
| 7369 | |||
| 7370 | printk(MPT2SAS_INFO_FMT "\tscan devices phys disk start\n", ioc->name); | ||
| 7371 | /* phys disk */ | ||
| 7372 | phys_disk_num = 0xFF; | ||
| 7373 | while (!(mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply, | ||
| 7374 | &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM, | ||
| 7375 | phys_disk_num))) { | ||
| 7376 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
| 7377 | MPI2_IOCSTATUS_MASK; | ||
| 7378 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { | ||
| 7379 | printk(MPT2SAS_INFO_FMT "\tbreak from phys disk scan:" | ||
| 7380 | "ioc_status(0x%04x), loginfo(0x%08x)\n", | ||
| 7381 | ioc->name, ioc_status, | ||
| 7382 | le32_to_cpu(mpi_reply.IOCLogInfo)); | ||
| 7383 | break; | ||
| 7384 | } | ||
| 7385 | phys_disk_num = pd_pg0.PhysDiskNum; | ||
| 7386 | handle = le16_to_cpu(pd_pg0.DevHandle); | ||
| 7387 | sas_device = mpt2sas_get_sdev_by_handle(ioc, handle); | ||
| 7388 | if (sas_device) { | ||
| 7389 | sas_device_put(sas_device); | ||
| 7390 | continue; | ||
| 7391 | } | ||
| 7392 | if (mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, | ||
| 7393 | &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, | ||
| 7394 | handle) != 0) | ||
| 7395 | continue; | ||
| 7396 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
| 7397 | MPI2_IOCSTATUS_MASK; | ||
| 7398 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { | ||
| 7399 | printk(MPT2SAS_INFO_FMT "\tbreak from phys disk scan " | ||
| 7400 | "ioc_status(0x%04x), loginfo(0x%08x)\n", | ||
| 7401 | ioc->name, ioc_status, | ||
| 7402 | le32_to_cpu(mpi_reply.IOCLogInfo)); | ||
| 7403 | break; | ||
| 7404 | } | ||
| 7405 | parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle); | ||
| 7406 | if (!_scsih_get_sas_address(ioc, parent_handle, | ||
| 7407 | &sas_address)) { | ||
| 7408 | printk(MPT2SAS_INFO_FMT "\tBEFORE adding phys disk: " | ||
| 7409 | " handle (0x%04x), sas_addr(0x%016llx)\n", | ||
| 7410 | ioc->name, handle, (unsigned long long) | ||
| 7411 | le64_to_cpu(sas_device_pg0.SASAddress)); | ||
| 7412 | mpt2sas_transport_update_links(ioc, sas_address, | ||
| 7413 | handle, sas_device_pg0.PhyNum, | ||
| 7414 | MPI2_SAS_NEG_LINK_RATE_1_5); | ||
| 7415 | set_bit(handle, ioc->pd_handles); | ||
| 7416 | retry_count = 0; | ||
| 7417 | /* This will retry adding the end device. | ||
| 7418 | * _scsih_add_device() will decide on retries and | ||
| 7419 | * return "1" when it should be retried | ||
| 7420 | */ | ||
| 7421 | while (_scsih_add_device(ioc, handle, retry_count++, | ||
| 7422 | 1)) { | ||
| 7423 | ssleep(1); | ||
| 7424 | } | ||
| 7425 | printk(MPT2SAS_INFO_FMT "\tAFTER adding phys disk: " | ||
| 7426 | " handle (0x%04x), sas_addr(0x%016llx)\n", | ||
| 7427 | ioc->name, handle, (unsigned long long) | ||
| 7428 | le64_to_cpu(sas_device_pg0.SASAddress)); | ||
| 7429 | } | ||
| 7430 | } | ||
| 7431 | |||
| 7432 | printk(MPT2SAS_INFO_FMT "\tscan devices: phys disk complete\n", | ||
| 7433 | ioc->name); | ||
| 7434 | |||
| 7435 | printk(MPT2SAS_INFO_FMT "\tscan devices: volumes start\n", ioc->name); | ||
| 7436 | /* volumes */ | ||
| 7437 | handle = 0xFFFF; | ||
| 7438 | while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply, | ||
| 7439 | &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) { | ||
| 7440 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
| 7441 | MPI2_IOCSTATUS_MASK; | ||
| 7442 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { | ||
| 7443 | printk(MPT2SAS_INFO_FMT "\tbreak from volume scan: " | ||
| 7444 | "ioc_status(0x%04x), loginfo(0x%08x)\n", | ||
| 7445 | ioc->name, ioc_status, | ||
| 7446 | le32_to_cpu(mpi_reply.IOCLogInfo)); | ||
| 7447 | break; | ||
| 7448 | } | ||
| 7449 | handle = le16_to_cpu(volume_pg1.DevHandle); | ||
| 7450 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | ||
| 7451 | raid_device = _scsih_raid_device_find_by_wwid(ioc, | ||
| 7452 | le64_to_cpu(volume_pg1.WWID)); | ||
| 7453 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); | ||
| 7454 | if (raid_device) | ||
| 7455 | continue; | ||
| 7456 | if (mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, | ||
| 7457 | &volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle, | ||
| 7458 | sizeof(Mpi2RaidVolPage0_t))) | ||
| 7459 | continue; | ||
| 7460 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
| 7461 | MPI2_IOCSTATUS_MASK; | ||
| 7462 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { | ||
| 7463 | printk(MPT2SAS_INFO_FMT "\tbreak from volume scan: " | ||
| 7464 | "ioc_status(0x%04x), loginfo(0x%08x)\n", | ||
| 7465 | ioc->name, ioc_status, | ||
| 7466 | le32_to_cpu(mpi_reply.IOCLogInfo)); | ||
| 7467 | break; | ||
| 7468 | } | ||
| 7469 | if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL || | ||
| 7470 | volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE || | ||
| 7471 | volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED) { | ||
| 7472 | memset(&element, 0, sizeof(Mpi2EventIrConfigElement_t)); | ||
| 7473 | element.ReasonCode = MPI2_EVENT_IR_CHANGE_RC_ADDED; | ||
| 7474 | element.VolDevHandle = volume_pg1.DevHandle; | ||
| 7475 | printk(MPT2SAS_INFO_FMT "\tBEFORE adding volume: " | ||
| 7476 | " handle (0x%04x)\n", ioc->name, | ||
| 7477 | volume_pg1.DevHandle); | ||
| 7478 | _scsih_sas_volume_add(ioc, &element); | ||
| 7479 | printk(MPT2SAS_INFO_FMT "\tAFTER adding volume: " | ||
| 7480 | " handle (0x%04x)\n", ioc->name, | ||
| 7481 | volume_pg1.DevHandle); | ||
| 7482 | } | ||
| 7483 | } | ||
| 7484 | |||
| 7485 | printk(MPT2SAS_INFO_FMT "\tscan devices: volumes complete\n", | ||
| 7486 | ioc->name); | ||
| 7487 | |||
| 7488 | skip_to_sas: | ||
| 7489 | |||
| 7490 | printk(MPT2SAS_INFO_FMT "\tscan devices: end devices start\n", | ||
| 7491 | ioc->name); | ||
| 7492 | /* sas devices */ | ||
| 7493 | handle = 0xFFFF; | ||
| 7494 | while (!(mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, | ||
| 7495 | &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE, | ||
| 7496 | handle))) { | ||
| 7497 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
| 7498 | MPI2_IOCSTATUS_MASK; | ||
| 7499 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { | ||
| 7500 | printk(MPT2SAS_INFO_FMT "\tbreak from end device scan:" | ||
| 7501 | " ioc_status(0x%04x), loginfo(0x%08x)\n", | ||
| 7502 | ioc->name, ioc_status, | ||
| 7503 | le32_to_cpu(mpi_reply.IOCLogInfo)); | ||
| 7504 | break; | ||
| 7505 | } | ||
| 7506 | handle = le16_to_cpu(sas_device_pg0.DevHandle); | ||
| 7507 | if (!(_scsih_is_end_device( | ||
| 7508 | le32_to_cpu(sas_device_pg0.DeviceInfo)))) | ||
| 7509 | continue; | ||
| 7510 | sas_device = mpt2sas_get_sdev_by_addr(ioc, | ||
| 7511 | le64_to_cpu(sas_device_pg0.SASAddress)); | ||
| 7512 | if (sas_device) { | ||
| 7513 | sas_device_put(sas_device); | ||
| 7514 | continue; | ||
| 7515 | } | ||
| 7516 | parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle); | ||
| 7517 | if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) { | ||
| 7518 | printk(MPT2SAS_INFO_FMT "\tBEFORE adding end device: " | ||
| 7519 | "handle (0x%04x), sas_addr(0x%016llx)\n", | ||
| 7520 | ioc->name, handle, (unsigned long long) | ||
| 7521 | le64_to_cpu(sas_device_pg0.SASAddress)); | ||
| 7522 | mpt2sas_transport_update_links(ioc, sas_address, handle, | ||
| 7523 | sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5); | ||
| 7524 | retry_count = 0; | ||
| 7525 | /* This will retry adding the end device. | ||
| 7526 | * _scsih_add_device() will decide on retries and | ||
| 7527 | * return "1" when it should be retried | ||
| 7528 | */ | ||
| 7529 | while (_scsih_add_device(ioc, handle, retry_count++, | ||
| 7530 | 0)) { | ||
| 7531 | ssleep(1); | ||
| 7532 | } | ||
| 7533 | printk(MPT2SAS_INFO_FMT "\tAFTER adding end device: " | ||
| 7534 | "handle (0x%04x), sas_addr(0x%016llx)\n", | ||
| 7535 | ioc->name, handle, (unsigned long long) | ||
| 7536 | le64_to_cpu(sas_device_pg0.SASAddress)); | ||
| 7537 | } | ||
| 7538 | } | ||
| 7539 | |||
| 7540 | printk(MPT2SAS_INFO_FMT "\tscan devices: end devices complete\n", | ||
| 7541 | ioc->name); | ||
| 7542 | |||
| 7543 | printk(MPT2SAS_INFO_FMT "scan devices: complete\n", ioc->name); | ||
| 7544 | } | ||
| 7545 | |||
| 7546 | |||
| 7547 | /** | ||
| 7548 | * mpt2sas_scsih_reset_handler - reset callback handler (for scsih) | ||
| 7549 | * @ioc: per adapter object | ||
| 7550 | * @reset_phase: phase | ||
| 7551 | * | ||
| 7552 | * The handler for doing any required cleanup or initialization. | ||
| 7553 | * | ||
| 7554 | * The reset phase can be MPT2_IOC_PRE_RESET, MPT2_IOC_AFTER_RESET, | ||
| 7555 | * MPT2_IOC_DONE_RESET | ||
| 7556 | * | ||
| 7557 | * Return nothing. | ||
| 7558 | */ | ||
| 7559 | void | ||
| 7560 | mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase) | ||
| 7561 | { | ||
| 7562 | switch (reset_phase) { | ||
| 7563 | case MPT2_IOC_PRE_RESET: | ||
| 7564 | dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " | ||
| 7565 | "MPT2_IOC_PRE_RESET\n", ioc->name, __func__)); | ||
| 7566 | break; | ||
| 7567 | case MPT2_IOC_AFTER_RESET: | ||
| 7568 | dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " | ||
| 7569 | "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__)); | ||
| 7570 | if (ioc->scsih_cmds.status & MPT2_CMD_PENDING) { | ||
| 7571 | ioc->scsih_cmds.status |= MPT2_CMD_RESET; | ||
| 7572 | mpt2sas_base_free_smid(ioc, ioc->scsih_cmds.smid); | ||
| 7573 | complete(&ioc->scsih_cmds.done); | ||
| 7574 | } | ||
| 7575 | if (ioc->tm_cmds.status & MPT2_CMD_PENDING) { | ||
| 7576 | ioc->tm_cmds.status |= MPT2_CMD_RESET; | ||
| 7577 | mpt2sas_base_free_smid(ioc, ioc->tm_cmds.smid); | ||
| 7578 | complete(&ioc->tm_cmds.done); | ||
| 7579 | } | ||
| 7580 | _scsih_fw_event_cleanup_queue(ioc); | ||
| 7581 | _scsih_flush_running_cmds(ioc); | ||
| 7582 | break; | ||
| 7583 | case MPT2_IOC_DONE_RESET: | ||
| 7584 | dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " | ||
| 7585 | "MPT2_IOC_DONE_RESET\n", ioc->name, __func__)); | ||
| 7586 | _scsih_sas_host_refresh(ioc); | ||
| 7587 | _scsih_prep_device_scan(ioc); | ||
| 7588 | _scsih_search_responding_sas_devices(ioc); | ||
| 7589 | _scsih_search_responding_raid_devices(ioc); | ||
| 7590 | _scsih_search_responding_expanders(ioc); | ||
| 7591 | if ((!ioc->is_driver_loading) && !(disable_discovery > 0 && | ||
| 7592 | !ioc->sas_hba.num_phys)) { | ||
| 7593 | _scsih_prep_device_scan(ioc); | ||
| 7594 | _scsih_search_responding_sas_devices(ioc); | ||
| 7595 | _scsih_search_responding_raid_devices(ioc); | ||
| 7596 | _scsih_search_responding_expanders(ioc); | ||
| 7597 | _scsih_error_recovery_delete_devices(ioc); | ||
| 7598 | } | ||
| 7599 | break; | ||
| 7600 | } | ||
| 7601 | } | ||
| 7602 | |||
| 7603 | /** | ||
| 7604 | * _firmware_event_work - delayed task for processing firmware events | ||
| 7605 | * @ioc: per adapter object | ||
| 7606 | * @work: equal to the fw_event_work object | ||
| 7607 | * Context: user. | ||
| 7608 | * | ||
| 7609 | * Return nothing. | ||
| 7610 | */ | ||
| 7611 | static void | ||
| 7612 | _firmware_event_work(struct work_struct *work) | ||
| 7613 | { | ||
| 7614 | struct fw_event_work *fw_event = container_of(work, | ||
| 7615 | struct fw_event_work, delayed_work.work); | ||
| 7616 | struct MPT2SAS_ADAPTER *ioc = fw_event->ioc; | ||
| 7617 | |||
| 7618 | _scsih_fw_event_del_from_list(ioc, fw_event); | ||
| 7619 | |||
| 7620 | /* the queue is being flushed so ignore this event */ | ||
| 7621 | if (ioc->remove_host || ioc->pci_error_recovery) { | ||
| 7622 | fw_event_work_put(fw_event); | ||
| 7623 | return; | ||
| 7624 | } | ||
| 7625 | |||
| 7626 | switch (fw_event->event) { | ||
| 7627 | case MPT2SAS_REMOVE_UNRESPONDING_DEVICES: | ||
| 7628 | while (scsi_host_in_recovery(ioc->shost) || | ||
| 7629 | ioc->shost_recovery) { | ||
| 7630 | /* | ||
| 7631 | * If we're unloading, bail. Otherwise, this can become | ||
| 7632 | * an infinite loop. | ||
| 7633 | */ | ||
| 7634 | if (ioc->remove_host) | ||
| 7635 | goto out; | ||
| 7636 | |||
| 7637 | ssleep(1); | ||
| 7638 | } | ||
| 7639 | _scsih_remove_unresponding_sas_devices(ioc); | ||
| 7640 | _scsih_scan_for_devices_after_reset(ioc); | ||
| 7641 | break; | ||
| 7642 | case MPT2SAS_PORT_ENABLE_COMPLETE: | ||
| 7643 | ioc->start_scan = 0; | ||
| 7644 | |||
| 7645 | if (missing_delay[0] != -1 && missing_delay[1] != -1) | ||
| 7646 | mpt2sas_base_update_missing_delay(ioc, missing_delay[0], | ||
| 7647 | missing_delay[1]); | ||
| 7648 | |||
| 7649 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "port enable: complete " | ||
| 7650 | "from worker thread\n", ioc->name)); | ||
| 7651 | break; | ||
| 7652 | case MPT2SAS_TURN_ON_PFA_LED: | ||
| 7653 | _scsih_turn_on_pfa_led(ioc, fw_event->device_handle); | ||
| 7654 | break; | ||
| 7655 | case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST: | ||
| 7656 | _scsih_sas_topology_change_event(ioc, fw_event); | ||
| 7657 | break; | ||
| 7658 | case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE: | ||
| 7659 | _scsih_sas_device_status_change_event(ioc, | ||
| 7660 | fw_event); | ||
| 7661 | break; | ||
| 7662 | case MPI2_EVENT_SAS_DISCOVERY: | ||
| 7663 | _scsih_sas_discovery_event(ioc, | ||
| 7664 | fw_event); | ||
| 7665 | break; | ||
| 7666 | case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE: | ||
| 7667 | _scsih_sas_broadcast_primitive_event(ioc, | ||
| 7668 | fw_event); | ||
| 7669 | break; | ||
| 7670 | case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE: | ||
| 7671 | _scsih_sas_enclosure_dev_status_change_event(ioc, | ||
| 7672 | fw_event); | ||
| 7673 | break; | ||
| 7674 | case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST: | ||
| 7675 | _scsih_sas_ir_config_change_event(ioc, fw_event); | ||
| 7676 | break; | ||
| 7677 | case MPI2_EVENT_IR_VOLUME: | ||
| 7678 | _scsih_sas_ir_volume_event(ioc, fw_event); | ||
| 7679 | break; | ||
| 7680 | case MPI2_EVENT_IR_PHYSICAL_DISK: | ||
| 7681 | _scsih_sas_ir_physical_disk_event(ioc, fw_event); | ||
| 7682 | break; | ||
| 7683 | case MPI2_EVENT_IR_OPERATION_STATUS: | ||
| 7684 | _scsih_sas_ir_operation_status_event(ioc, fw_event); | ||
| 7685 | break; | ||
| 7686 | } | ||
| 7687 | out: | ||
| 7688 | fw_event_work_put(fw_event); | ||
| 7689 | } | ||
| 7690 | |||
| 7691 | /** | ||
| 7692 | * mpt2sas_scsih_event_callback - firmware event handler (called at ISR time) | ||
| 7693 | * @ioc: per adapter object | ||
| 7694 | * @msix_index: MSIX table index supplied by the OS | ||
| 7695 | * @reply: reply message frame(lower 32bit addr) | ||
| 7696 | * Context: interrupt. | ||
| 7697 | * | ||
| 7698 | * This function merely adds a new work task into ioc->firmware_event_thread. | ||
| 7699 | * The tasks are worked from _firmware_event_work in user context. | ||
| 7700 | * | ||
| 7701 | * Returns void. | ||
| 7702 | */ | ||
| 7703 | void | ||
| 7704 | mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, | ||
| 7705 | u32 reply) | ||
| 7706 | { | ||
| 7707 | struct fw_event_work *fw_event; | ||
| 7708 | Mpi2EventNotificationReply_t *mpi_reply; | ||
| 7709 | u16 event; | ||
| 7710 | u16 sz; | ||
| 7711 | |||
| 7712 | /* events turned off due to host reset or driver unloading */ | ||
| 7713 | if (ioc->remove_host || ioc->pci_error_recovery) | ||
| 7714 | return; | ||
| 7715 | |||
| 7716 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | ||
| 7717 | |||
| 7718 | if (unlikely(!mpi_reply)) { | ||
| 7719 | printk(MPT2SAS_ERR_FMT "mpi_reply not valid at %s:%d/%s()!\n", | ||
| 7720 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 7721 | return; | ||
| 7722 | } | ||
| 7723 | |||
| 7724 | event = le16_to_cpu(mpi_reply->Event); | ||
| 7725 | |||
| 7726 | switch (event) { | ||
| 7727 | /* handle these */ | ||
| 7728 | case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE: | ||
| 7729 | { | ||
| 7730 | Mpi2EventDataSasBroadcastPrimitive_t *baen_data = | ||
| 7731 | (Mpi2EventDataSasBroadcastPrimitive_t *) | ||
| 7732 | mpi_reply->EventData; | ||
| 7733 | |||
| 7734 | if (baen_data->Primitive != | ||
| 7735 | MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT) | ||
| 7736 | return; | ||
| 7737 | |||
| 7738 | if (ioc->broadcast_aen_busy) { | ||
| 7739 | ioc->broadcast_aen_pending++; | ||
| 7740 | return; | ||
| 7741 | } else | ||
| 7742 | ioc->broadcast_aen_busy = 1; | ||
| 7743 | break; | ||
| 7744 | } | ||
| 7745 | |||
| 7746 | case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST: | ||
| 7747 | _scsih_check_topo_delete_events(ioc, | ||
| 7748 | (Mpi2EventDataSasTopologyChangeList_t *) | ||
| 7749 | mpi_reply->EventData); | ||
| 7750 | break; | ||
| 7751 | case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST: | ||
| 7752 | _scsih_check_ir_config_unhide_events(ioc, | ||
| 7753 | (Mpi2EventDataIrConfigChangeList_t *) | ||
| 7754 | mpi_reply->EventData); | ||
| 7755 | break; | ||
| 7756 | case MPI2_EVENT_IR_VOLUME: | ||
| 7757 | _scsih_check_volume_delete_events(ioc, | ||
| 7758 | (Mpi2EventDataIrVolume_t *) | ||
| 7759 | mpi_reply->EventData); | ||
| 7760 | break; | ||
| 7761 | case MPI2_EVENT_LOG_ENTRY_ADDED: | ||
| 7762 | { | ||
| 7763 | Mpi2EventDataLogEntryAdded_t *log_entry; | ||
| 7764 | __le32 *log_code; | ||
| 7765 | |||
| 7766 | if (!ioc->is_warpdrive) | ||
| 7767 | break; | ||
| 7768 | |||
| 7769 | log_entry = (Mpi2EventDataLogEntryAdded_t *) | ||
| 7770 | mpi_reply->EventData; | ||
| 7771 | log_code = (__le32 *)log_entry->LogData; | ||
| 7772 | |||
| 7773 | if (le16_to_cpu(log_entry->LogEntryQualifier) | ||
| 7774 | != MPT2_WARPDRIVE_LOGENTRY) | ||
| 7775 | break; | ||
| 7776 | |||
| 7777 | switch (le32_to_cpu(*log_code)) { | ||
| 7778 | case MPT2_WARPDRIVE_LC_SSDT: | ||
| 7779 | printk(MPT2SAS_WARN_FMT "WarpDrive Warning: " | ||
| 7780 | "IO Throttling has occurred in the WarpDrive " | ||
| 7781 | "subsystem. Check WarpDrive documentation for " | ||
| 7782 | "additional details.\n", ioc->name); | ||
| 7783 | break; | ||
| 7784 | case MPT2_WARPDRIVE_LC_SSDLW: | ||
| 7785 | printk(MPT2SAS_WARN_FMT "WarpDrive Warning: " | ||
| 7786 | "Program/Erase Cycles for the WarpDrive subsystem " | ||
| 7787 | "in degraded range. Check WarpDrive documentation " | ||
| 7788 | "for additional details.\n", ioc->name); | ||
| 7789 | break; | ||
| 7790 | case MPT2_WARPDRIVE_LC_SSDLF: | ||
| 7791 | printk(MPT2SAS_ERR_FMT "WarpDrive Fatal Error: " | ||
| 7792 | "There are no Program/Erase Cycles for the " | ||
| 7793 | "WarpDrive subsystem. The storage device will be " | ||
| 7794 | "in read-only mode. Check WarpDrive documentation " | ||
| 7795 | "for additional details.\n", ioc->name); | ||
| 7796 | break; | ||
| 7797 | case MPT2_WARPDRIVE_LC_BRMF: | ||
| 7798 | printk(MPT2SAS_ERR_FMT "WarpDrive Fatal Error: " | ||
| 7799 | "The Backup Rail Monitor has failed on the " | ||
| 7800 | "WarpDrive subsystem. Check WarpDrive " | ||
| 7801 | "documentation for additional details.\n", | ||
| 7802 | ioc->name); | ||
| 7803 | break; | ||
| 7804 | } | ||
| 7805 | |||
| 7806 | break; | ||
| 7807 | } | ||
| 7808 | case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE: | ||
| 7809 | case MPI2_EVENT_IR_OPERATION_STATUS: | ||
| 7810 | case MPI2_EVENT_SAS_DISCOVERY: | ||
| 7811 | case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE: | ||
| 7812 | case MPI2_EVENT_IR_PHYSICAL_DISK: | ||
| 7813 | break; | ||
| 7814 | |||
| 7815 | case MPI2_EVENT_TEMP_THRESHOLD: | ||
| 7816 | _scsih_temp_threshold_events(ioc, | ||
| 7817 | (Mpi2EventDataTemperature_t *) | ||
| 7818 | mpi_reply->EventData); | ||
| 7819 | break; | ||
| 7820 | |||
| 7821 | default: /* ignore the rest */ | ||
| 7822 | return; | ||
| 7823 | } | ||
| 7824 | |||
| 7825 | sz = le16_to_cpu(mpi_reply->EventDataLength) * 4; | ||
| 7826 | fw_event = alloc_fw_event_work(sz); | ||
| 7827 | if (!fw_event) { | ||
| 7828 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 7829 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 7830 | return; | ||
| 7831 | } | ||
| 7832 | |||
| 7833 | memcpy(fw_event->event_data, mpi_reply->EventData, sz); | ||
| 7834 | fw_event->ioc = ioc; | ||
| 7835 | fw_event->VF_ID = mpi_reply->VF_ID; | ||
| 7836 | fw_event->VP_ID = mpi_reply->VP_ID; | ||
| 7837 | fw_event->event = event; | ||
| 7838 | _scsih_fw_event_add(ioc, fw_event); | ||
| 7839 | fw_event_work_put(fw_event); | ||
| 7840 | return; | ||
| 7841 | } | ||
| 7842 | |||
| 7843 | /* shost template */ | ||
| 7844 | static struct scsi_host_template scsih_driver_template = { | ||
| 7845 | .module = THIS_MODULE, | ||
| 7846 | .name = "Fusion MPT SAS Host", | ||
| 7847 | .proc_name = MPT2SAS_DRIVER_NAME, | ||
| 7848 | .queuecommand = _scsih_qcmd, | ||
| 7849 | .target_alloc = _scsih_target_alloc, | ||
| 7850 | .slave_alloc = _scsih_slave_alloc, | ||
| 7851 | .slave_configure = _scsih_slave_configure, | ||
| 7852 | .target_destroy = _scsih_target_destroy, | ||
| 7853 | .slave_destroy = _scsih_slave_destroy, | ||
| 7854 | .scan_finished = _scsih_scan_finished, | ||
| 7855 | .scan_start = _scsih_scan_start, | ||
| 7856 | .change_queue_depth = _scsih_change_queue_depth, | ||
| 7857 | .eh_abort_handler = _scsih_abort, | ||
| 7858 | .eh_device_reset_handler = _scsih_dev_reset, | ||
| 7859 | .eh_target_reset_handler = _scsih_target_reset, | ||
| 7860 | .eh_host_reset_handler = _scsih_host_reset, | ||
| 7861 | .bios_param = _scsih_bios_param, | ||
| 7862 | .can_queue = 1, | ||
| 7863 | .this_id = -1, | ||
| 7864 | .sg_tablesize = MPT2SAS_SG_DEPTH, | ||
| 7865 | .max_sectors = 32767, | ||
| 7866 | .cmd_per_lun = 7, | ||
| 7867 | .use_clustering = ENABLE_CLUSTERING, | ||
| 7868 | .shost_attrs = mpt2sas_host_attrs, | ||
| 7869 | .sdev_attrs = mpt2sas_dev_attrs, | ||
| 7870 | .track_queue_depth = 1, | ||
| 7871 | }; | ||
| 7872 | |||
| 7873 | /** | ||
| 7874 | * _scsih_expander_node_remove - removing expander device from list. | ||
| 7875 | * @ioc: per adapter object | ||
| 7876 | * @sas_expander: the sas_device object | ||
| 7877 | * Context: Calling function should acquire ioc->sas_node_lock. | ||
| 7878 | * | ||
| 7879 | * Removing object and freeing associated memory from the | ||
| 7880 | * ioc->sas_expander_list. | ||
| 7881 | * | ||
| 7882 | * Return nothing. | ||
| 7883 | */ | ||
| 7884 | static void | ||
| 7885 | _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc, | ||
| 7886 | struct _sas_node *sas_expander) | ||
| 7887 | { | ||
| 7888 | struct _sas_port *mpt2sas_port, *next; | ||
| 7889 | |||
| 7890 | /* remove sibling ports attached to this expander */ | ||
| 7891 | list_for_each_entry_safe(mpt2sas_port, next, | ||
| 7892 | &sas_expander->sas_port_list, port_list) { | ||
| 7893 | if (ioc->shost_recovery) | ||
| 7894 | return; | ||
| 7895 | if (mpt2sas_port->remote_identify.device_type == | ||
| 7896 | SAS_END_DEVICE) | ||
| 7897 | mpt2sas_device_remove_by_sas_address(ioc, | ||
| 7898 | mpt2sas_port->remote_identify.sas_address); | ||
| 7899 | else if (mpt2sas_port->remote_identify.device_type == | ||
| 7900 | SAS_EDGE_EXPANDER_DEVICE || | ||
| 7901 | mpt2sas_port->remote_identify.device_type == | ||
| 7902 | SAS_FANOUT_EXPANDER_DEVICE) | ||
| 7903 | mpt2sas_expander_remove(ioc, | ||
| 7904 | mpt2sas_port->remote_identify.sas_address); | ||
| 7905 | } | ||
| 7906 | |||
| 7907 | mpt2sas_transport_port_remove(ioc, sas_expander->sas_address, | ||
| 7908 | sas_expander->sas_address_parent); | ||
| 7909 | |||
| 7910 | printk(MPT2SAS_INFO_FMT "expander_remove: handle" | ||
| 7911 | "(0x%04x), sas_addr(0x%016llx)\n", ioc->name, | ||
| 7912 | sas_expander->handle, (unsigned long long) | ||
| 7913 | sas_expander->sas_address); | ||
| 7914 | |||
| 7915 | kfree(sas_expander->phy); | ||
| 7916 | kfree(sas_expander); | ||
| 7917 | } | ||
| 7918 | |||
| 7919 | /** | ||
| 7920 | * _scsih_ir_shutdown - IR shutdown notification | ||
| 7921 | * @ioc: per adapter object | ||
| 7922 | * | ||
| 7923 | * Sending RAID Action to alert the Integrated RAID subsystem of the IOC that | ||
| 7924 | * the host system is shutting down. | ||
| 7925 | * | ||
| 7926 | * Return nothing. | ||
| 7927 | */ | ||
| 7928 | static void | ||
| 7929 | _scsih_ir_shutdown(struct MPT2SAS_ADAPTER *ioc) | ||
| 7930 | { | ||
| 7931 | Mpi2RaidActionRequest_t *mpi_request; | ||
| 7932 | Mpi2RaidActionReply_t *mpi_reply; | ||
| 7933 | u16 smid; | ||
| 7934 | |||
| 7935 | /* is IR firmware build loaded ? */ | ||
| 7936 | if (!ioc->ir_firmware) | ||
| 7937 | return; | ||
| 7938 | |||
| 7939 | mutex_lock(&ioc->scsih_cmds.mutex); | ||
| 7940 | |||
| 7941 | if (ioc->scsih_cmds.status != MPT2_CMD_NOT_USED) { | ||
| 7942 | printk(MPT2SAS_ERR_FMT "%s: scsih_cmd in use\n", | ||
| 7943 | ioc->name, __func__); | ||
| 7944 | goto out; | ||
| 7945 | } | ||
| 7946 | ioc->scsih_cmds.status = MPT2_CMD_PENDING; | ||
| 7947 | |||
| 7948 | smid = mpt2sas_base_get_smid(ioc, ioc->scsih_cb_idx); | ||
| 7949 | if (!smid) { | ||
| 7950 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", | ||
| 7951 | ioc->name, __func__); | ||
| 7952 | ioc->scsih_cmds.status = MPT2_CMD_NOT_USED; | ||
| 7953 | goto out; | ||
| 7954 | } | ||
| 7955 | |||
| 7956 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); | ||
| 7957 | ioc->scsih_cmds.smid = smid; | ||
| 7958 | memset(mpi_request, 0, sizeof(Mpi2RaidActionRequest_t)); | ||
| 7959 | |||
| 7960 | mpi_request->Function = MPI2_FUNCTION_RAID_ACTION; | ||
| 7961 | mpi_request->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED; | ||
| 7962 | |||
| 7963 | if (!ioc->hide_ir_msg) | ||
| 7964 | printk(MPT2SAS_INFO_FMT "IR shutdown (sending)\n", ioc->name); | ||
| 7965 | init_completion(&ioc->scsih_cmds.done); | ||
| 7966 | mpt2sas_base_put_smid_default(ioc, smid); | ||
| 7967 | wait_for_completion_timeout(&ioc->scsih_cmds.done, 10*HZ); | ||
| 7968 | |||
| 7969 | if (!(ioc->scsih_cmds.status & MPT2_CMD_COMPLETE)) { | ||
| 7970 | printk(MPT2SAS_ERR_FMT "%s: timeout\n", | ||
| 7971 | ioc->name, __func__); | ||
| 7972 | goto out; | ||
| 7973 | } | ||
| 7974 | |||
| 7975 | if (ioc->scsih_cmds.status & MPT2_CMD_REPLY_VALID) { | ||
| 7976 | mpi_reply = ioc->scsih_cmds.reply; | ||
| 7977 | |||
| 7978 | if (!ioc->hide_ir_msg) | ||
| 7979 | printk(MPT2SAS_INFO_FMT "IR shutdown (complete): " | ||
| 7980 | "ioc_status(0x%04x), loginfo(0x%08x)\n", | ||
| 7981 | ioc->name, le16_to_cpu(mpi_reply->IOCStatus), | ||
| 7982 | le32_to_cpu(mpi_reply->IOCLogInfo)); | ||
| 7983 | } | ||
| 7984 | |||
| 7985 | out: | ||
| 7986 | ioc->scsih_cmds.status = MPT2_CMD_NOT_USED; | ||
| 7987 | mutex_unlock(&ioc->scsih_cmds.mutex); | ||
| 7988 | } | ||
| 7989 | |||
| 7990 | /** | ||
| 7991 | * _scsih_shutdown - routine call during system shutdown | ||
| 7992 | * @pdev: PCI device struct | ||
| 7993 | * | ||
| 7994 | * Return nothing. | ||
| 7995 | */ | ||
| 7996 | static void | ||
| 7997 | _scsih_shutdown(struct pci_dev *pdev) | ||
| 7998 | { | ||
| 7999 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | ||
| 8000 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 8001 | struct workqueue_struct *wq; | ||
| 8002 | unsigned long flags; | ||
| 8003 | |||
| 8004 | ioc->remove_host = 1; | ||
| 8005 | _scsih_fw_event_cleanup_queue(ioc); | ||
| 8006 | |||
| 8007 | spin_lock_irqsave(&ioc->fw_event_lock, flags); | ||
| 8008 | wq = ioc->firmware_event_thread; | ||
| 8009 | ioc->firmware_event_thread = NULL; | ||
| 8010 | spin_unlock_irqrestore(&ioc->fw_event_lock, flags); | ||
| 8011 | if (wq) | ||
| 8012 | destroy_workqueue(wq); | ||
| 8013 | |||
| 8014 | _scsih_ir_shutdown(ioc); | ||
| 8015 | mpt2sas_base_detach(ioc); | ||
| 8016 | } | ||
| 8017 | |||
| 8018 | /** | ||
| 8019 | * _scsih_remove - detach and remove add host | ||
| 8020 | * @pdev: PCI device struct | ||
| 8021 | * | ||
| 8022 | * Routine called when unloading the driver. | ||
| 8023 | * Return nothing. | ||
| 8024 | */ | ||
| 8025 | static void | ||
| 8026 | _scsih_remove(struct pci_dev *pdev) | ||
| 8027 | { | ||
| 8028 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | ||
| 8029 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 8030 | struct _sas_port *mpt2sas_port, *next_port; | ||
| 8031 | struct _raid_device *raid_device, *next; | ||
| 8032 | struct MPT2SAS_TARGET *sas_target_priv_data; | ||
| 8033 | struct workqueue_struct *wq; | ||
| 8034 | unsigned long flags; | ||
| 8035 | |||
| 8036 | ioc->remove_host = 1; | ||
| 8037 | _scsih_fw_event_cleanup_queue(ioc); | ||
| 8038 | |||
| 8039 | spin_lock_irqsave(&ioc->fw_event_lock, flags); | ||
| 8040 | wq = ioc->firmware_event_thread; | ||
| 8041 | ioc->firmware_event_thread = NULL; | ||
| 8042 | spin_unlock_irqrestore(&ioc->fw_event_lock, flags); | ||
| 8043 | if (wq) | ||
| 8044 | destroy_workqueue(wq); | ||
| 8045 | |||
| 8046 | /* release all the volumes */ | ||
| 8047 | _scsih_ir_shutdown(ioc); | ||
| 8048 | list_for_each_entry_safe(raid_device, next, &ioc->raid_device_list, | ||
| 8049 | list) { | ||
| 8050 | if (raid_device->starget) { | ||
| 8051 | sas_target_priv_data = | ||
| 8052 | raid_device->starget->hostdata; | ||
| 8053 | sas_target_priv_data->deleted = 1; | ||
| 8054 | scsi_remove_target(&raid_device->starget->dev); | ||
| 8055 | } | ||
| 8056 | printk(MPT2SAS_INFO_FMT "removing handle(0x%04x), wwid" | ||
| 8057 | "(0x%016llx)\n", ioc->name, raid_device->handle, | ||
| 8058 | (unsigned long long) raid_device->wwid); | ||
| 8059 | _scsih_raid_device_remove(ioc, raid_device); | ||
| 8060 | } | ||
| 8061 | |||
| 8062 | /* free ports attached to the sas_host */ | ||
| 8063 | list_for_each_entry_safe(mpt2sas_port, next_port, | ||
| 8064 | &ioc->sas_hba.sas_port_list, port_list) { | ||
| 8065 | if (mpt2sas_port->remote_identify.device_type == | ||
| 8066 | SAS_END_DEVICE) | ||
| 8067 | mpt2sas_device_remove_by_sas_address(ioc, | ||
| 8068 | mpt2sas_port->remote_identify.sas_address); | ||
| 8069 | else if (mpt2sas_port->remote_identify.device_type == | ||
| 8070 | SAS_EDGE_EXPANDER_DEVICE || | ||
| 8071 | mpt2sas_port->remote_identify.device_type == | ||
| 8072 | SAS_FANOUT_EXPANDER_DEVICE) | ||
| 8073 | mpt2sas_expander_remove(ioc, | ||
| 8074 | mpt2sas_port->remote_identify.sas_address); | ||
| 8075 | } | ||
| 8076 | |||
| 8077 | /* free phys attached to the sas_host */ | ||
| 8078 | if (ioc->sas_hba.num_phys) { | ||
| 8079 | kfree(ioc->sas_hba.phy); | ||
| 8080 | ioc->sas_hba.phy = NULL; | ||
| 8081 | ioc->sas_hba.num_phys = 0; | ||
| 8082 | } | ||
| 8083 | |||
| 8084 | sas_remove_host(shost); | ||
| 8085 | scsi_remove_host(shost); | ||
| 8086 | mpt2sas_base_detach(ioc); | ||
| 8087 | spin_lock(&gioc_lock); | ||
| 8088 | list_del(&ioc->list); | ||
| 8089 | spin_unlock(&gioc_lock); | ||
| 8090 | scsi_host_put(shost); | ||
| 8091 | } | ||
| 8092 | |||
| 8093 | /** | ||
| 8094 | * _scsih_probe_boot_devices - reports 1st device | ||
| 8095 | * @ioc: per adapter object | ||
| 8096 | * | ||
| 8097 | * If specified in bios page 2, this routine reports the 1st | ||
| 8098 | * device scsi-ml or sas transport for persistent boot device | ||
| 8099 | * purposes. Please refer to function _scsih_determine_boot_device() | ||
| 8100 | */ | ||
| 8101 | static void | ||
| 8102 | _scsih_probe_boot_devices(struct MPT2SAS_ADAPTER *ioc) | ||
| 8103 | { | ||
| 8104 | u8 is_raid; | ||
| 8105 | void *device; | ||
| 8106 | struct _sas_device *sas_device; | ||
| 8107 | struct _raid_device *raid_device; | ||
| 8108 | u16 handle; | ||
| 8109 | u64 sas_address_parent; | ||
| 8110 | u64 sas_address; | ||
| 8111 | unsigned long flags; | ||
| 8112 | int rc; | ||
| 8113 | |||
| 8114 | /* no Bios, return immediately */ | ||
| 8115 | if (!ioc->bios_pg3.BiosVersion) | ||
| 8116 | return; | ||
| 8117 | |||
| 8118 | device = NULL; | ||
| 8119 | is_raid = 0; | ||
| 8120 | if (ioc->req_boot_device.device) { | ||
| 8121 | device = ioc->req_boot_device.device; | ||
| 8122 | is_raid = ioc->req_boot_device.is_raid; | ||
| 8123 | } else if (ioc->req_alt_boot_device.device) { | ||
| 8124 | device = ioc->req_alt_boot_device.device; | ||
| 8125 | is_raid = ioc->req_alt_boot_device.is_raid; | ||
| 8126 | } else if (ioc->current_boot_device.device) { | ||
| 8127 | device = ioc->current_boot_device.device; | ||
| 8128 | is_raid = ioc->current_boot_device.is_raid; | ||
| 8129 | } | ||
| 8130 | |||
| 8131 | if (!device) | ||
| 8132 | return; | ||
| 8133 | |||
| 8134 | if (is_raid) { | ||
| 8135 | raid_device = device; | ||
| 8136 | rc = scsi_add_device(ioc->shost, RAID_CHANNEL, | ||
| 8137 | raid_device->id, 0); | ||
| 8138 | if (rc) | ||
| 8139 | _scsih_raid_device_remove(ioc, raid_device); | ||
| 8140 | } else { | ||
| 8141 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 8142 | sas_device = device; | ||
| 8143 | handle = sas_device->handle; | ||
| 8144 | sas_address_parent = sas_device->sas_address_parent; | ||
| 8145 | sas_address = sas_device->sas_address; | ||
| 8146 | list_move_tail(&sas_device->list, &ioc->sas_device_list); | ||
| 8147 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 8148 | |||
| 8149 | if (ioc->hide_drives) | ||
| 8150 | return; | ||
| 8151 | if (!mpt2sas_transport_port_add(ioc, sas_device->handle, | ||
| 8152 | sas_device->sas_address_parent)) { | ||
| 8153 | _scsih_sas_device_remove(ioc, sas_device); | ||
| 8154 | } else if (!sas_device->starget) { | ||
| 8155 | if (!ioc->is_driver_loading) { | ||
| 8156 | mpt2sas_transport_port_remove(ioc, | ||
| 8157 | sas_address, | ||
| 8158 | sas_address_parent); | ||
| 8159 | _scsih_sas_device_remove(ioc, sas_device); | ||
| 8160 | } | ||
| 8161 | } | ||
| 8162 | } | ||
| 8163 | } | ||
| 8164 | |||
| 8165 | /** | ||
| 8166 | * _scsih_probe_raid - reporting raid volumes to scsi-ml | ||
| 8167 | * @ioc: per adapter object | ||
| 8168 | * | ||
| 8169 | * Called during initial loading of the driver. | ||
| 8170 | */ | ||
| 8171 | static void | ||
| 8172 | _scsih_probe_raid(struct MPT2SAS_ADAPTER *ioc) | ||
| 8173 | { | ||
| 8174 | struct _raid_device *raid_device, *raid_next; | ||
| 8175 | int rc; | ||
| 8176 | |||
| 8177 | list_for_each_entry_safe(raid_device, raid_next, | ||
| 8178 | &ioc->raid_device_list, list) { | ||
| 8179 | if (raid_device->starget) | ||
| 8180 | continue; | ||
| 8181 | rc = scsi_add_device(ioc->shost, RAID_CHANNEL, | ||
| 8182 | raid_device->id, 0); | ||
| 8183 | if (rc) | ||
| 8184 | _scsih_raid_device_remove(ioc, raid_device); | ||
| 8185 | } | ||
| 8186 | } | ||
| 8187 | |||
| 8188 | static struct _sas_device *get_next_sas_device(struct MPT2SAS_ADAPTER *ioc) | ||
| 8189 | { | ||
| 8190 | struct _sas_device *sas_device = NULL; | ||
| 8191 | unsigned long flags; | ||
| 8192 | |||
| 8193 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 8194 | if (!list_empty(&ioc->sas_device_init_list)) { | ||
| 8195 | sas_device = list_first_entry(&ioc->sas_device_init_list, | ||
| 8196 | struct _sas_device, list); | ||
| 8197 | sas_device_get(sas_device); | ||
| 8198 | } | ||
| 8199 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 8200 | |||
| 8201 | return sas_device; | ||
| 8202 | } | ||
| 8203 | |||
| 8204 | static void sas_device_make_active(struct MPT2SAS_ADAPTER *ioc, | ||
| 8205 | struct _sas_device *sas_device) | ||
| 8206 | { | ||
| 8207 | unsigned long flags; | ||
| 8208 | |||
| 8209 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 8210 | |||
| 8211 | /* | ||
| 8212 | * Since we dropped the lock during the call to port_add(), we need to | ||
| 8213 | * be careful here that somebody else didn't move or delete this item | ||
| 8214 | * while we were busy with other things. | ||
| 8215 | * | ||
| 8216 | * If it was on the list, we need a put() for the reference the list | ||
| 8217 | * had. Either way, we need a get() for the destination list. | ||
| 8218 | */ | ||
| 8219 | if (!list_empty(&sas_device->list)) { | ||
| 8220 | list_del_init(&sas_device->list); | ||
| 8221 | sas_device_put(sas_device); | ||
| 8222 | } | ||
| 8223 | |||
| 8224 | sas_device_get(sas_device); | ||
| 8225 | list_add_tail(&sas_device->list, &ioc->sas_device_list); | ||
| 8226 | |||
| 8227 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 8228 | } | ||
| 8229 | |||
| 8230 | /** | ||
| 8231 | * _scsih_probe_sas - reporting sas devices to sas transport | ||
| 8232 | * @ioc: per adapter object | ||
| 8233 | * | ||
| 8234 | * Called during initial loading of the driver. | ||
| 8235 | */ | ||
| 8236 | static void | ||
| 8237 | _scsih_probe_sas(struct MPT2SAS_ADAPTER *ioc) | ||
| 8238 | { | ||
| 8239 | struct _sas_device *sas_device; | ||
| 8240 | |||
| 8241 | if (ioc->hide_drives) | ||
| 8242 | return; | ||
| 8243 | |||
| 8244 | while ((sas_device = get_next_sas_device(ioc))) { | ||
| 8245 | if (!mpt2sas_transport_port_add(ioc, sas_device->handle, | ||
| 8246 | sas_device->sas_address_parent)) { | ||
| 8247 | _scsih_sas_device_remove(ioc, sas_device); | ||
| 8248 | sas_device_put(sas_device); | ||
| 8249 | continue; | ||
| 8250 | } else if (!sas_device->starget) { | ||
| 8251 | if (!ioc->is_driver_loading) { | ||
| 8252 | mpt2sas_transport_port_remove(ioc, | ||
| 8253 | sas_device->sas_address, | ||
| 8254 | sas_device->sas_address_parent); | ||
| 8255 | _scsih_sas_device_remove(ioc, sas_device); | ||
| 8256 | sas_device_put(sas_device); | ||
| 8257 | continue; | ||
| 8258 | } | ||
| 8259 | } | ||
| 8260 | |||
| 8261 | sas_device_make_active(ioc, sas_device); | ||
| 8262 | sas_device_put(sas_device); | ||
| 8263 | } | ||
| 8264 | } | ||
| 8265 | |||
| 8266 | /** | ||
| 8267 | * _scsih_probe_devices - probing for devices | ||
| 8268 | * @ioc: per adapter object | ||
| 8269 | * | ||
| 8270 | * Called during initial loading of the driver. | ||
| 8271 | */ | ||
| 8272 | static void | ||
| 8273 | _scsih_probe_devices(struct MPT2SAS_ADAPTER *ioc) | ||
| 8274 | { | ||
| 8275 | u16 volume_mapping_flags; | ||
| 8276 | |||
| 8277 | if (!(ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR)) | ||
| 8278 | return; /* return when IOC doesn't support initiator mode */ | ||
| 8279 | |||
| 8280 | _scsih_probe_boot_devices(ioc); | ||
| 8281 | |||
| 8282 | if (ioc->ir_firmware) { | ||
| 8283 | volume_mapping_flags = | ||
| 8284 | le16_to_cpu(ioc->ioc_pg8.IRVolumeMappingFlags) & | ||
| 8285 | MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE; | ||
| 8286 | if (volume_mapping_flags == | ||
| 8287 | MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) { | ||
| 8288 | _scsih_probe_raid(ioc); | ||
| 8289 | _scsih_probe_sas(ioc); | ||
| 8290 | } else { | ||
| 8291 | _scsih_probe_sas(ioc); | ||
| 8292 | _scsih_probe_raid(ioc); | ||
| 8293 | } | ||
| 8294 | } else | ||
| 8295 | _scsih_probe_sas(ioc); | ||
| 8296 | } | ||
| 8297 | |||
| 8298 | |||
| 8299 | /** | ||
| 8300 | * _scsih_scan_start - scsi lld callback for .scan_start | ||
| 8301 | * @shost: SCSI host pointer | ||
| 8302 | * | ||
| 8303 | * The shost has the ability to discover targets on its own instead | ||
| 8304 | * of scanning the entire bus. In our implemention, we will kick off | ||
| 8305 | * firmware discovery. | ||
| 8306 | */ | ||
| 8307 | static void | ||
| 8308 | _scsih_scan_start(struct Scsi_Host *shost) | ||
| 8309 | { | ||
| 8310 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 8311 | int rc; | ||
| 8312 | |||
| 8313 | if (diag_buffer_enable != -1 && diag_buffer_enable != 0) | ||
| 8314 | mpt2sas_enable_diag_buffer(ioc, diag_buffer_enable); | ||
| 8315 | |||
| 8316 | if (disable_discovery > 0) | ||
| 8317 | return; | ||
| 8318 | |||
| 8319 | ioc->start_scan = 1; | ||
| 8320 | rc = mpt2sas_port_enable(ioc); | ||
| 8321 | |||
| 8322 | if (rc != 0) | ||
| 8323 | printk(MPT2SAS_INFO_FMT "port enable: FAILED\n", ioc->name); | ||
| 8324 | } | ||
| 8325 | |||
| 8326 | /** | ||
| 8327 | * _scsih_scan_finished - scsi lld callback for .scan_finished | ||
| 8328 | * @shost: SCSI host pointer | ||
| 8329 | * @time: elapsed time of the scan in jiffies | ||
| 8330 | * | ||
| 8331 | * This function will be called periodically until it returns 1 with the | ||
| 8332 | * scsi_host and the elapsed time of the scan in jiffies. In our implemention, | ||
| 8333 | * we wait for firmware discovery to complete, then return 1. | ||
| 8334 | */ | ||
| 8335 | static int | ||
| 8336 | _scsih_scan_finished(struct Scsi_Host *shost, unsigned long time) | ||
| 8337 | { | ||
| 8338 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 8339 | |||
| 8340 | if (disable_discovery > 0) { | ||
| 8341 | ioc->is_driver_loading = 0; | ||
| 8342 | ioc->wait_for_discovery_to_complete = 0; | ||
| 8343 | return 1; | ||
| 8344 | } | ||
| 8345 | |||
| 8346 | if (time >= (300 * HZ)) { | ||
| 8347 | ioc->base_cmds.status = MPT2_CMD_NOT_USED; | ||
| 8348 | printk(MPT2SAS_INFO_FMT "port enable: FAILED with timeout " | ||
| 8349 | "(timeout=300s)\n", ioc->name); | ||
| 8350 | ioc->is_driver_loading = 0; | ||
| 8351 | return 1; | ||
| 8352 | } | ||
| 8353 | |||
| 8354 | if (ioc->start_scan) | ||
| 8355 | return 0; | ||
| 8356 | |||
| 8357 | if (ioc->start_scan_failed) { | ||
| 8358 | printk(MPT2SAS_INFO_FMT "port enable: FAILED with " | ||
| 8359 | "(ioc_status=0x%08x)\n", ioc->name, ioc->start_scan_failed); | ||
| 8360 | ioc->is_driver_loading = 0; | ||
| 8361 | ioc->wait_for_discovery_to_complete = 0; | ||
| 8362 | ioc->remove_host = 1; | ||
| 8363 | return 1; | ||
| 8364 | } | ||
| 8365 | |||
| 8366 | printk(MPT2SAS_INFO_FMT "port enable: SUCCESS\n", ioc->name); | ||
| 8367 | ioc->base_cmds.status = MPT2_CMD_NOT_USED; | ||
| 8368 | |||
| 8369 | if (ioc->wait_for_discovery_to_complete) { | ||
| 8370 | ioc->wait_for_discovery_to_complete = 0; | ||
| 8371 | _scsih_probe_devices(ioc); | ||
| 8372 | } | ||
| 8373 | mpt2sas_base_start_watchdog(ioc); | ||
| 8374 | ioc->is_driver_loading = 0; | ||
| 8375 | return 1; | ||
| 8376 | } | ||
| 8377 | |||
| 8378 | |||
| 8379 | /** | ||
| 8380 | * _scsih_probe - attach and add scsi host | ||
| 8381 | * @pdev: PCI device struct | ||
| 8382 | * @id: pci device id | ||
| 8383 | * | ||
| 8384 | * Returns 0 success, anything else error. | ||
| 8385 | */ | ||
| 8386 | static int | ||
| 8387 | _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) | ||
| 8388 | { | ||
| 8389 | struct MPT2SAS_ADAPTER *ioc; | ||
| 8390 | struct Scsi_Host *shost; | ||
| 8391 | int rv; | ||
| 8392 | |||
| 8393 | shost = scsi_host_alloc(&scsih_driver_template, | ||
| 8394 | sizeof(struct MPT2SAS_ADAPTER)); | ||
| 8395 | if (!shost) | ||
| 8396 | return -ENODEV; | ||
| 8397 | |||
| 8398 | /* init local params */ | ||
| 8399 | ioc = shost_priv(shost); | ||
| 8400 | memset(ioc, 0, sizeof(struct MPT2SAS_ADAPTER)); | ||
| 8401 | INIT_LIST_HEAD(&ioc->list); | ||
| 8402 | spin_lock(&gioc_lock); | ||
| 8403 | list_add_tail(&ioc->list, &mpt2sas_ioc_list); | ||
| 8404 | spin_unlock(&gioc_lock); | ||
| 8405 | ioc->shost = shost; | ||
| 8406 | ioc->id = mpt_ids++; | ||
| 8407 | sprintf(ioc->name, "%s%d", MPT2SAS_DRIVER_NAME, ioc->id); | ||
| 8408 | ioc->pdev = pdev; | ||
| 8409 | if (id->device == MPI2_MFGPAGE_DEVID_SSS6200) { | ||
| 8410 | ioc->is_warpdrive = 1; | ||
| 8411 | ioc->hide_ir_msg = 1; | ||
| 8412 | } else | ||
| 8413 | ioc->mfg_pg10_hide_flag = MFG_PAGE10_EXPOSE_ALL_DISKS; | ||
| 8414 | ioc->scsi_io_cb_idx = scsi_io_cb_idx; | ||
| 8415 | ioc->tm_cb_idx = tm_cb_idx; | ||
| 8416 | ioc->ctl_cb_idx = ctl_cb_idx; | ||
| 8417 | ioc->base_cb_idx = base_cb_idx; | ||
| 8418 | ioc->port_enable_cb_idx = port_enable_cb_idx; | ||
| 8419 | ioc->transport_cb_idx = transport_cb_idx; | ||
| 8420 | ioc->scsih_cb_idx = scsih_cb_idx; | ||
| 8421 | ioc->config_cb_idx = config_cb_idx; | ||
| 8422 | ioc->tm_tr_cb_idx = tm_tr_cb_idx; | ||
| 8423 | ioc->tm_tr_volume_cb_idx = tm_tr_volume_cb_idx; | ||
| 8424 | ioc->tm_sas_control_cb_idx = tm_sas_control_cb_idx; | ||
| 8425 | ioc->logging_level = logging_level; | ||
| 8426 | ioc->schedule_dead_ioc_flush_running_cmds = &_scsih_flush_running_cmds; | ||
| 8427 | /* misc semaphores and spin locks */ | ||
| 8428 | mutex_init(&ioc->reset_in_progress_mutex); | ||
| 8429 | /* initializing pci_access_mutex lock */ | ||
| 8430 | mutex_init(&ioc->pci_access_mutex); | ||
| 8431 | spin_lock_init(&ioc->ioc_reset_in_progress_lock); | ||
| 8432 | spin_lock_init(&ioc->scsi_lookup_lock); | ||
| 8433 | spin_lock_init(&ioc->sas_device_lock); | ||
| 8434 | spin_lock_init(&ioc->sas_node_lock); | ||
| 8435 | spin_lock_init(&ioc->fw_event_lock); | ||
| 8436 | spin_lock_init(&ioc->raid_device_lock); | ||
| 8437 | |||
| 8438 | INIT_LIST_HEAD(&ioc->sas_device_list); | ||
| 8439 | INIT_LIST_HEAD(&ioc->sas_device_init_list); | ||
| 8440 | INIT_LIST_HEAD(&ioc->sas_expander_list); | ||
| 8441 | INIT_LIST_HEAD(&ioc->fw_event_list); | ||
| 8442 | INIT_LIST_HEAD(&ioc->raid_device_list); | ||
| 8443 | INIT_LIST_HEAD(&ioc->sas_hba.sas_port_list); | ||
| 8444 | INIT_LIST_HEAD(&ioc->delayed_tr_list); | ||
| 8445 | INIT_LIST_HEAD(&ioc->delayed_tr_volume_list); | ||
| 8446 | INIT_LIST_HEAD(&ioc->reply_queue_list); | ||
| 8447 | |||
| 8448 | /* init shost parameters */ | ||
| 8449 | shost->max_cmd_len = 32; | ||
| 8450 | shost->max_lun = max_lun; | ||
| 8451 | shost->transportt = mpt2sas_transport_template; | ||
| 8452 | shost->unique_id = ioc->id; | ||
| 8453 | |||
| 8454 | if (max_sectors != 0xFFFF) { | ||
| 8455 | if (max_sectors < 64) { | ||
| 8456 | shost->max_sectors = 64; | ||
| 8457 | printk(MPT2SAS_WARN_FMT "Invalid value %d passed " | ||
| 8458 | "for max_sectors, range is 64 to 32767. Assigning " | ||
| 8459 | "value of 64.\n", ioc->name, max_sectors); | ||
| 8460 | } else if (max_sectors > 32767) { | ||
| 8461 | shost->max_sectors = 32767; | ||
| 8462 | printk(MPT2SAS_WARN_FMT "Invalid value %d passed " | ||
| 8463 | "for max_sectors, range is 64 to 8192. Assigning " | ||
| 8464 | "default value of 32767.\n", ioc->name, | ||
| 8465 | max_sectors); | ||
| 8466 | } else { | ||
| 8467 | shost->max_sectors = max_sectors & 0xFFFE; | ||
| 8468 | printk(MPT2SAS_INFO_FMT "The max_sectors value is " | ||
| 8469 | "set to %d\n", ioc->name, shost->max_sectors); | ||
| 8470 | } | ||
| 8471 | } | ||
| 8472 | |||
| 8473 | /* register EEDP capabilities with SCSI layer */ | ||
| 8474 | if (prot_mask) | ||
| 8475 | scsi_host_set_prot(shost, prot_mask); | ||
| 8476 | else | ||
| 8477 | scsi_host_set_prot(shost, SHOST_DIF_TYPE1_PROTECTION | ||
| 8478 | | SHOST_DIF_TYPE2_PROTECTION | ||
| 8479 | | SHOST_DIF_TYPE3_PROTECTION); | ||
| 8480 | |||
| 8481 | scsi_host_set_guard(shost, SHOST_DIX_GUARD_CRC); | ||
| 8482 | |||
| 8483 | /* event thread */ | ||
| 8484 | snprintf(ioc->firmware_event_name, sizeof(ioc->firmware_event_name), | ||
| 8485 | "fw_event%d", ioc->id); | ||
| 8486 | ioc->firmware_event_thread = create_singlethread_workqueue( | ||
| 8487 | ioc->firmware_event_name); | ||
| 8488 | if (!ioc->firmware_event_thread) { | ||
| 8489 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 8490 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 8491 | rv = -ENODEV; | ||
| 8492 | goto out_thread_fail; | ||
| 8493 | } | ||
| 8494 | |||
| 8495 | ioc->is_driver_loading = 1; | ||
| 8496 | if ((mpt2sas_base_attach(ioc))) { | ||
| 8497 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 8498 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 8499 | rv = -ENODEV; | ||
| 8500 | goto out_attach_fail; | ||
| 8501 | } | ||
| 8502 | |||
| 8503 | if (ioc->is_warpdrive) { | ||
| 8504 | if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_EXPOSE_ALL_DISKS) | ||
| 8505 | ioc->hide_drives = 0; | ||
| 8506 | else if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_HIDE_ALL_DISKS) | ||
| 8507 | ioc->hide_drives = 1; | ||
| 8508 | else { | ||
| 8509 | if (_scsih_get_num_volumes(ioc)) | ||
| 8510 | ioc->hide_drives = 1; | ||
| 8511 | else | ||
| 8512 | ioc->hide_drives = 0; | ||
| 8513 | } | ||
| 8514 | } else | ||
| 8515 | ioc->hide_drives = 0; | ||
| 8516 | |||
| 8517 | rv = scsi_add_host(shost, &pdev->dev); | ||
| 8518 | if (rv) { | ||
| 8519 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 8520 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 8521 | goto out_add_shost_fail; | ||
| 8522 | } | ||
| 8523 | |||
| 8524 | scsi_scan_host(shost); | ||
| 8525 | |||
| 8526 | return 0; | ||
| 8527 | |||
| 8528 | out_add_shost_fail: | ||
| 8529 | mpt2sas_base_detach(ioc); | ||
| 8530 | out_attach_fail: | ||
| 8531 | destroy_workqueue(ioc->firmware_event_thread); | ||
| 8532 | out_thread_fail: | ||
| 8533 | spin_lock(&gioc_lock); | ||
| 8534 | list_del(&ioc->list); | ||
| 8535 | spin_unlock(&gioc_lock); | ||
| 8536 | scsi_host_put(shost); | ||
| 8537 | return rv; | ||
| 8538 | } | ||
| 8539 | |||
| 8540 | #ifdef CONFIG_PM | ||
| 8541 | /** | ||
| 8542 | * _scsih_suspend - power management suspend main entry point | ||
| 8543 | * @pdev: PCI device struct | ||
| 8544 | * @state: PM state change to (usually PCI_D3) | ||
| 8545 | * | ||
| 8546 | * Returns 0 success, anything else error. | ||
| 8547 | */ | ||
| 8548 | static int | ||
| 8549 | _scsih_suspend(struct pci_dev *pdev, pm_message_t state) | ||
| 8550 | { | ||
| 8551 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | ||
| 8552 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 8553 | pci_power_t device_state; | ||
| 8554 | |||
| 8555 | mpt2sas_base_stop_watchdog(ioc); | ||
| 8556 | scsi_block_requests(shost); | ||
| 8557 | _scsih_ir_shutdown(ioc); | ||
| 8558 | device_state = pci_choose_state(pdev, state); | ||
| 8559 | printk(MPT2SAS_INFO_FMT "pdev=0x%p, slot=%s, entering " | ||
| 8560 | "operating state [D%d]\n", ioc->name, pdev, | ||
| 8561 | pci_name(pdev), device_state); | ||
| 8562 | |||
| 8563 | mpt2sas_base_free_resources(ioc); | ||
| 8564 | pci_save_state(pdev); | ||
| 8565 | pci_set_power_state(pdev, device_state); | ||
| 8566 | return 0; | ||
| 8567 | } | ||
| 8568 | |||
| 8569 | /** | ||
| 8570 | * _scsih_resume - power management resume main entry point | ||
| 8571 | * @pdev: PCI device struct | ||
| 8572 | * | ||
| 8573 | * Returns 0 success, anything else error. | ||
| 8574 | */ | ||
| 8575 | static int | ||
| 8576 | _scsih_resume(struct pci_dev *pdev) | ||
| 8577 | { | ||
| 8578 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | ||
| 8579 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 8580 | pci_power_t device_state = pdev->current_state; | ||
| 8581 | int r; | ||
| 8582 | |||
| 8583 | printk(MPT2SAS_INFO_FMT "pdev=0x%p, slot=%s, previous " | ||
| 8584 | "operating state [D%d]\n", ioc->name, pdev, | ||
| 8585 | pci_name(pdev), device_state); | ||
| 8586 | |||
| 8587 | pci_set_power_state(pdev, PCI_D0); | ||
| 8588 | pci_enable_wake(pdev, PCI_D0, 0); | ||
| 8589 | pci_restore_state(pdev); | ||
| 8590 | ioc->pdev = pdev; | ||
| 8591 | r = mpt2sas_base_map_resources(ioc); | ||
| 8592 | if (r) | ||
| 8593 | return r; | ||
| 8594 | |||
| 8595 | mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, SOFT_RESET); | ||
| 8596 | scsi_unblock_requests(shost); | ||
| 8597 | mpt2sas_base_start_watchdog(ioc); | ||
| 8598 | return 0; | ||
| 8599 | } | ||
| 8600 | #endif /* CONFIG_PM */ | ||
| 8601 | |||
| 8602 | /** | ||
| 8603 | * _scsih_pci_error_detected - Called when a PCI error is detected. | ||
| 8604 | * @pdev: PCI device struct | ||
| 8605 | * @state: PCI channel state | ||
| 8606 | * | ||
| 8607 | * Description: Called when a PCI error is detected. | ||
| 8608 | * | ||
| 8609 | * Return value: | ||
| 8610 | * PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT | ||
| 8611 | */ | ||
| 8612 | static pci_ers_result_t | ||
| 8613 | _scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) | ||
| 8614 | { | ||
| 8615 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | ||
| 8616 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 8617 | |||
| 8618 | printk(MPT2SAS_INFO_FMT "PCI error: detected callback, state(%d)!!\n", | ||
| 8619 | ioc->name, state); | ||
| 8620 | |||
| 8621 | switch (state) { | ||
| 8622 | case pci_channel_io_normal: | ||
| 8623 | return PCI_ERS_RESULT_CAN_RECOVER; | ||
| 8624 | case pci_channel_io_frozen: | ||
| 8625 | /* Fatal error, prepare for slot reset */ | ||
| 8626 | ioc->pci_error_recovery = 1; | ||
| 8627 | scsi_block_requests(ioc->shost); | ||
| 8628 | mpt2sas_base_stop_watchdog(ioc); | ||
| 8629 | mpt2sas_base_free_resources(ioc); | ||
| 8630 | return PCI_ERS_RESULT_NEED_RESET; | ||
| 8631 | case pci_channel_io_perm_failure: | ||
| 8632 | /* Permanent error, prepare for device removal */ | ||
| 8633 | ioc->pci_error_recovery = 1; | ||
| 8634 | mpt2sas_base_stop_watchdog(ioc); | ||
| 8635 | _scsih_flush_running_cmds(ioc); | ||
| 8636 | return PCI_ERS_RESULT_DISCONNECT; | ||
| 8637 | } | ||
| 8638 | return PCI_ERS_RESULT_NEED_RESET; | ||
| 8639 | } | ||
| 8640 | |||
| 8641 | /** | ||
| 8642 | * _scsih_pci_slot_reset - Called when PCI slot has been reset. | ||
| 8643 | * @pdev: PCI device struct | ||
| 8644 | * | ||
| 8645 | * Description: This routine is called by the pci error recovery | ||
| 8646 | * code after the PCI slot has been reset, just before we | ||
| 8647 | * should resume normal operations. | ||
| 8648 | */ | ||
| 8649 | static pci_ers_result_t | ||
| 8650 | _scsih_pci_slot_reset(struct pci_dev *pdev) | ||
| 8651 | { | ||
| 8652 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | ||
| 8653 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 8654 | int rc; | ||
| 8655 | |||
| 8656 | printk(MPT2SAS_INFO_FMT "PCI error: slot reset callback!!\n", | ||
| 8657 | ioc->name); | ||
| 8658 | |||
| 8659 | ioc->pci_error_recovery = 0; | ||
| 8660 | ioc->pdev = pdev; | ||
| 8661 | pci_restore_state(pdev); | ||
| 8662 | rc = mpt2sas_base_map_resources(ioc); | ||
| 8663 | if (rc) | ||
| 8664 | return PCI_ERS_RESULT_DISCONNECT; | ||
| 8665 | |||
| 8666 | |||
| 8667 | rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, | ||
| 8668 | FORCE_BIG_HAMMER); | ||
| 8669 | |||
| 8670 | printk(MPT2SAS_WARN_FMT "hard reset: %s\n", ioc->name, | ||
| 8671 | (rc == 0) ? "success" : "failed"); | ||
| 8672 | |||
| 8673 | if (!rc) | ||
| 8674 | return PCI_ERS_RESULT_RECOVERED; | ||
| 8675 | else | ||
| 8676 | return PCI_ERS_RESULT_DISCONNECT; | ||
| 8677 | } | ||
| 8678 | |||
| 8679 | /** | ||
| 8680 | * _scsih_pci_resume() - resume normal ops after PCI reset | ||
| 8681 | * @pdev: pointer to PCI device | ||
| 8682 | * | ||
| 8683 | * Called when the error recovery driver tells us that its | ||
| 8684 | * OK to resume normal operation. Use completion to allow | ||
| 8685 | * halted scsi ops to resume. | ||
| 8686 | */ | ||
| 8687 | static void | ||
| 8688 | _scsih_pci_resume(struct pci_dev *pdev) | ||
| 8689 | { | ||
| 8690 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | ||
| 8691 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 8692 | |||
| 8693 | printk(MPT2SAS_INFO_FMT "PCI error: resume callback!!\n", ioc->name); | ||
| 8694 | |||
| 8695 | pci_cleanup_aer_uncorrect_error_status(pdev); | ||
| 8696 | mpt2sas_base_start_watchdog(ioc); | ||
| 8697 | scsi_unblock_requests(ioc->shost); | ||
| 8698 | } | ||
| 8699 | |||
| 8700 | /** | ||
| 8701 | * _scsih_pci_mmio_enabled - Enable MMIO and dump debug registers | ||
| 8702 | * @pdev: pointer to PCI device | ||
| 8703 | */ | ||
| 8704 | static pci_ers_result_t | ||
| 8705 | _scsih_pci_mmio_enabled(struct pci_dev *pdev) | ||
| 8706 | { | ||
| 8707 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | ||
| 8708 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 8709 | |||
| 8710 | printk(MPT2SAS_INFO_FMT "PCI error: mmio enabled callback!!\n", | ||
| 8711 | ioc->name); | ||
| 8712 | |||
| 8713 | /* TODO - dump whatever for debugging purposes */ | ||
| 8714 | |||
| 8715 | /* Request a slot reset. */ | ||
| 8716 | return PCI_ERS_RESULT_NEED_RESET; | ||
| 8717 | } | ||
| 8718 | |||
| 8719 | static const struct pci_error_handlers _scsih_err_handler = { | ||
| 8720 | .error_detected = _scsih_pci_error_detected, | ||
| 8721 | .mmio_enabled = _scsih_pci_mmio_enabled, | ||
| 8722 | .slot_reset = _scsih_pci_slot_reset, | ||
| 8723 | .resume = _scsih_pci_resume, | ||
| 8724 | }; | ||
| 8725 | |||
| 8726 | static struct pci_driver scsih_driver = { | ||
| 8727 | .name = MPT2SAS_DRIVER_NAME, | ||
| 8728 | .id_table = scsih_pci_table, | ||
| 8729 | .probe = _scsih_probe, | ||
| 8730 | .remove = _scsih_remove, | ||
| 8731 | .shutdown = _scsih_shutdown, | ||
| 8732 | .err_handler = &_scsih_err_handler, | ||
| 8733 | #ifdef CONFIG_PM | ||
| 8734 | .suspend = _scsih_suspend, | ||
| 8735 | .resume = _scsih_resume, | ||
| 8736 | #endif | ||
| 8737 | }; | ||
| 8738 | |||
| 8739 | /* raid transport support */ | ||
| 8740 | static struct raid_function_template mpt2sas_raid_functions = { | ||
| 8741 | .cookie = &scsih_driver_template, | ||
| 8742 | .is_raid = _scsih_is_raid, | ||
| 8743 | .get_resync = _scsih_get_resync, | ||
| 8744 | .get_state = _scsih_get_state, | ||
| 8745 | }; | ||
| 8746 | |||
| 8747 | /** | ||
| 8748 | * _scsih_init - main entry point for this driver. | ||
| 8749 | * | ||
| 8750 | * Returns 0 success, anything else error. | ||
| 8751 | */ | ||
| 8752 | static int __init | ||
| 8753 | _scsih_init(void) | ||
| 8754 | { | ||
| 8755 | int error; | ||
| 8756 | |||
| 8757 | mpt_ids = 0; | ||
| 8758 | printk(KERN_INFO "%s version %s loaded\n", MPT2SAS_DRIVER_NAME, | ||
| 8759 | MPT2SAS_DRIVER_VERSION); | ||
| 8760 | |||
| 8761 | mpt2sas_transport_template = | ||
| 8762 | sas_attach_transport(&mpt2sas_transport_functions); | ||
| 8763 | if (!mpt2sas_transport_template) | ||
| 8764 | return -ENODEV; | ||
| 8765 | /* raid transport support */ | ||
| 8766 | mpt2sas_raid_template = raid_class_attach(&mpt2sas_raid_functions); | ||
| 8767 | if (!mpt2sas_raid_template) { | ||
| 8768 | sas_release_transport(mpt2sas_transport_template); | ||
| 8769 | return -ENODEV; | ||
| 8770 | } | ||
| 8771 | |||
| 8772 | mpt2sas_base_initialize_callback_handler(); | ||
| 8773 | |||
| 8774 | /* queuecommand callback hander */ | ||
| 8775 | scsi_io_cb_idx = mpt2sas_base_register_callback_handler(_scsih_io_done); | ||
| 8776 | |||
| 8777 | /* task management callback handler */ | ||
| 8778 | tm_cb_idx = mpt2sas_base_register_callback_handler(_scsih_tm_done); | ||
| 8779 | |||
| 8780 | /* base internal commands callback handler */ | ||
| 8781 | base_cb_idx = mpt2sas_base_register_callback_handler(mpt2sas_base_done); | ||
| 8782 | port_enable_cb_idx = mpt2sas_base_register_callback_handler( | ||
| 8783 | mpt2sas_port_enable_done); | ||
| 8784 | |||
| 8785 | /* transport internal commands callback handler */ | ||
| 8786 | transport_cb_idx = mpt2sas_base_register_callback_handler( | ||
| 8787 | mpt2sas_transport_done); | ||
| 8788 | |||
| 8789 | /* scsih internal commands callback handler */ | ||
| 8790 | scsih_cb_idx = mpt2sas_base_register_callback_handler(_scsih_done); | ||
| 8791 | |||
| 8792 | /* configuration page API internal commands callback handler */ | ||
| 8793 | config_cb_idx = mpt2sas_base_register_callback_handler( | ||
| 8794 | mpt2sas_config_done); | ||
| 8795 | |||
| 8796 | /* ctl module callback handler */ | ||
| 8797 | ctl_cb_idx = mpt2sas_base_register_callback_handler(mpt2sas_ctl_done); | ||
| 8798 | |||
| 8799 | tm_tr_cb_idx = mpt2sas_base_register_callback_handler( | ||
| 8800 | _scsih_tm_tr_complete); | ||
| 8801 | |||
| 8802 | tm_tr_volume_cb_idx = mpt2sas_base_register_callback_handler( | ||
| 8803 | _scsih_tm_volume_tr_complete); | ||
| 8804 | |||
| 8805 | tm_sas_control_cb_idx = mpt2sas_base_register_callback_handler( | ||
| 8806 | _scsih_sas_control_complete); | ||
| 8807 | |||
| 8808 | mpt2sas_ctl_init(); | ||
| 8809 | |||
| 8810 | error = pci_register_driver(&scsih_driver); | ||
| 8811 | if (error) { | ||
| 8812 | /* raid transport support */ | ||
| 8813 | raid_class_release(mpt2sas_raid_template); | ||
| 8814 | sas_release_transport(mpt2sas_transport_template); | ||
| 8815 | } | ||
| 8816 | |||
| 8817 | return error; | ||
| 8818 | } | ||
| 8819 | |||
| 8820 | /** | ||
| 8821 | * _scsih_exit - exit point for this driver (when it is a module). | ||
| 8822 | * | ||
| 8823 | * Returns 0 success, anything else error. | ||
| 8824 | */ | ||
| 8825 | static void __exit | ||
| 8826 | _scsih_exit(void) | ||
| 8827 | { | ||
| 8828 | printk(KERN_INFO "mpt2sas version %s unloading\n", | ||
| 8829 | MPT2SAS_DRIVER_VERSION); | ||
| 8830 | |||
| 8831 | pci_unregister_driver(&scsih_driver); | ||
| 8832 | |||
| 8833 | mpt2sas_ctl_exit(); | ||
| 8834 | |||
| 8835 | mpt2sas_base_release_callback_handler(scsi_io_cb_idx); | ||
| 8836 | mpt2sas_base_release_callback_handler(tm_cb_idx); | ||
| 8837 | mpt2sas_base_release_callback_handler(base_cb_idx); | ||
| 8838 | mpt2sas_base_release_callback_handler(port_enable_cb_idx); | ||
| 8839 | mpt2sas_base_release_callback_handler(transport_cb_idx); | ||
| 8840 | mpt2sas_base_release_callback_handler(scsih_cb_idx); | ||
| 8841 | mpt2sas_base_release_callback_handler(config_cb_idx); | ||
| 8842 | mpt2sas_base_release_callback_handler(ctl_cb_idx); | ||
| 8843 | |||
| 8844 | mpt2sas_base_release_callback_handler(tm_tr_cb_idx); | ||
| 8845 | mpt2sas_base_release_callback_handler(tm_tr_volume_cb_idx); | ||
| 8846 | mpt2sas_base_release_callback_handler(tm_sas_control_cb_idx); | ||
| 8847 | |||
| 8848 | /* raid transport support */ | ||
| 8849 | raid_class_release(mpt2sas_raid_template); | ||
| 8850 | sas_release_transport(mpt2sas_transport_template); | ||
| 8851 | |||
| 8852 | } | ||
| 8853 | |||
| 8854 | module_init(_scsih_init); | ||
| 8855 | module_exit(_scsih_exit); | ||
diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c deleted file mode 100644 index af868009395d..000000000000 --- a/drivers/scsi/mpt2sas/mpt2sas_transport.c +++ /dev/null | |||
| @@ -1,2173 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * SAS Transport Layer for MPT (Message Passing Technology) based controllers | ||
| 3 | * | ||
| 4 | * This code is based on drivers/scsi/mpt2sas/mpt2_transport.c | ||
| 5 | * Copyright (C) 2007-2014 LSI Corporation | ||
| 6 | * Copyright (C) 20013-2014 Avago Technologies | ||
| 7 | * (mailto: MPT-FusionLinux.pdl@avagotech.com) | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or | ||
| 10 | * modify it under the terms of the GNU General Public License | ||
| 11 | * as published by the Free Software Foundation; either version 2 | ||
| 12 | * of the License, or (at your option) any later version. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | * NO WARRANTY | ||
| 20 | * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR | ||
| 21 | * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT | ||
| 22 | * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, | ||
| 23 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is | ||
| 24 | * solely responsible for determining the appropriateness of using and | ||
| 25 | * distributing the Program and assumes all risks associated with its | ||
| 26 | * exercise of rights under this Agreement, including but not limited to | ||
| 27 | * the risks and costs of program errors, damage to or loss of data, | ||
| 28 | * programs or equipment, and unavailability or interruption of operations. | ||
| 29 | |||
| 30 | * DISCLAIMER OF LIABILITY | ||
| 31 | * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY | ||
| 32 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 33 | * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND | ||
| 34 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR | ||
| 35 | * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | ||
| 36 | * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED | ||
| 37 | * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES | ||
| 38 | |||
| 39 | * You should have received a copy of the GNU General Public License | ||
| 40 | * along with this program; if not, write to the Free Software | ||
| 41 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
| 42 | * USA. | ||
| 43 | */ | ||
| 44 | |||
| 45 | #include <linux/module.h> | ||
| 46 | #include <linux/kernel.h> | ||
| 47 | #include <linux/init.h> | ||
| 48 | #include <linux/errno.h> | ||
| 49 | #include <linux/sched.h> | ||
| 50 | #include <linux/workqueue.h> | ||
| 51 | #include <linux/delay.h> | ||
| 52 | #include <linux/pci.h> | ||
| 53 | #include <linux/slab.h> | ||
| 54 | |||
| 55 | #include <scsi/scsi.h> | ||
| 56 | #include <scsi/scsi_cmnd.h> | ||
| 57 | #include <scsi/scsi_device.h> | ||
| 58 | #include <scsi/scsi_host.h> | ||
| 59 | #include <scsi/scsi_transport_sas.h> | ||
| 60 | #include <scsi/scsi_dbg.h> | ||
| 61 | |||
| 62 | #include "mpt2sas_base.h" | ||
| 63 | /** | ||
| 64 | * _transport_sas_node_find_by_sas_address - sas node search | ||
| 65 | * @ioc: per adapter object | ||
| 66 | * @sas_address: sas address of expander or sas host | ||
| 67 | * Context: Calling function should acquire ioc->sas_node_lock. | ||
| 68 | * | ||
| 69 | * Search for either hba phys or expander device based on handle, then returns | ||
| 70 | * the sas_node object. | ||
| 71 | */ | ||
| 72 | static struct _sas_node * | ||
| 73 | _transport_sas_node_find_by_sas_address(struct MPT2SAS_ADAPTER *ioc, | ||
| 74 | u64 sas_address) | ||
| 75 | { | ||
| 76 | if (ioc->sas_hba.sas_address == sas_address) | ||
| 77 | return &ioc->sas_hba; | ||
| 78 | else | ||
| 79 | return mpt2sas_scsih_expander_find_by_sas_address(ioc, | ||
| 80 | sas_address); | ||
| 81 | } | ||
| 82 | |||
| 83 | /** | ||
| 84 | * _transport_convert_phy_link_rate - | ||
| 85 | * @link_rate: link rate returned from mpt firmware | ||
| 86 | * | ||
| 87 | * Convert link_rate from mpi fusion into sas_transport form. | ||
| 88 | */ | ||
| 89 | static enum sas_linkrate | ||
| 90 | _transport_convert_phy_link_rate(u8 link_rate) | ||
| 91 | { | ||
| 92 | enum sas_linkrate rc; | ||
| 93 | |||
| 94 | switch (link_rate) { | ||
| 95 | case MPI2_SAS_NEG_LINK_RATE_1_5: | ||
| 96 | rc = SAS_LINK_RATE_1_5_GBPS; | ||
| 97 | break; | ||
| 98 | case MPI2_SAS_NEG_LINK_RATE_3_0: | ||
| 99 | rc = SAS_LINK_RATE_3_0_GBPS; | ||
| 100 | break; | ||
| 101 | case MPI2_SAS_NEG_LINK_RATE_6_0: | ||
| 102 | rc = SAS_LINK_RATE_6_0_GBPS; | ||
| 103 | break; | ||
| 104 | case MPI2_SAS_NEG_LINK_RATE_PHY_DISABLED: | ||
| 105 | rc = SAS_PHY_DISABLED; | ||
| 106 | break; | ||
| 107 | case MPI2_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED: | ||
| 108 | rc = SAS_LINK_RATE_FAILED; | ||
| 109 | break; | ||
| 110 | case MPI2_SAS_NEG_LINK_RATE_PORT_SELECTOR: | ||
| 111 | rc = SAS_SATA_PORT_SELECTOR; | ||
| 112 | break; | ||
| 113 | case MPI2_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS: | ||
| 114 | rc = SAS_PHY_RESET_IN_PROGRESS; | ||
| 115 | break; | ||
| 116 | default: | ||
| 117 | case MPI2_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE: | ||
| 118 | case MPI2_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE: | ||
| 119 | rc = SAS_LINK_RATE_UNKNOWN; | ||
| 120 | break; | ||
| 121 | } | ||
| 122 | return rc; | ||
| 123 | } | ||
| 124 | |||
| 125 | /** | ||
| 126 | * _transport_set_identify - set identify for phys and end devices | ||
| 127 | * @ioc: per adapter object | ||
| 128 | * @handle: device handle | ||
| 129 | * @identify: sas identify info | ||
| 130 | * | ||
| 131 | * Populates sas identify info. | ||
| 132 | * | ||
| 133 | * Returns 0 for success, non-zero for failure. | ||
| 134 | */ | ||
| 135 | static int | ||
| 136 | _transport_set_identify(struct MPT2SAS_ADAPTER *ioc, u16 handle, | ||
| 137 | struct sas_identify *identify) | ||
| 138 | { | ||
| 139 | Mpi2SasDevicePage0_t sas_device_pg0; | ||
| 140 | Mpi2ConfigReply_t mpi_reply; | ||
| 141 | u32 device_info; | ||
| 142 | u32 ioc_status; | ||
| 143 | |||
| 144 | if (ioc->shost_recovery || ioc->pci_error_recovery) { | ||
| 145 | printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n", | ||
| 146 | __func__, ioc->name); | ||
| 147 | return -EFAULT; | ||
| 148 | } | ||
| 149 | |||
| 150 | if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, | ||
| 151 | MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { | ||
| 152 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 153 | |||
| 154 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 155 | return -ENXIO; | ||
| 156 | } | ||
| 157 | |||
| 158 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
| 159 | MPI2_IOCSTATUS_MASK; | ||
| 160 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { | ||
| 161 | printk(MPT2SAS_ERR_FMT "handle(0x%04x), ioc_status(0x%04x)" | ||
| 162 | "\nfailure at %s:%d/%s()!\n", ioc->name, handle, ioc_status, | ||
| 163 | __FILE__, __LINE__, __func__); | ||
| 164 | return -EIO; | ||
| 165 | } | ||
| 166 | |||
| 167 | memset(identify, 0, sizeof(struct sas_identify)); | ||
| 168 | device_info = le32_to_cpu(sas_device_pg0.DeviceInfo); | ||
| 169 | |||
| 170 | /* sas_address */ | ||
| 171 | identify->sas_address = le64_to_cpu(sas_device_pg0.SASAddress); | ||
| 172 | |||
| 173 | /* phy number of the parent device this device is linked to */ | ||
| 174 | identify->phy_identifier = sas_device_pg0.PhyNum; | ||
| 175 | |||
| 176 | /* device_type */ | ||
| 177 | switch (device_info & MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) { | ||
| 178 | case MPI2_SAS_DEVICE_INFO_NO_DEVICE: | ||
| 179 | identify->device_type = SAS_PHY_UNUSED; | ||
| 180 | break; | ||
| 181 | case MPI2_SAS_DEVICE_INFO_END_DEVICE: | ||
| 182 | identify->device_type = SAS_END_DEVICE; | ||
| 183 | break; | ||
| 184 | case MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER: | ||
| 185 | identify->device_type = SAS_EDGE_EXPANDER_DEVICE; | ||
| 186 | break; | ||
| 187 | case MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER: | ||
| 188 | identify->device_type = SAS_FANOUT_EXPANDER_DEVICE; | ||
| 189 | break; | ||
| 190 | } | ||
| 191 | |||
| 192 | /* initiator_port_protocols */ | ||
| 193 | if (device_info & MPI2_SAS_DEVICE_INFO_SSP_INITIATOR) | ||
| 194 | identify->initiator_port_protocols |= SAS_PROTOCOL_SSP; | ||
| 195 | if (device_info & MPI2_SAS_DEVICE_INFO_STP_INITIATOR) | ||
| 196 | identify->initiator_port_protocols |= SAS_PROTOCOL_STP; | ||
| 197 | if (device_info & MPI2_SAS_DEVICE_INFO_SMP_INITIATOR) | ||
| 198 | identify->initiator_port_protocols |= SAS_PROTOCOL_SMP; | ||
| 199 | if (device_info & MPI2_SAS_DEVICE_INFO_SATA_HOST) | ||
| 200 | identify->initiator_port_protocols |= SAS_PROTOCOL_SATA; | ||
| 201 | |||
| 202 | /* target_port_protocols */ | ||
| 203 | if (device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) | ||
| 204 | identify->target_port_protocols |= SAS_PROTOCOL_SSP; | ||
| 205 | if (device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET) | ||
| 206 | identify->target_port_protocols |= SAS_PROTOCOL_STP; | ||
| 207 | if (device_info & MPI2_SAS_DEVICE_INFO_SMP_TARGET) | ||
| 208 | identify->target_port_protocols |= SAS_PROTOCOL_SMP; | ||
| 209 | if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) | ||
| 210 | identify->target_port_protocols |= SAS_PROTOCOL_SATA; | ||
| 211 | |||
| 212 | return 0; | ||
| 213 | } | ||
| 214 | |||
| 215 | /** | ||
| 216 | * mpt2sas_transport_done - internal transport layer callback handler. | ||
| 217 | * @ioc: per adapter object | ||
| 218 | * @smid: system request message index | ||
| 219 | * @msix_index: MSIX table index supplied by the OS | ||
| 220 | * @reply: reply message frame(lower 32bit addr) | ||
| 221 | * | ||
| 222 | * Callback handler when sending internal generated transport cmds. | ||
| 223 | * The callback index passed is `ioc->transport_cb_idx` | ||
| 224 | * | ||
| 225 | * Return 1 meaning mf should be freed from _base_interrupt | ||
| 226 | * 0 means the mf is freed from this function. | ||
| 227 | */ | ||
| 228 | u8 | ||
| 229 | mpt2sas_transport_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | ||
| 230 | u32 reply) | ||
| 231 | { | ||
| 232 | MPI2DefaultReply_t *mpi_reply; | ||
| 233 | |||
| 234 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | ||
| 235 | if (ioc->transport_cmds.status == MPT2_CMD_NOT_USED) | ||
| 236 | return 1; | ||
| 237 | if (ioc->transport_cmds.smid != smid) | ||
| 238 | return 1; | ||
| 239 | ioc->transport_cmds.status |= MPT2_CMD_COMPLETE; | ||
| 240 | if (mpi_reply) { | ||
| 241 | memcpy(ioc->transport_cmds.reply, mpi_reply, | ||
| 242 | mpi_reply->MsgLength*4); | ||
| 243 | ioc->transport_cmds.status |= MPT2_CMD_REPLY_VALID; | ||
| 244 | } | ||
| 245 | ioc->transport_cmds.status &= ~MPT2_CMD_PENDING; | ||
| 246 | complete(&ioc->transport_cmds.done); | ||
| 247 | return 1; | ||
| 248 | } | ||
| 249 | |||
| 250 | /* report manufacture request structure */ | ||
| 251 | struct rep_manu_request{ | ||
| 252 | u8 smp_frame_type; | ||
| 253 | u8 function; | ||
| 254 | u8 reserved; | ||
| 255 | u8 request_length; | ||
| 256 | }; | ||
| 257 | |||
| 258 | /* report manufacture reply structure */ | ||
| 259 | struct rep_manu_reply{ | ||
| 260 | u8 smp_frame_type; /* 0x41 */ | ||
| 261 | u8 function; /* 0x01 */ | ||
| 262 | u8 function_result; | ||
| 263 | u8 response_length; | ||
| 264 | u16 expander_change_count; | ||
| 265 | u8 reserved0[2]; | ||
| 266 | u8 sas_format; | ||
| 267 | u8 reserved2[3]; | ||
| 268 | u8 vendor_id[SAS_EXPANDER_VENDOR_ID_LEN]; | ||
| 269 | u8 product_id[SAS_EXPANDER_PRODUCT_ID_LEN]; | ||
| 270 | u8 product_rev[SAS_EXPANDER_PRODUCT_REV_LEN]; | ||
| 271 | u8 component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN]; | ||
| 272 | u16 component_id; | ||
| 273 | u8 component_revision_id; | ||
| 274 | u8 reserved3; | ||
| 275 | u8 vendor_specific[8]; | ||
| 276 | }; | ||
| 277 | |||
| 278 | /** | ||
| 279 | * _transport_expander_report_manufacture - obtain SMP report_manufacture | ||
| 280 | * @ioc: per adapter object | ||
| 281 | * @sas_address: expander sas address | ||
| 282 | * @edev: the sas_expander_device object | ||
| 283 | * | ||
| 284 | * Fills in the sas_expander_device object when SMP port is created. | ||
| 285 | * | ||
| 286 | * Returns 0 for success, non-zero for failure. | ||
| 287 | */ | ||
| 288 | static int | ||
| 289 | _transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc, | ||
| 290 | u64 sas_address, struct sas_expander_device *edev) | ||
| 291 | { | ||
| 292 | Mpi2SmpPassthroughRequest_t *mpi_request; | ||
| 293 | Mpi2SmpPassthroughReply_t *mpi_reply; | ||
| 294 | struct rep_manu_reply *manufacture_reply; | ||
| 295 | struct rep_manu_request *manufacture_request; | ||
| 296 | int rc; | ||
| 297 | u16 smid; | ||
| 298 | u32 ioc_state; | ||
| 299 | unsigned long timeleft; | ||
| 300 | void *psge; | ||
| 301 | u32 sgl_flags; | ||
| 302 | u8 issue_reset = 0; | ||
| 303 | void *data_out = NULL; | ||
| 304 | dma_addr_t data_out_dma; | ||
| 305 | u32 sz; | ||
| 306 | u16 wait_state_count; | ||
| 307 | |||
| 308 | if (ioc->shost_recovery || ioc->pci_error_recovery) { | ||
| 309 | printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n", | ||
| 310 | __func__, ioc->name); | ||
| 311 | return -EFAULT; | ||
| 312 | } | ||
| 313 | |||
| 314 | mutex_lock(&ioc->transport_cmds.mutex); | ||
| 315 | |||
| 316 | if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) { | ||
| 317 | printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n", | ||
| 318 | ioc->name, __func__); | ||
| 319 | rc = -EAGAIN; | ||
| 320 | goto out; | ||
| 321 | } | ||
| 322 | ioc->transport_cmds.status = MPT2_CMD_PENDING; | ||
| 323 | |||
| 324 | wait_state_count = 0; | ||
| 325 | ioc_state = mpt2sas_base_get_iocstate(ioc, 1); | ||
| 326 | while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { | ||
| 327 | if (wait_state_count++ == 10) { | ||
| 328 | printk(MPT2SAS_ERR_FMT | ||
| 329 | "%s: failed due to ioc not operational\n", | ||
| 330 | ioc->name, __func__); | ||
| 331 | rc = -EFAULT; | ||
| 332 | goto out; | ||
| 333 | } | ||
| 334 | ssleep(1); | ||
| 335 | ioc_state = mpt2sas_base_get_iocstate(ioc, 1); | ||
| 336 | printk(MPT2SAS_INFO_FMT "%s: waiting for " | ||
| 337 | "operational state(count=%d)\n", ioc->name, | ||
| 338 | __func__, wait_state_count); | ||
| 339 | } | ||
| 340 | if (wait_state_count) | ||
| 341 | printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n", | ||
| 342 | ioc->name, __func__); | ||
| 343 | |||
| 344 | smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx); | ||
| 345 | if (!smid) { | ||
| 346 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", | ||
| 347 | ioc->name, __func__); | ||
| 348 | rc = -EAGAIN; | ||
| 349 | goto out; | ||
| 350 | } | ||
| 351 | |||
| 352 | rc = 0; | ||
| 353 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); | ||
| 354 | ioc->transport_cmds.smid = smid; | ||
| 355 | |||
| 356 | sz = sizeof(struct rep_manu_request) + sizeof(struct rep_manu_reply); | ||
| 357 | data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma); | ||
| 358 | |||
| 359 | if (!data_out) { | ||
| 360 | printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, | ||
| 361 | __LINE__, __func__); | ||
| 362 | rc = -ENOMEM; | ||
| 363 | mpt2sas_base_free_smid(ioc, smid); | ||
| 364 | goto out; | ||
| 365 | } | ||
| 366 | |||
| 367 | manufacture_request = data_out; | ||
| 368 | manufacture_request->smp_frame_type = 0x40; | ||
| 369 | manufacture_request->function = 1; | ||
| 370 | manufacture_request->reserved = 0; | ||
| 371 | manufacture_request->request_length = 0; | ||
| 372 | |||
| 373 | memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t)); | ||
| 374 | mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH; | ||
| 375 | mpi_request->PhysicalPort = 0xFF; | ||
| 376 | mpi_request->VF_ID = 0; /* TODO */ | ||
| 377 | mpi_request->VP_ID = 0; | ||
| 378 | mpi_request->SASAddress = cpu_to_le64(sas_address); | ||
| 379 | mpi_request->RequestDataLength = | ||
| 380 | cpu_to_le16(sizeof(struct rep_manu_request)); | ||
| 381 | psge = &mpi_request->SGL; | ||
| 382 | |||
| 383 | /* WRITE sgel first */ | ||
| 384 | sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT | | ||
| 385 | MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC); | ||
| 386 | sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; | ||
| 387 | ioc->base_add_sg_single(psge, sgl_flags | | ||
| 388 | sizeof(struct rep_manu_request), data_out_dma); | ||
| 389 | |||
| 390 | /* incr sgel */ | ||
| 391 | psge += ioc->sge_size; | ||
| 392 | |||
| 393 | /* READ sgel last */ | ||
| 394 | sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT | | ||
| 395 | MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER | | ||
| 396 | MPI2_SGE_FLAGS_END_OF_LIST); | ||
| 397 | sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; | ||
| 398 | ioc->base_add_sg_single(psge, sgl_flags | | ||
| 399 | sizeof(struct rep_manu_reply), data_out_dma + | ||
| 400 | sizeof(struct rep_manu_request)); | ||
| 401 | |||
| 402 | dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "report_manufacture - " | ||
| 403 | "send to sas_addr(0x%016llx)\n", ioc->name, | ||
| 404 | (unsigned long long)sas_address)); | ||
| 405 | init_completion(&ioc->transport_cmds.done); | ||
| 406 | mpt2sas_base_put_smid_default(ioc, smid); | ||
| 407 | timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done, | ||
| 408 | 10*HZ); | ||
| 409 | |||
| 410 | if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) { | ||
| 411 | printk(MPT2SAS_ERR_FMT "%s: timeout\n", | ||
| 412 | ioc->name, __func__); | ||
| 413 | _debug_dump_mf(mpi_request, | ||
| 414 | sizeof(Mpi2SmpPassthroughRequest_t)/4); | ||
| 415 | if (!(ioc->transport_cmds.status & MPT2_CMD_RESET)) | ||
| 416 | issue_reset = 1; | ||
| 417 | goto issue_host_reset; | ||
| 418 | } | ||
| 419 | |||
| 420 | dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "report_manufacture - " | ||
| 421 | "complete\n", ioc->name)); | ||
| 422 | |||
| 423 | if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) { | ||
| 424 | u8 *tmp; | ||
| 425 | |||
| 426 | mpi_reply = ioc->transport_cmds.reply; | ||
| 427 | |||
| 428 | dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 429 | "report_manufacture - reply data transfer size(%d)\n", | ||
| 430 | ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength))); | ||
| 431 | |||
| 432 | if (le16_to_cpu(mpi_reply->ResponseDataLength) != | ||
| 433 | sizeof(struct rep_manu_reply)) | ||
| 434 | goto out; | ||
| 435 | |||
| 436 | manufacture_reply = data_out + sizeof(struct rep_manu_request); | ||
| 437 | strncpy(edev->vendor_id, manufacture_reply->vendor_id, | ||
| 438 | SAS_EXPANDER_VENDOR_ID_LEN); | ||
| 439 | strncpy(edev->product_id, manufacture_reply->product_id, | ||
| 440 | SAS_EXPANDER_PRODUCT_ID_LEN); | ||
| 441 | strncpy(edev->product_rev, manufacture_reply->product_rev, | ||
| 442 | SAS_EXPANDER_PRODUCT_REV_LEN); | ||
| 443 | edev->level = manufacture_reply->sas_format & 1; | ||
| 444 | if (edev->level) { | ||
| 445 | strncpy(edev->component_vendor_id, | ||
| 446 | manufacture_reply->component_vendor_id, | ||
| 447 | SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN); | ||
| 448 | tmp = (u8 *)&manufacture_reply->component_id; | ||
| 449 | edev->component_id = tmp[0] << 8 | tmp[1]; | ||
| 450 | edev->component_revision_id = | ||
| 451 | manufacture_reply->component_revision_id; | ||
| 452 | } | ||
| 453 | } else | ||
| 454 | dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 455 | "report_manufacture - no reply\n", ioc->name)); | ||
| 456 | |||
| 457 | issue_host_reset: | ||
| 458 | if (issue_reset) | ||
| 459 | mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, | ||
| 460 | FORCE_BIG_HAMMER); | ||
| 461 | out: | ||
| 462 | ioc->transport_cmds.status = MPT2_CMD_NOT_USED; | ||
| 463 | if (data_out) | ||
| 464 | pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma); | ||
| 465 | |||
| 466 | mutex_unlock(&ioc->transport_cmds.mutex); | ||
| 467 | return rc; | ||
| 468 | } | ||
| 469 | |||
| 470 | /** | ||
| 471 | * _transport_delete_port - helper function to removing a port | ||
| 472 | * @ioc: per adapter object | ||
| 473 | * @mpt2sas_port: mpt2sas per port object | ||
| 474 | * | ||
| 475 | * Returns nothing. | ||
| 476 | */ | ||
| 477 | static void | ||
| 478 | _transport_delete_port(struct MPT2SAS_ADAPTER *ioc, | ||
| 479 | struct _sas_port *mpt2sas_port) | ||
| 480 | { | ||
| 481 | u64 sas_address = mpt2sas_port->remote_identify.sas_address; | ||
| 482 | enum sas_device_type device_type = | ||
| 483 | mpt2sas_port->remote_identify.device_type; | ||
| 484 | |||
| 485 | dev_printk(KERN_INFO, &mpt2sas_port->port->dev, | ||
| 486 | "remove: sas_addr(0x%016llx)\n", | ||
| 487 | (unsigned long long) sas_address); | ||
| 488 | |||
| 489 | ioc->logging_level |= MPT_DEBUG_TRANSPORT; | ||
| 490 | if (device_type == SAS_END_DEVICE) | ||
| 491 | mpt2sas_device_remove_by_sas_address(ioc, sas_address); | ||
| 492 | else if (device_type == SAS_EDGE_EXPANDER_DEVICE || | ||
| 493 | device_type == SAS_FANOUT_EXPANDER_DEVICE) | ||
| 494 | mpt2sas_expander_remove(ioc, sas_address); | ||
| 495 | ioc->logging_level &= ~MPT_DEBUG_TRANSPORT; | ||
| 496 | } | ||
| 497 | |||
| 498 | /** | ||
| 499 | * _transport_delete_phy - helper function to removing single phy from port | ||
| 500 | * @ioc: per adapter object | ||
| 501 | * @mpt2sas_port: mpt2sas per port object | ||
| 502 | * @mpt2sas_phy: mpt2sas per phy object | ||
| 503 | * | ||
| 504 | * Returns nothing. | ||
| 505 | */ | ||
| 506 | static void | ||
| 507 | _transport_delete_phy(struct MPT2SAS_ADAPTER *ioc, | ||
| 508 | struct _sas_port *mpt2sas_port, struct _sas_phy *mpt2sas_phy) | ||
| 509 | { | ||
| 510 | u64 sas_address = mpt2sas_port->remote_identify.sas_address; | ||
| 511 | |||
| 512 | dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev, | ||
| 513 | "remove: sas_addr(0x%016llx), phy(%d)\n", | ||
| 514 | (unsigned long long) sas_address, mpt2sas_phy->phy_id); | ||
| 515 | |||
| 516 | list_del(&mpt2sas_phy->port_siblings); | ||
| 517 | mpt2sas_port->num_phys--; | ||
| 518 | sas_port_delete_phy(mpt2sas_port->port, mpt2sas_phy->phy); | ||
| 519 | mpt2sas_phy->phy_belongs_to_port = 0; | ||
| 520 | } | ||
| 521 | |||
| 522 | /** | ||
| 523 | * _transport_add_phy - helper function to adding single phy to port | ||
| 524 | * @ioc: per adapter object | ||
| 525 | * @mpt2sas_port: mpt2sas per port object | ||
| 526 | * @mpt2sas_phy: mpt2sas per phy object | ||
| 527 | * | ||
| 528 | * Returns nothing. | ||
| 529 | */ | ||
| 530 | static void | ||
| 531 | _transport_add_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_port *mpt2sas_port, | ||
| 532 | struct _sas_phy *mpt2sas_phy) | ||
| 533 | { | ||
| 534 | u64 sas_address = mpt2sas_port->remote_identify.sas_address; | ||
| 535 | |||
| 536 | dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev, | ||
| 537 | "add: sas_addr(0x%016llx), phy(%d)\n", (unsigned long long) | ||
| 538 | sas_address, mpt2sas_phy->phy_id); | ||
| 539 | |||
| 540 | list_add_tail(&mpt2sas_phy->port_siblings, &mpt2sas_port->phy_list); | ||
| 541 | mpt2sas_port->num_phys++; | ||
| 542 | sas_port_add_phy(mpt2sas_port->port, mpt2sas_phy->phy); | ||
| 543 | mpt2sas_phy->phy_belongs_to_port = 1; | ||
| 544 | } | ||
| 545 | |||
| 546 | /** | ||
| 547 | * _transport_add_phy_to_an_existing_port - adding new phy to existing port | ||
| 548 | * @ioc: per adapter object | ||
| 549 | * @sas_node: sas node object (either expander or sas host) | ||
| 550 | * @mpt2sas_phy: mpt2sas per phy object | ||
| 551 | * @sas_address: sas address of device/expander were phy needs to be added to | ||
| 552 | * | ||
| 553 | * Returns nothing. | ||
| 554 | */ | ||
| 555 | static void | ||
| 556 | _transport_add_phy_to_an_existing_port(struct MPT2SAS_ADAPTER *ioc, | ||
| 557 | struct _sas_node *sas_node, struct _sas_phy *mpt2sas_phy, u64 sas_address) | ||
| 558 | { | ||
| 559 | struct _sas_port *mpt2sas_port; | ||
| 560 | struct _sas_phy *phy_srch; | ||
| 561 | |||
| 562 | if (mpt2sas_phy->phy_belongs_to_port == 1) | ||
| 563 | return; | ||
| 564 | |||
| 565 | list_for_each_entry(mpt2sas_port, &sas_node->sas_port_list, | ||
| 566 | port_list) { | ||
| 567 | if (mpt2sas_port->remote_identify.sas_address != | ||
| 568 | sas_address) | ||
| 569 | continue; | ||
| 570 | list_for_each_entry(phy_srch, &mpt2sas_port->phy_list, | ||
| 571 | port_siblings) { | ||
| 572 | if (phy_srch == mpt2sas_phy) | ||
| 573 | return; | ||
| 574 | } | ||
| 575 | _transport_add_phy(ioc, mpt2sas_port, mpt2sas_phy); | ||
| 576 | return; | ||
| 577 | } | ||
| 578 | |||
| 579 | } | ||
| 580 | |||
| 581 | /** | ||
| 582 | * _transport_del_phy_from_an_existing_port - delete phy from existing port | ||
| 583 | * @ioc: per adapter object | ||
| 584 | * @sas_node: sas node object (either expander or sas host) | ||
| 585 | * @mpt2sas_phy: mpt2sas per phy object | ||
| 586 | * | ||
| 587 | * Returns nothing. | ||
| 588 | */ | ||
| 589 | static void | ||
| 590 | _transport_del_phy_from_an_existing_port(struct MPT2SAS_ADAPTER *ioc, | ||
| 591 | struct _sas_node *sas_node, struct _sas_phy *mpt2sas_phy) | ||
| 592 | { | ||
| 593 | struct _sas_port *mpt2sas_port, *next; | ||
| 594 | struct _sas_phy *phy_srch; | ||
| 595 | |||
| 596 | if (mpt2sas_phy->phy_belongs_to_port == 0) | ||
| 597 | return; | ||
| 598 | |||
| 599 | list_for_each_entry_safe(mpt2sas_port, next, &sas_node->sas_port_list, | ||
| 600 | port_list) { | ||
| 601 | list_for_each_entry(phy_srch, &mpt2sas_port->phy_list, | ||
| 602 | port_siblings) { | ||
| 603 | if (phy_srch != mpt2sas_phy) | ||
| 604 | continue; | ||
| 605 | if (mpt2sas_port->num_phys == 1) | ||
| 606 | _transport_delete_port(ioc, mpt2sas_port); | ||
| 607 | else | ||
| 608 | _transport_delete_phy(ioc, mpt2sas_port, | ||
| 609 | mpt2sas_phy); | ||
| 610 | return; | ||
| 611 | } | ||
| 612 | } | ||
| 613 | } | ||
| 614 | |||
| 615 | /** | ||
| 616 | * _transport_sanity_check - sanity check when adding a new port | ||
| 617 | * @ioc: per adapter object | ||
| 618 | * @sas_node: sas node object (either expander or sas host) | ||
| 619 | * @sas_address: sas address of device being added | ||
| 620 | * | ||
| 621 | * See the explanation above from _transport_delete_duplicate_port | ||
| 622 | */ | ||
| 623 | static void | ||
| 624 | _transport_sanity_check(struct MPT2SAS_ADAPTER *ioc, struct _sas_node *sas_node, | ||
| 625 | u64 sas_address) | ||
| 626 | { | ||
| 627 | int i; | ||
| 628 | |||
| 629 | for (i = 0; i < sas_node->num_phys; i++) { | ||
| 630 | if (sas_node->phy[i].remote_identify.sas_address != sas_address) | ||
| 631 | continue; | ||
| 632 | if (sas_node->phy[i].phy_belongs_to_port == 1) | ||
| 633 | _transport_del_phy_from_an_existing_port(ioc, sas_node, | ||
| 634 | &sas_node->phy[i]); | ||
| 635 | } | ||
| 636 | } | ||
| 637 | |||
| 638 | /** | ||
| 639 | * mpt2sas_transport_port_add - insert port to the list | ||
| 640 | * @ioc: per adapter object | ||
| 641 | * @handle: handle of attached device | ||
| 642 | * @sas_address: sas address of parent expander or sas host | ||
| 643 | * Context: This function will acquire ioc->sas_node_lock. | ||
| 644 | * | ||
| 645 | * Adding new port object to the sas_node->sas_port_list. | ||
| 646 | * | ||
| 647 | * Returns mpt2sas_port. | ||
| 648 | */ | ||
| 649 | struct _sas_port * | ||
| 650 | mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER *ioc, u16 handle, | ||
| 651 | u64 sas_address) | ||
| 652 | { | ||
| 653 | struct _sas_phy *mpt2sas_phy, *next; | ||
| 654 | struct _sas_port *mpt2sas_port; | ||
| 655 | unsigned long flags; | ||
| 656 | struct _sas_node *sas_node; | ||
| 657 | struct sas_rphy *rphy; | ||
| 658 | int i; | ||
| 659 | struct sas_port *port; | ||
| 660 | |||
| 661 | mpt2sas_port = kzalloc(sizeof(struct _sas_port), | ||
| 662 | GFP_KERNEL); | ||
| 663 | if (!mpt2sas_port) { | ||
| 664 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 665 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 666 | return NULL; | ||
| 667 | } | ||
| 668 | |||
| 669 | INIT_LIST_HEAD(&mpt2sas_port->port_list); | ||
| 670 | INIT_LIST_HEAD(&mpt2sas_port->phy_list); | ||
| 671 | spin_lock_irqsave(&ioc->sas_node_lock, flags); | ||
| 672 | sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address); | ||
| 673 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | ||
| 674 | |||
| 675 | if (!sas_node) { | ||
| 676 | printk(MPT2SAS_ERR_FMT "%s: Could not find " | ||
| 677 | "parent sas_address(0x%016llx)!\n", ioc->name, | ||
| 678 | __func__, (unsigned long long)sas_address); | ||
| 679 | goto out_fail; | ||
| 680 | } | ||
| 681 | |||
| 682 | if ((_transport_set_identify(ioc, handle, | ||
| 683 | &mpt2sas_port->remote_identify))) { | ||
| 684 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 685 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 686 | goto out_fail; | ||
| 687 | } | ||
| 688 | |||
| 689 | if (mpt2sas_port->remote_identify.device_type == SAS_PHY_UNUSED) { | ||
| 690 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 691 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 692 | goto out_fail; | ||
| 693 | } | ||
| 694 | |||
| 695 | _transport_sanity_check(ioc, sas_node, | ||
| 696 | mpt2sas_port->remote_identify.sas_address); | ||
| 697 | |||
| 698 | for (i = 0; i < sas_node->num_phys; i++) { | ||
| 699 | if (sas_node->phy[i].remote_identify.sas_address != | ||
| 700 | mpt2sas_port->remote_identify.sas_address) | ||
| 701 | continue; | ||
| 702 | list_add_tail(&sas_node->phy[i].port_siblings, | ||
| 703 | &mpt2sas_port->phy_list); | ||
| 704 | mpt2sas_port->num_phys++; | ||
| 705 | } | ||
| 706 | |||
| 707 | if (!mpt2sas_port->num_phys) { | ||
| 708 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 709 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 710 | goto out_fail; | ||
| 711 | } | ||
| 712 | |||
| 713 | port = sas_port_alloc_num(sas_node->parent_dev); | ||
| 714 | if ((sas_port_add(port))) { | ||
| 715 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 716 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 717 | goto out_fail; | ||
| 718 | } | ||
| 719 | |||
| 720 | list_for_each_entry(mpt2sas_phy, &mpt2sas_port->phy_list, | ||
| 721 | port_siblings) { | ||
| 722 | if ((ioc->logging_level & MPT_DEBUG_TRANSPORT)) | ||
| 723 | dev_printk(KERN_INFO, &port->dev, "add: handle(0x%04x)" | ||
| 724 | ", sas_addr(0x%016llx), phy(%d)\n", handle, | ||
| 725 | (unsigned long long) | ||
| 726 | mpt2sas_port->remote_identify.sas_address, | ||
| 727 | mpt2sas_phy->phy_id); | ||
| 728 | sas_port_add_phy(port, mpt2sas_phy->phy); | ||
| 729 | mpt2sas_phy->phy_belongs_to_port = 1; | ||
| 730 | } | ||
| 731 | |||
| 732 | mpt2sas_port->port = port; | ||
| 733 | if (mpt2sas_port->remote_identify.device_type == SAS_END_DEVICE) | ||
| 734 | rphy = sas_end_device_alloc(port); | ||
| 735 | else | ||
| 736 | rphy = sas_expander_alloc(port, | ||
| 737 | mpt2sas_port->remote_identify.device_type); | ||
| 738 | |||
| 739 | rphy->identify = mpt2sas_port->remote_identify; | ||
| 740 | if ((sas_rphy_add(rphy))) { | ||
| 741 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 742 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 743 | } | ||
| 744 | if ((ioc->logging_level & MPT_DEBUG_TRANSPORT)) | ||
| 745 | dev_printk(KERN_INFO, &rphy->dev, "add: handle(0x%04x), " | ||
| 746 | "sas_addr(0x%016llx)\n", handle, | ||
| 747 | (unsigned long long) | ||
| 748 | mpt2sas_port->remote_identify.sas_address); | ||
| 749 | mpt2sas_port->rphy = rphy; | ||
| 750 | spin_lock_irqsave(&ioc->sas_node_lock, flags); | ||
| 751 | list_add_tail(&mpt2sas_port->port_list, &sas_node->sas_port_list); | ||
| 752 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | ||
| 753 | |||
| 754 | /* fill in report manufacture */ | ||
| 755 | if (mpt2sas_port->remote_identify.device_type == | ||
| 756 | MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER || | ||
| 757 | mpt2sas_port->remote_identify.device_type == | ||
| 758 | MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER) | ||
| 759 | _transport_expander_report_manufacture(ioc, | ||
| 760 | mpt2sas_port->remote_identify.sas_address, | ||
| 761 | rphy_to_expander_device(rphy)); | ||
| 762 | |||
| 763 | return mpt2sas_port; | ||
| 764 | |||
| 765 | out_fail: | ||
| 766 | list_for_each_entry_safe(mpt2sas_phy, next, &mpt2sas_port->phy_list, | ||
| 767 | port_siblings) | ||
| 768 | list_del(&mpt2sas_phy->port_siblings); | ||
| 769 | kfree(mpt2sas_port); | ||
| 770 | return NULL; | ||
| 771 | } | ||
| 772 | |||
| 773 | /** | ||
| 774 | * mpt2sas_transport_port_remove - remove port from the list | ||
| 775 | * @ioc: per adapter object | ||
| 776 | * @sas_address: sas address of attached device | ||
| 777 | * @sas_address_parent: sas address of parent expander or sas host | ||
| 778 | * Context: This function will acquire ioc->sas_node_lock. | ||
| 779 | * | ||
| 780 | * Removing object and freeing associated memory from the | ||
| 781 | * ioc->sas_port_list. | ||
| 782 | * | ||
| 783 | * Return nothing. | ||
| 784 | */ | ||
| 785 | void | ||
| 786 | mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address, | ||
| 787 | u64 sas_address_parent) | ||
| 788 | { | ||
| 789 | int i; | ||
| 790 | unsigned long flags; | ||
| 791 | struct _sas_port *mpt2sas_port, *next; | ||
| 792 | struct _sas_node *sas_node; | ||
| 793 | u8 found = 0; | ||
| 794 | struct _sas_phy *mpt2sas_phy, *next_phy; | ||
| 795 | |||
| 796 | spin_lock_irqsave(&ioc->sas_node_lock, flags); | ||
| 797 | sas_node = _transport_sas_node_find_by_sas_address(ioc, | ||
| 798 | sas_address_parent); | ||
| 799 | if (!sas_node) { | ||
| 800 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | ||
| 801 | return; | ||
| 802 | } | ||
| 803 | list_for_each_entry_safe(mpt2sas_port, next, &sas_node->sas_port_list, | ||
| 804 | port_list) { | ||
| 805 | if (mpt2sas_port->remote_identify.sas_address != sas_address) | ||
| 806 | continue; | ||
| 807 | found = 1; | ||
| 808 | list_del(&mpt2sas_port->port_list); | ||
| 809 | goto out; | ||
| 810 | } | ||
| 811 | out: | ||
| 812 | if (!found) { | ||
| 813 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | ||
| 814 | return; | ||
| 815 | } | ||
| 816 | |||
| 817 | for (i = 0; i < sas_node->num_phys; i++) { | ||
| 818 | if (sas_node->phy[i].remote_identify.sas_address == sas_address) | ||
| 819 | memset(&sas_node->phy[i].remote_identify, 0 , | ||
| 820 | sizeof(struct sas_identify)); | ||
| 821 | } | ||
| 822 | |||
| 823 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | ||
| 824 | list_for_each_entry_safe(mpt2sas_phy, next_phy, | ||
| 825 | &mpt2sas_port->phy_list, port_siblings) { | ||
| 826 | if ((ioc->logging_level & MPT_DEBUG_TRANSPORT)) | ||
| 827 | dev_printk(KERN_INFO, &mpt2sas_port->port->dev, | ||
| 828 | "remove: sas_addr(0x%016llx), phy(%d)\n", | ||
| 829 | (unsigned long long) | ||
| 830 | mpt2sas_port->remote_identify.sas_address, | ||
| 831 | mpt2sas_phy->phy_id); | ||
| 832 | mpt2sas_phy->phy_belongs_to_port = 0; | ||
| 833 | sas_port_delete_phy(mpt2sas_port->port, mpt2sas_phy->phy); | ||
| 834 | list_del(&mpt2sas_phy->port_siblings); | ||
| 835 | } | ||
| 836 | sas_port_delete(mpt2sas_port->port); | ||
| 837 | kfree(mpt2sas_port); | ||
| 838 | } | ||
| 839 | |||
| 840 | /** | ||
| 841 | * mpt2sas_transport_add_host_phy - report sas_host phy to transport | ||
| 842 | * @ioc: per adapter object | ||
| 843 | * @mpt2sas_phy: mpt2sas per phy object | ||
| 844 | * @phy_pg0: sas phy page 0 | ||
| 845 | * @parent_dev: parent device class object | ||
| 846 | * | ||
| 847 | * Returns 0 for success, non-zero for failure. | ||
| 848 | */ | ||
| 849 | int | ||
| 850 | mpt2sas_transport_add_host_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy | ||
| 851 | *mpt2sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev) | ||
| 852 | { | ||
| 853 | struct sas_phy *phy; | ||
| 854 | int phy_index = mpt2sas_phy->phy_id; | ||
| 855 | |||
| 856 | |||
| 857 | INIT_LIST_HEAD(&mpt2sas_phy->port_siblings); | ||
| 858 | phy = sas_phy_alloc(parent_dev, phy_index); | ||
| 859 | if (!phy) { | ||
| 860 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 861 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 862 | return -1; | ||
| 863 | } | ||
| 864 | if ((_transport_set_identify(ioc, mpt2sas_phy->handle, | ||
| 865 | &mpt2sas_phy->identify))) { | ||
| 866 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 867 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 868 | return -1; | ||
| 869 | } | ||
| 870 | phy->identify = mpt2sas_phy->identify; | ||
| 871 | mpt2sas_phy->attached_handle = le16_to_cpu(phy_pg0.AttachedDevHandle); | ||
| 872 | if (mpt2sas_phy->attached_handle) | ||
| 873 | _transport_set_identify(ioc, mpt2sas_phy->attached_handle, | ||
| 874 | &mpt2sas_phy->remote_identify); | ||
| 875 | phy->identify.phy_identifier = mpt2sas_phy->phy_id; | ||
| 876 | phy->negotiated_linkrate = _transport_convert_phy_link_rate( | ||
| 877 | phy_pg0.NegotiatedLinkRate & MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL); | ||
| 878 | phy->minimum_linkrate_hw = _transport_convert_phy_link_rate( | ||
| 879 | phy_pg0.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK); | ||
| 880 | phy->maximum_linkrate_hw = _transport_convert_phy_link_rate( | ||
| 881 | phy_pg0.HwLinkRate >> 4); | ||
| 882 | phy->minimum_linkrate = _transport_convert_phy_link_rate( | ||
| 883 | phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK); | ||
| 884 | phy->maximum_linkrate = _transport_convert_phy_link_rate( | ||
| 885 | phy_pg0.ProgrammedLinkRate >> 4); | ||
| 886 | |||
| 887 | if ((sas_phy_add(phy))) { | ||
| 888 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 889 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 890 | sas_phy_free(phy); | ||
| 891 | return -1; | ||
| 892 | } | ||
| 893 | if ((ioc->logging_level & MPT_DEBUG_TRANSPORT)) | ||
| 894 | dev_printk(KERN_INFO, &phy->dev, | ||
| 895 | "add: handle(0x%04x), sas_addr(0x%016llx)\n" | ||
| 896 | "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n", | ||
| 897 | mpt2sas_phy->handle, (unsigned long long) | ||
| 898 | mpt2sas_phy->identify.sas_address, | ||
| 899 | mpt2sas_phy->attached_handle, | ||
| 900 | (unsigned long long) | ||
| 901 | mpt2sas_phy->remote_identify.sas_address); | ||
| 902 | mpt2sas_phy->phy = phy; | ||
| 903 | return 0; | ||
| 904 | } | ||
| 905 | |||
| 906 | |||
| 907 | /** | ||
| 908 | * mpt2sas_transport_add_expander_phy - report expander phy to transport | ||
| 909 | * @ioc: per adapter object | ||
| 910 | * @mpt2sas_phy: mpt2sas per phy object | ||
| 911 | * @expander_pg1: expander page 1 | ||
| 912 | * @parent_dev: parent device class object | ||
| 913 | * | ||
| 914 | * Returns 0 for success, non-zero for failure. | ||
| 915 | */ | ||
| 916 | int | ||
| 917 | mpt2sas_transport_add_expander_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy | ||
| 918 | *mpt2sas_phy, Mpi2ExpanderPage1_t expander_pg1, struct device *parent_dev) | ||
| 919 | { | ||
| 920 | struct sas_phy *phy; | ||
| 921 | int phy_index = mpt2sas_phy->phy_id; | ||
| 922 | |||
| 923 | INIT_LIST_HEAD(&mpt2sas_phy->port_siblings); | ||
| 924 | phy = sas_phy_alloc(parent_dev, phy_index); | ||
| 925 | if (!phy) { | ||
| 926 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 927 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 928 | return -1; | ||
| 929 | } | ||
| 930 | if ((_transport_set_identify(ioc, mpt2sas_phy->handle, | ||
| 931 | &mpt2sas_phy->identify))) { | ||
| 932 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 933 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 934 | return -1; | ||
| 935 | } | ||
| 936 | phy->identify = mpt2sas_phy->identify; | ||
| 937 | mpt2sas_phy->attached_handle = | ||
| 938 | le16_to_cpu(expander_pg1.AttachedDevHandle); | ||
| 939 | if (mpt2sas_phy->attached_handle) | ||
| 940 | _transport_set_identify(ioc, mpt2sas_phy->attached_handle, | ||
| 941 | &mpt2sas_phy->remote_identify); | ||
| 942 | phy->identify.phy_identifier = mpt2sas_phy->phy_id; | ||
| 943 | phy->negotiated_linkrate = _transport_convert_phy_link_rate( | ||
| 944 | expander_pg1.NegotiatedLinkRate & | ||
| 945 | MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL); | ||
| 946 | phy->minimum_linkrate_hw = _transport_convert_phy_link_rate( | ||
| 947 | expander_pg1.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK); | ||
| 948 | phy->maximum_linkrate_hw = _transport_convert_phy_link_rate( | ||
| 949 | expander_pg1.HwLinkRate >> 4); | ||
| 950 | phy->minimum_linkrate = _transport_convert_phy_link_rate( | ||
| 951 | expander_pg1.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK); | ||
| 952 | phy->maximum_linkrate = _transport_convert_phy_link_rate( | ||
| 953 | expander_pg1.ProgrammedLinkRate >> 4); | ||
| 954 | |||
| 955 | if ((sas_phy_add(phy))) { | ||
| 956 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 957 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 958 | sas_phy_free(phy); | ||
| 959 | return -1; | ||
| 960 | } | ||
| 961 | if ((ioc->logging_level & MPT_DEBUG_TRANSPORT)) | ||
| 962 | dev_printk(KERN_INFO, &phy->dev, | ||
| 963 | "add: handle(0x%04x), sas_addr(0x%016llx)\n" | ||
| 964 | "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n", | ||
| 965 | mpt2sas_phy->handle, (unsigned long long) | ||
| 966 | mpt2sas_phy->identify.sas_address, | ||
| 967 | mpt2sas_phy->attached_handle, | ||
| 968 | (unsigned long long) | ||
| 969 | mpt2sas_phy->remote_identify.sas_address); | ||
| 970 | mpt2sas_phy->phy = phy; | ||
| 971 | return 0; | ||
| 972 | } | ||
| 973 | |||
| 974 | /** | ||
| 975 | * mpt2sas_transport_update_links - refreshing phy link changes | ||
| 976 | * @ioc: per adapter object | ||
| 977 | * @sas_address: sas address of parent expander or sas host | ||
| 978 | * @handle: attached device handle | ||
| 979 | * @phy_numberv: phy number | ||
| 980 | * @link_rate: new link rate | ||
| 981 | * | ||
| 982 | * Returns nothing. | ||
| 983 | */ | ||
| 984 | void | ||
| 985 | mpt2sas_transport_update_links(struct MPT2SAS_ADAPTER *ioc, | ||
| 986 | u64 sas_address, u16 handle, u8 phy_number, u8 link_rate) | ||
| 987 | { | ||
| 988 | unsigned long flags; | ||
| 989 | struct _sas_node *sas_node; | ||
| 990 | struct _sas_phy *mpt2sas_phy; | ||
| 991 | |||
| 992 | if (ioc->shost_recovery || ioc->pci_error_recovery) | ||
| 993 | return; | ||
| 994 | |||
| 995 | spin_lock_irqsave(&ioc->sas_node_lock, flags); | ||
| 996 | sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address); | ||
| 997 | if (!sas_node) { | ||
| 998 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | ||
| 999 | return; | ||
| 1000 | } | ||
| 1001 | |||
| 1002 | mpt2sas_phy = &sas_node->phy[phy_number]; | ||
| 1003 | mpt2sas_phy->attached_handle = handle; | ||
| 1004 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | ||
| 1005 | if (handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5)) { | ||
| 1006 | _transport_set_identify(ioc, handle, | ||
| 1007 | &mpt2sas_phy->remote_identify); | ||
| 1008 | _transport_add_phy_to_an_existing_port(ioc, sas_node, | ||
| 1009 | mpt2sas_phy, mpt2sas_phy->remote_identify.sas_address); | ||
| 1010 | } else | ||
| 1011 | memset(&mpt2sas_phy->remote_identify, 0 , sizeof(struct | ||
| 1012 | sas_identify)); | ||
| 1013 | |||
| 1014 | if (mpt2sas_phy->phy) | ||
| 1015 | mpt2sas_phy->phy->negotiated_linkrate = | ||
| 1016 | _transport_convert_phy_link_rate(link_rate); | ||
| 1017 | |||
| 1018 | if ((ioc->logging_level & MPT_DEBUG_TRANSPORT)) | ||
| 1019 | dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev, | ||
| 1020 | "refresh: parent sas_addr(0x%016llx),\n" | ||
| 1021 | "\tlink_rate(0x%02x), phy(%d)\n" | ||
| 1022 | "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n", | ||
| 1023 | (unsigned long long)sas_address, | ||
| 1024 | link_rate, phy_number, handle, (unsigned long long) | ||
| 1025 | mpt2sas_phy->remote_identify.sas_address); | ||
| 1026 | } | ||
| 1027 | |||
| 1028 | static inline void * | ||
| 1029 | phy_to_ioc(struct sas_phy *phy) | ||
| 1030 | { | ||
| 1031 | struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); | ||
| 1032 | return shost_priv(shost); | ||
| 1033 | } | ||
| 1034 | |||
| 1035 | static inline void * | ||
| 1036 | rphy_to_ioc(struct sas_rphy *rphy) | ||
| 1037 | { | ||
| 1038 | struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent); | ||
| 1039 | return shost_priv(shost); | ||
| 1040 | } | ||
| 1041 | |||
| 1042 | |||
| 1043 | /* report phy error log structure */ | ||
| 1044 | struct phy_error_log_request{ | ||
| 1045 | u8 smp_frame_type; /* 0x40 */ | ||
| 1046 | u8 function; /* 0x11 */ | ||
| 1047 | u8 allocated_response_length; | ||
| 1048 | u8 request_length; /* 02 */ | ||
| 1049 | u8 reserved_1[5]; | ||
| 1050 | u8 phy_identifier; | ||
| 1051 | u8 reserved_2[2]; | ||
| 1052 | }; | ||
| 1053 | |||
| 1054 | /* report phy error log reply structure */ | ||
| 1055 | struct phy_error_log_reply{ | ||
| 1056 | u8 smp_frame_type; /* 0x41 */ | ||
| 1057 | u8 function; /* 0x11 */ | ||
| 1058 | u8 function_result; | ||
| 1059 | u8 response_length; | ||
| 1060 | __be16 expander_change_count; | ||
| 1061 | u8 reserved_1[3]; | ||
| 1062 | u8 phy_identifier; | ||
| 1063 | u8 reserved_2[2]; | ||
| 1064 | __be32 invalid_dword; | ||
| 1065 | __be32 running_disparity_error; | ||
| 1066 | __be32 loss_of_dword_sync; | ||
| 1067 | __be32 phy_reset_problem; | ||
| 1068 | }; | ||
| 1069 | |||
| 1070 | /** | ||
| 1071 | * _transport_get_expander_phy_error_log - return expander counters | ||
| 1072 | * @ioc: per adapter object | ||
| 1073 | * @phy: The sas phy object | ||
| 1074 | * | ||
| 1075 | * Returns 0 for success, non-zero for failure. | ||
| 1076 | * | ||
| 1077 | */ | ||
| 1078 | static int | ||
| 1079 | _transport_get_expander_phy_error_log(struct MPT2SAS_ADAPTER *ioc, | ||
| 1080 | struct sas_phy *phy) | ||
| 1081 | { | ||
| 1082 | Mpi2SmpPassthroughRequest_t *mpi_request; | ||
| 1083 | Mpi2SmpPassthroughReply_t *mpi_reply; | ||
| 1084 | struct phy_error_log_request *phy_error_log_request; | ||
| 1085 | struct phy_error_log_reply *phy_error_log_reply; | ||
| 1086 | int rc; | ||
| 1087 | u16 smid; | ||
| 1088 | u32 ioc_state; | ||
| 1089 | unsigned long timeleft; | ||
| 1090 | void *psge; | ||
| 1091 | u32 sgl_flags; | ||
| 1092 | u8 issue_reset = 0; | ||
| 1093 | void *data_out = NULL; | ||
| 1094 | dma_addr_t data_out_dma; | ||
| 1095 | u32 sz; | ||
| 1096 | u16 wait_state_count; | ||
| 1097 | |||
| 1098 | if (ioc->shost_recovery || ioc->pci_error_recovery) { | ||
| 1099 | printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n", | ||
| 1100 | __func__, ioc->name); | ||
| 1101 | return -EFAULT; | ||
| 1102 | } | ||
| 1103 | |||
| 1104 | mutex_lock(&ioc->transport_cmds.mutex); | ||
| 1105 | |||
| 1106 | if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) { | ||
| 1107 | printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n", | ||
| 1108 | ioc->name, __func__); | ||
| 1109 | rc = -EAGAIN; | ||
| 1110 | goto out; | ||
| 1111 | } | ||
| 1112 | ioc->transport_cmds.status = MPT2_CMD_PENDING; | ||
| 1113 | |||
| 1114 | wait_state_count = 0; | ||
| 1115 | ioc_state = mpt2sas_base_get_iocstate(ioc, 1); | ||
| 1116 | while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { | ||
| 1117 | if (wait_state_count++ == 10) { | ||
| 1118 | printk(MPT2SAS_ERR_FMT | ||
| 1119 | "%s: failed due to ioc not operational\n", | ||
| 1120 | ioc->name, __func__); | ||
| 1121 | rc = -EFAULT; | ||
| 1122 | goto out; | ||
| 1123 | } | ||
| 1124 | ssleep(1); | ||
| 1125 | ioc_state = mpt2sas_base_get_iocstate(ioc, 1); | ||
| 1126 | printk(MPT2SAS_INFO_FMT "%s: waiting for " | ||
| 1127 | "operational state(count=%d)\n", ioc->name, | ||
| 1128 | __func__, wait_state_count); | ||
| 1129 | } | ||
| 1130 | if (wait_state_count) | ||
| 1131 | printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n", | ||
| 1132 | ioc->name, __func__); | ||
| 1133 | |||
| 1134 | smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx); | ||
| 1135 | if (!smid) { | ||
| 1136 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", | ||
| 1137 | ioc->name, __func__); | ||
| 1138 | rc = -EAGAIN; | ||
| 1139 | goto out; | ||
| 1140 | } | ||
| 1141 | |||
| 1142 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); | ||
| 1143 | ioc->transport_cmds.smid = smid; | ||
| 1144 | |||
| 1145 | sz = sizeof(struct phy_error_log_request) + | ||
| 1146 | sizeof(struct phy_error_log_reply); | ||
| 1147 | data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma); | ||
| 1148 | if (!data_out) { | ||
| 1149 | printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, | ||
| 1150 | __LINE__, __func__); | ||
| 1151 | rc = -ENOMEM; | ||
| 1152 | mpt2sas_base_free_smid(ioc, smid); | ||
| 1153 | goto out; | ||
| 1154 | } | ||
| 1155 | |||
| 1156 | rc = -EINVAL; | ||
| 1157 | memset(data_out, 0, sz); | ||
| 1158 | phy_error_log_request = data_out; | ||
| 1159 | phy_error_log_request->smp_frame_type = 0x40; | ||
| 1160 | phy_error_log_request->function = 0x11; | ||
| 1161 | phy_error_log_request->request_length = 2; | ||
| 1162 | phy_error_log_request->allocated_response_length = 0; | ||
| 1163 | phy_error_log_request->phy_identifier = phy->number; | ||
| 1164 | |||
| 1165 | memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t)); | ||
| 1166 | mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH; | ||
| 1167 | mpi_request->PhysicalPort = 0xFF; | ||
| 1168 | mpi_request->VF_ID = 0; /* TODO */ | ||
| 1169 | mpi_request->VP_ID = 0; | ||
| 1170 | mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address); | ||
| 1171 | mpi_request->RequestDataLength = | ||
| 1172 | cpu_to_le16(sizeof(struct phy_error_log_request)); | ||
| 1173 | psge = &mpi_request->SGL; | ||
| 1174 | |||
| 1175 | /* WRITE sgel first */ | ||
| 1176 | sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT | | ||
| 1177 | MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC); | ||
| 1178 | sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; | ||
| 1179 | ioc->base_add_sg_single(psge, sgl_flags | | ||
| 1180 | sizeof(struct phy_error_log_request), data_out_dma); | ||
| 1181 | |||
| 1182 | /* incr sgel */ | ||
| 1183 | psge += ioc->sge_size; | ||
| 1184 | |||
| 1185 | /* READ sgel last */ | ||
| 1186 | sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT | | ||
| 1187 | MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER | | ||
| 1188 | MPI2_SGE_FLAGS_END_OF_LIST); | ||
| 1189 | sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; | ||
| 1190 | ioc->base_add_sg_single(psge, sgl_flags | | ||
| 1191 | sizeof(struct phy_error_log_reply), data_out_dma + | ||
| 1192 | sizeof(struct phy_error_log_request)); | ||
| 1193 | |||
| 1194 | dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_error_log - " | ||
| 1195 | "send to sas_addr(0x%016llx), phy(%d)\n", ioc->name, | ||
| 1196 | (unsigned long long)phy->identify.sas_address, phy->number)); | ||
| 1197 | init_completion(&ioc->transport_cmds.done); | ||
| 1198 | mpt2sas_base_put_smid_default(ioc, smid); | ||
| 1199 | timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done, | ||
| 1200 | 10*HZ); | ||
| 1201 | |||
| 1202 | if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) { | ||
| 1203 | printk(MPT2SAS_ERR_FMT "%s: timeout\n", | ||
| 1204 | ioc->name, __func__); | ||
| 1205 | _debug_dump_mf(mpi_request, | ||
| 1206 | sizeof(Mpi2SmpPassthroughRequest_t)/4); | ||
| 1207 | if (!(ioc->transport_cmds.status & MPT2_CMD_RESET)) | ||
| 1208 | issue_reset = 1; | ||
| 1209 | goto issue_host_reset; | ||
| 1210 | } | ||
| 1211 | |||
| 1212 | dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_error_log - " | ||
| 1213 | "complete\n", ioc->name)); | ||
| 1214 | |||
| 1215 | if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) { | ||
| 1216 | |||
| 1217 | mpi_reply = ioc->transport_cmds.reply; | ||
| 1218 | |||
| 1219 | dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 1220 | "phy_error_log - reply data transfer size(%d)\n", | ||
| 1221 | ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength))); | ||
| 1222 | |||
| 1223 | if (le16_to_cpu(mpi_reply->ResponseDataLength) != | ||
| 1224 | sizeof(struct phy_error_log_reply)) | ||
| 1225 | goto out; | ||
| 1226 | |||
| 1227 | phy_error_log_reply = data_out + | ||
| 1228 | sizeof(struct phy_error_log_request); | ||
| 1229 | |||
| 1230 | dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 1231 | "phy_error_log - function_result(%d)\n", | ||
| 1232 | ioc->name, phy_error_log_reply->function_result)); | ||
| 1233 | |||
| 1234 | phy->invalid_dword_count = | ||
| 1235 | be32_to_cpu(phy_error_log_reply->invalid_dword); | ||
| 1236 | phy->running_disparity_error_count = | ||
| 1237 | be32_to_cpu(phy_error_log_reply->running_disparity_error); | ||
| 1238 | phy->loss_of_dword_sync_count = | ||
| 1239 | be32_to_cpu(phy_error_log_reply->loss_of_dword_sync); | ||
| 1240 | phy->phy_reset_problem_count = | ||
| 1241 | be32_to_cpu(phy_error_log_reply->phy_reset_problem); | ||
| 1242 | rc = 0; | ||
| 1243 | } else | ||
| 1244 | dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 1245 | "phy_error_log - no reply\n", ioc->name)); | ||
| 1246 | |||
| 1247 | issue_host_reset: | ||
| 1248 | if (issue_reset) | ||
| 1249 | mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, | ||
| 1250 | FORCE_BIG_HAMMER); | ||
| 1251 | out: | ||
| 1252 | ioc->transport_cmds.status = MPT2_CMD_NOT_USED; | ||
| 1253 | if (data_out) | ||
| 1254 | pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma); | ||
| 1255 | |||
| 1256 | mutex_unlock(&ioc->transport_cmds.mutex); | ||
| 1257 | return rc; | ||
| 1258 | } | ||
| 1259 | |||
| 1260 | /** | ||
| 1261 | * _transport_get_linkerrors - return phy counters for both hba and expanders | ||
| 1262 | * @phy: The sas phy object | ||
| 1263 | * | ||
| 1264 | * Returns 0 for success, non-zero for failure. | ||
| 1265 | * | ||
| 1266 | */ | ||
| 1267 | static int | ||
| 1268 | _transport_get_linkerrors(struct sas_phy *phy) | ||
| 1269 | { | ||
| 1270 | struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy); | ||
| 1271 | unsigned long flags; | ||
| 1272 | Mpi2ConfigReply_t mpi_reply; | ||
| 1273 | Mpi2SasPhyPage1_t phy_pg1; | ||
| 1274 | |||
| 1275 | spin_lock_irqsave(&ioc->sas_node_lock, flags); | ||
| 1276 | if (_transport_sas_node_find_by_sas_address(ioc, | ||
| 1277 | phy->identify.sas_address) == NULL) { | ||
| 1278 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | ||
| 1279 | return -EINVAL; | ||
| 1280 | } | ||
| 1281 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | ||
| 1282 | |||
| 1283 | if (phy->identify.sas_address != ioc->sas_hba.sas_address) | ||
| 1284 | return _transport_get_expander_phy_error_log(ioc, phy); | ||
| 1285 | |||
| 1286 | /* get hba phy error logs */ | ||
| 1287 | if ((mpt2sas_config_get_phy_pg1(ioc, &mpi_reply, &phy_pg1, | ||
| 1288 | phy->number))) { | ||
| 1289 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 1290 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 1291 | return -ENXIO; | ||
| 1292 | } | ||
| 1293 | |||
| 1294 | if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) | ||
| 1295 | printk(MPT2SAS_INFO_FMT "phy(%d), ioc_status" | ||
| 1296 | "(0x%04x), loginfo(0x%08x)\n", ioc->name, | ||
| 1297 | phy->number, le16_to_cpu(mpi_reply.IOCStatus), | ||
| 1298 | le32_to_cpu(mpi_reply.IOCLogInfo)); | ||
| 1299 | |||
| 1300 | phy->invalid_dword_count = le32_to_cpu(phy_pg1.InvalidDwordCount); | ||
| 1301 | phy->running_disparity_error_count = | ||
| 1302 | le32_to_cpu(phy_pg1.RunningDisparityErrorCount); | ||
| 1303 | phy->loss_of_dword_sync_count = | ||
| 1304 | le32_to_cpu(phy_pg1.LossDwordSynchCount); | ||
| 1305 | phy->phy_reset_problem_count = | ||
| 1306 | le32_to_cpu(phy_pg1.PhyResetProblemCount); | ||
| 1307 | return 0; | ||
| 1308 | } | ||
| 1309 | |||
| 1310 | /** | ||
| 1311 | * _transport_get_enclosure_identifier - | ||
| 1312 | * @phy: The sas phy object | ||
| 1313 | * | ||
| 1314 | * Obtain the enclosure logical id for an expander. | ||
| 1315 | * Returns 0 for success, non-zero for failure. | ||
| 1316 | */ | ||
| 1317 | static int | ||
| 1318 | _transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier) | ||
| 1319 | { | ||
| 1320 | struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy); | ||
| 1321 | struct _sas_device *sas_device; | ||
| 1322 | unsigned long flags; | ||
| 1323 | int rc; | ||
| 1324 | |||
| 1325 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 1326 | sas_device = __mpt2sas_get_sdev_by_addr(ioc, | ||
| 1327 | rphy->identify.sas_address); | ||
| 1328 | if (sas_device) { | ||
| 1329 | *identifier = sas_device->enclosure_logical_id; | ||
| 1330 | rc = 0; | ||
| 1331 | sas_device_put(sas_device); | ||
| 1332 | } else { | ||
| 1333 | *identifier = 0; | ||
| 1334 | rc = -ENXIO; | ||
| 1335 | } | ||
| 1336 | |||
| 1337 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 1338 | return rc; | ||
| 1339 | } | ||
| 1340 | |||
| 1341 | /** | ||
| 1342 | * _transport_get_bay_identifier - | ||
| 1343 | * @phy: The sas phy object | ||
| 1344 | * | ||
| 1345 | * Returns the slot id for a device that resides inside an enclosure. | ||
| 1346 | */ | ||
| 1347 | static int | ||
| 1348 | _transport_get_bay_identifier(struct sas_rphy *rphy) | ||
| 1349 | { | ||
| 1350 | struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy); | ||
| 1351 | struct _sas_device *sas_device; | ||
| 1352 | unsigned long flags; | ||
| 1353 | int rc; | ||
| 1354 | |||
| 1355 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 1356 | sas_device = __mpt2sas_get_sdev_by_addr(ioc, | ||
| 1357 | rphy->identify.sas_address); | ||
| 1358 | if (sas_device) { | ||
| 1359 | rc = sas_device->slot; | ||
| 1360 | sas_device_put(sas_device); | ||
| 1361 | } else { | ||
| 1362 | rc = -ENXIO; | ||
| 1363 | } | ||
| 1364 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 1365 | return rc; | ||
| 1366 | } | ||
| 1367 | |||
| 1368 | /* phy control request structure */ | ||
| 1369 | struct phy_control_request{ | ||
| 1370 | u8 smp_frame_type; /* 0x40 */ | ||
| 1371 | u8 function; /* 0x91 */ | ||
| 1372 | u8 allocated_response_length; | ||
| 1373 | u8 request_length; /* 0x09 */ | ||
| 1374 | u16 expander_change_count; | ||
| 1375 | u8 reserved_1[3]; | ||
| 1376 | u8 phy_identifier; | ||
| 1377 | u8 phy_operation; | ||
| 1378 | u8 reserved_2[13]; | ||
| 1379 | u64 attached_device_name; | ||
| 1380 | u8 programmed_min_physical_link_rate; | ||
| 1381 | u8 programmed_max_physical_link_rate; | ||
| 1382 | u8 reserved_3[6]; | ||
| 1383 | }; | ||
| 1384 | |||
| 1385 | /* phy control reply structure */ | ||
| 1386 | struct phy_control_reply{ | ||
| 1387 | u8 smp_frame_type; /* 0x41 */ | ||
| 1388 | u8 function; /* 0x11 */ | ||
| 1389 | u8 function_result; | ||
| 1390 | u8 response_length; | ||
| 1391 | }; | ||
| 1392 | |||
| 1393 | #define SMP_PHY_CONTROL_LINK_RESET (0x01) | ||
| 1394 | #define SMP_PHY_CONTROL_HARD_RESET (0x02) | ||
| 1395 | #define SMP_PHY_CONTROL_DISABLE (0x03) | ||
| 1396 | |||
| 1397 | /** | ||
| 1398 | * _transport_expander_phy_control - expander phy control | ||
| 1399 | * @ioc: per adapter object | ||
| 1400 | * @phy: The sas phy object | ||
| 1401 | * | ||
| 1402 | * Returns 0 for success, non-zero for failure. | ||
| 1403 | * | ||
| 1404 | */ | ||
| 1405 | static int | ||
| 1406 | _transport_expander_phy_control(struct MPT2SAS_ADAPTER *ioc, | ||
| 1407 | struct sas_phy *phy, u8 phy_operation) | ||
| 1408 | { | ||
| 1409 | Mpi2SmpPassthroughRequest_t *mpi_request; | ||
| 1410 | Mpi2SmpPassthroughReply_t *mpi_reply; | ||
| 1411 | struct phy_control_request *phy_control_request; | ||
| 1412 | struct phy_control_reply *phy_control_reply; | ||
| 1413 | int rc; | ||
| 1414 | u16 smid; | ||
| 1415 | u32 ioc_state; | ||
| 1416 | unsigned long timeleft; | ||
| 1417 | void *psge; | ||
| 1418 | u32 sgl_flags; | ||
| 1419 | u8 issue_reset = 0; | ||
| 1420 | void *data_out = NULL; | ||
| 1421 | dma_addr_t data_out_dma; | ||
| 1422 | u32 sz; | ||
| 1423 | u16 wait_state_count; | ||
| 1424 | |||
| 1425 | if (ioc->shost_recovery) { | ||
| 1426 | printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n", | ||
| 1427 | __func__, ioc->name); | ||
| 1428 | return -EFAULT; | ||
| 1429 | } | ||
| 1430 | |||
| 1431 | mutex_lock(&ioc->transport_cmds.mutex); | ||
| 1432 | |||
| 1433 | if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) { | ||
| 1434 | printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n", | ||
| 1435 | ioc->name, __func__); | ||
| 1436 | rc = -EAGAIN; | ||
| 1437 | goto out; | ||
| 1438 | } | ||
| 1439 | ioc->transport_cmds.status = MPT2_CMD_PENDING; | ||
| 1440 | |||
| 1441 | wait_state_count = 0; | ||
| 1442 | ioc_state = mpt2sas_base_get_iocstate(ioc, 1); | ||
| 1443 | while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { | ||
| 1444 | if (wait_state_count++ == 10) { | ||
| 1445 | printk(MPT2SAS_ERR_FMT | ||
| 1446 | "%s: failed due to ioc not operational\n", | ||
| 1447 | ioc->name, __func__); | ||
| 1448 | rc = -EFAULT; | ||
| 1449 | goto out; | ||
| 1450 | } | ||
| 1451 | ssleep(1); | ||
| 1452 | ioc_state = mpt2sas_base_get_iocstate(ioc, 1); | ||
| 1453 | printk(MPT2SAS_INFO_FMT "%s: waiting for " | ||
| 1454 | "operational state(count=%d)\n", ioc->name, | ||
| 1455 | __func__, wait_state_count); | ||
| 1456 | } | ||
| 1457 | if (wait_state_count) | ||
| 1458 | printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n", | ||
| 1459 | ioc->name, __func__); | ||
| 1460 | |||
| 1461 | smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx); | ||
| 1462 | if (!smid) { | ||
| 1463 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", | ||
| 1464 | ioc->name, __func__); | ||
| 1465 | rc = -EAGAIN; | ||
| 1466 | goto out; | ||
| 1467 | } | ||
| 1468 | |||
| 1469 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); | ||
| 1470 | ioc->transport_cmds.smid = smid; | ||
| 1471 | |||
| 1472 | sz = sizeof(struct phy_control_request) + | ||
| 1473 | sizeof(struct phy_control_reply); | ||
| 1474 | data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma); | ||
| 1475 | if (!data_out) { | ||
| 1476 | printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, | ||
| 1477 | __LINE__, __func__); | ||
| 1478 | rc = -ENOMEM; | ||
| 1479 | mpt2sas_base_free_smid(ioc, smid); | ||
| 1480 | goto out; | ||
| 1481 | } | ||
| 1482 | |||
| 1483 | rc = -EINVAL; | ||
| 1484 | memset(data_out, 0, sz); | ||
| 1485 | phy_control_request = data_out; | ||
| 1486 | phy_control_request->smp_frame_type = 0x40; | ||
| 1487 | phy_control_request->function = 0x91; | ||
| 1488 | phy_control_request->request_length = 9; | ||
| 1489 | phy_control_request->allocated_response_length = 0; | ||
| 1490 | phy_control_request->phy_identifier = phy->number; | ||
| 1491 | phy_control_request->phy_operation = phy_operation; | ||
| 1492 | phy_control_request->programmed_min_physical_link_rate = | ||
| 1493 | phy->minimum_linkrate << 4; | ||
| 1494 | phy_control_request->programmed_max_physical_link_rate = | ||
| 1495 | phy->maximum_linkrate << 4; | ||
| 1496 | |||
| 1497 | memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t)); | ||
| 1498 | mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH; | ||
| 1499 | mpi_request->PhysicalPort = 0xFF; | ||
| 1500 | mpi_request->VF_ID = 0; /* TODO */ | ||
| 1501 | mpi_request->VP_ID = 0; | ||
| 1502 | mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address); | ||
| 1503 | mpi_request->RequestDataLength = | ||
| 1504 | cpu_to_le16(sizeof(struct phy_error_log_request)); | ||
| 1505 | psge = &mpi_request->SGL; | ||
| 1506 | |||
| 1507 | /* WRITE sgel first */ | ||
| 1508 | sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT | | ||
| 1509 | MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC); | ||
| 1510 | sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; | ||
| 1511 | ioc->base_add_sg_single(psge, sgl_flags | | ||
| 1512 | sizeof(struct phy_control_request), data_out_dma); | ||
| 1513 | |||
| 1514 | /* incr sgel */ | ||
| 1515 | psge += ioc->sge_size; | ||
| 1516 | |||
| 1517 | /* READ sgel last */ | ||
| 1518 | sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT | | ||
| 1519 | MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER | | ||
| 1520 | MPI2_SGE_FLAGS_END_OF_LIST); | ||
| 1521 | sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; | ||
| 1522 | ioc->base_add_sg_single(psge, sgl_flags | | ||
| 1523 | sizeof(struct phy_control_reply), data_out_dma + | ||
| 1524 | sizeof(struct phy_control_request)); | ||
| 1525 | |||
| 1526 | dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_control - " | ||
| 1527 | "send to sas_addr(0x%016llx), phy(%d), opcode(%d)\n", ioc->name, | ||
| 1528 | (unsigned long long)phy->identify.sas_address, phy->number, | ||
| 1529 | phy_operation)); | ||
| 1530 | |||
| 1531 | init_completion(&ioc->transport_cmds.done); | ||
| 1532 | mpt2sas_base_put_smid_default(ioc, smid); | ||
| 1533 | timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done, | ||
| 1534 | 10*HZ); | ||
| 1535 | |||
| 1536 | if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) { | ||
| 1537 | printk(MPT2SAS_ERR_FMT "%s: timeout\n", | ||
| 1538 | ioc->name, __func__); | ||
| 1539 | _debug_dump_mf(mpi_request, | ||
| 1540 | sizeof(Mpi2SmpPassthroughRequest_t)/4); | ||
| 1541 | if (!(ioc->transport_cmds.status & MPT2_CMD_RESET)) | ||
| 1542 | issue_reset = 1; | ||
| 1543 | goto issue_host_reset; | ||
| 1544 | } | ||
| 1545 | |||
| 1546 | dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_control - " | ||
| 1547 | "complete\n", ioc->name)); | ||
| 1548 | |||
| 1549 | if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) { | ||
| 1550 | |||
| 1551 | mpi_reply = ioc->transport_cmds.reply; | ||
| 1552 | |||
| 1553 | dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 1554 | "phy_control - reply data transfer size(%d)\n", | ||
| 1555 | ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength))); | ||
| 1556 | |||
| 1557 | if (le16_to_cpu(mpi_reply->ResponseDataLength) != | ||
| 1558 | sizeof(struct phy_control_reply)) | ||
| 1559 | goto out; | ||
| 1560 | |||
| 1561 | phy_control_reply = data_out + | ||
| 1562 | sizeof(struct phy_control_request); | ||
| 1563 | |||
| 1564 | dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 1565 | "phy_control - function_result(%d)\n", | ||
| 1566 | ioc->name, phy_control_reply->function_result)); | ||
| 1567 | |||
| 1568 | rc = 0; | ||
| 1569 | } else | ||
| 1570 | dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 1571 | "phy_control - no reply\n", ioc->name)); | ||
| 1572 | |||
| 1573 | issue_host_reset: | ||
| 1574 | if (issue_reset) | ||
| 1575 | mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, | ||
| 1576 | FORCE_BIG_HAMMER); | ||
| 1577 | out: | ||
| 1578 | ioc->transport_cmds.status = MPT2_CMD_NOT_USED; | ||
| 1579 | if (data_out) | ||
| 1580 | pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma); | ||
| 1581 | |||
| 1582 | mutex_unlock(&ioc->transport_cmds.mutex); | ||
| 1583 | return rc; | ||
| 1584 | } | ||
| 1585 | |||
| 1586 | /** | ||
| 1587 | * _transport_phy_reset - | ||
| 1588 | * @phy: The sas phy object | ||
| 1589 | * @hard_reset: | ||
| 1590 | * | ||
| 1591 | * Returns 0 for success, non-zero for failure. | ||
| 1592 | */ | ||
| 1593 | static int | ||
| 1594 | _transport_phy_reset(struct sas_phy *phy, int hard_reset) | ||
| 1595 | { | ||
| 1596 | struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy); | ||
| 1597 | Mpi2SasIoUnitControlReply_t mpi_reply; | ||
| 1598 | Mpi2SasIoUnitControlRequest_t mpi_request; | ||
| 1599 | unsigned long flags; | ||
| 1600 | |||
| 1601 | spin_lock_irqsave(&ioc->sas_node_lock, flags); | ||
| 1602 | if (_transport_sas_node_find_by_sas_address(ioc, | ||
| 1603 | phy->identify.sas_address) == NULL) { | ||
| 1604 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | ||
| 1605 | return -EINVAL; | ||
| 1606 | } | ||
| 1607 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | ||
| 1608 | |||
| 1609 | /* handle expander phys */ | ||
| 1610 | if (phy->identify.sas_address != ioc->sas_hba.sas_address) | ||
| 1611 | return _transport_expander_phy_control(ioc, phy, | ||
| 1612 | (hard_reset == 1) ? SMP_PHY_CONTROL_HARD_RESET : | ||
| 1613 | SMP_PHY_CONTROL_LINK_RESET); | ||
| 1614 | |||
| 1615 | /* handle hba phys */ | ||
| 1616 | memset(&mpi_request, 0, sizeof(Mpi2SasIoUnitControlReply_t)); | ||
| 1617 | mpi_request.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL; | ||
| 1618 | mpi_request.Operation = hard_reset ? | ||
| 1619 | MPI2_SAS_OP_PHY_HARD_RESET : MPI2_SAS_OP_PHY_LINK_RESET; | ||
| 1620 | mpi_request.PhyNum = phy->number; | ||
| 1621 | |||
| 1622 | if ((mpt2sas_base_sas_iounit_control(ioc, &mpi_reply, &mpi_request))) { | ||
| 1623 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 1624 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 1625 | return -ENXIO; | ||
| 1626 | } | ||
| 1627 | |||
| 1628 | if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) | ||
| 1629 | printk(MPT2SAS_INFO_FMT "phy(%d), ioc_status" | ||
| 1630 | "(0x%04x), loginfo(0x%08x)\n", ioc->name, | ||
| 1631 | phy->number, le16_to_cpu(mpi_reply.IOCStatus), | ||
| 1632 | le32_to_cpu(mpi_reply.IOCLogInfo)); | ||
| 1633 | |||
| 1634 | return 0; | ||
| 1635 | } | ||
| 1636 | |||
| 1637 | /** | ||
| 1638 | * _transport_phy_enable - enable/disable phys | ||
| 1639 | * @phy: The sas phy object | ||
| 1640 | * @enable: enable phy when true | ||
| 1641 | * | ||
| 1642 | * Only support sas_host direct attached phys. | ||
| 1643 | * Returns 0 for success, non-zero for failure. | ||
| 1644 | */ | ||
| 1645 | static int | ||
| 1646 | _transport_phy_enable(struct sas_phy *phy, int enable) | ||
| 1647 | { | ||
| 1648 | struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy); | ||
| 1649 | Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL; | ||
| 1650 | Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL; | ||
| 1651 | Mpi2ConfigReply_t mpi_reply; | ||
| 1652 | u16 ioc_status; | ||
| 1653 | u16 sz; | ||
| 1654 | int rc = 0; | ||
| 1655 | unsigned long flags; | ||
| 1656 | int i, discovery_active; | ||
| 1657 | |||
| 1658 | spin_lock_irqsave(&ioc->sas_node_lock, flags); | ||
| 1659 | if (_transport_sas_node_find_by_sas_address(ioc, | ||
| 1660 | phy->identify.sas_address) == NULL) { | ||
| 1661 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | ||
| 1662 | return -EINVAL; | ||
| 1663 | } | ||
| 1664 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | ||
| 1665 | |||
| 1666 | /* handle expander phys */ | ||
| 1667 | if (phy->identify.sas_address != ioc->sas_hba.sas_address) | ||
| 1668 | return _transport_expander_phy_control(ioc, phy, | ||
| 1669 | (enable == 1) ? SMP_PHY_CONTROL_LINK_RESET : | ||
| 1670 | SMP_PHY_CONTROL_DISABLE); | ||
| 1671 | |||
| 1672 | /* handle hba phys */ | ||
| 1673 | |||
| 1674 | /* read sas_iounit page 0 */ | ||
| 1675 | sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys * | ||
| 1676 | sizeof(Mpi2SasIOUnit0PhyData_t)); | ||
| 1677 | sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL); | ||
| 1678 | if (!sas_iounit_pg0) { | ||
| 1679 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 1680 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 1681 | rc = -ENOMEM; | ||
| 1682 | goto out; | ||
| 1683 | } | ||
| 1684 | if ((mpt2sas_config_get_sas_iounit_pg0(ioc, &mpi_reply, | ||
| 1685 | sas_iounit_pg0, sz))) { | ||
| 1686 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 1687 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 1688 | rc = -ENXIO; | ||
| 1689 | goto out; | ||
| 1690 | } | ||
| 1691 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
| 1692 | MPI2_IOCSTATUS_MASK; | ||
| 1693 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { | ||
| 1694 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 1695 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 1696 | rc = -EIO; | ||
| 1697 | goto out; | ||
| 1698 | } | ||
| 1699 | |||
| 1700 | /* unable to enable/disable phys when when discovery is active */ | ||
| 1701 | for (i = 0, discovery_active = 0; i < ioc->sas_hba.num_phys ; i++) { | ||
| 1702 | if (sas_iounit_pg0->PhyData[i].PortFlags & | ||
| 1703 | MPI2_SASIOUNIT0_PORTFLAGS_DISCOVERY_IN_PROGRESS) { | ||
| 1704 | printk(MPT2SAS_ERR_FMT "discovery is active on " | ||
| 1705 | "port = %d, phy = %d: unable to enable/disable " | ||
| 1706 | "phys, try again later!\n", ioc->name, | ||
| 1707 | sas_iounit_pg0->PhyData[i].Port, i); | ||
| 1708 | discovery_active = 1; | ||
| 1709 | } | ||
| 1710 | } | ||
| 1711 | |||
| 1712 | if (discovery_active) { | ||
| 1713 | rc = -EAGAIN; | ||
| 1714 | goto out; | ||
| 1715 | } | ||
| 1716 | |||
| 1717 | /* read sas_iounit page 1 */ | ||
| 1718 | sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys * | ||
| 1719 | sizeof(Mpi2SasIOUnit1PhyData_t)); | ||
| 1720 | sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL); | ||
| 1721 | if (!sas_iounit_pg1) { | ||
| 1722 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 1723 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 1724 | rc = -ENOMEM; | ||
| 1725 | goto out; | ||
| 1726 | } | ||
| 1727 | if ((mpt2sas_config_get_sas_iounit_pg1(ioc, &mpi_reply, | ||
| 1728 | sas_iounit_pg1, sz))) { | ||
| 1729 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 1730 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 1731 | rc = -ENXIO; | ||
| 1732 | goto out; | ||
| 1733 | } | ||
| 1734 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
| 1735 | MPI2_IOCSTATUS_MASK; | ||
| 1736 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { | ||
| 1737 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 1738 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 1739 | rc = -EIO; | ||
| 1740 | goto out; | ||
| 1741 | } | ||
| 1742 | /* copy Port/PortFlags/PhyFlags from page 0 */ | ||
| 1743 | for (i = 0; i < ioc->sas_hba.num_phys ; i++) { | ||
| 1744 | sas_iounit_pg1->PhyData[i].Port = | ||
| 1745 | sas_iounit_pg0->PhyData[i].Port; | ||
| 1746 | sas_iounit_pg1->PhyData[i].PortFlags = | ||
| 1747 | (sas_iounit_pg0->PhyData[i].PortFlags & | ||
| 1748 | MPI2_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG); | ||
| 1749 | sas_iounit_pg1->PhyData[i].PhyFlags = | ||
| 1750 | (sas_iounit_pg0->PhyData[i].PhyFlags & | ||
| 1751 | (MPI2_SASIOUNIT0_PHYFLAGS_ZONING_ENABLED + | ||
| 1752 | MPI2_SASIOUNIT0_PHYFLAGS_PHY_DISABLED)); | ||
| 1753 | } | ||
| 1754 | if (enable) | ||
| 1755 | sas_iounit_pg1->PhyData[phy->number].PhyFlags | ||
| 1756 | &= ~MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE; | ||
| 1757 | else | ||
| 1758 | sas_iounit_pg1->PhyData[phy->number].PhyFlags | ||
| 1759 | |= MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE; | ||
| 1760 | |||
| 1761 | mpt2sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1, sz); | ||
| 1762 | |||
| 1763 | /* link reset */ | ||
| 1764 | if (enable) | ||
| 1765 | _transport_phy_reset(phy, 0); | ||
| 1766 | |||
| 1767 | out: | ||
| 1768 | kfree(sas_iounit_pg1); | ||
| 1769 | kfree(sas_iounit_pg0); | ||
| 1770 | return rc; | ||
| 1771 | } | ||
| 1772 | |||
| 1773 | /** | ||
| 1774 | * _transport_phy_speed - set phy min/max link rates | ||
| 1775 | * @phy: The sas phy object | ||
| 1776 | * @rates: rates defined in sas_phy_linkrates | ||
| 1777 | * | ||
| 1778 | * Only support sas_host direct attached phys. | ||
| 1779 | * Returns 0 for success, non-zero for failure. | ||
| 1780 | */ | ||
| 1781 | static int | ||
| 1782 | _transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates) | ||
| 1783 | { | ||
| 1784 | struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy); | ||
| 1785 | Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL; | ||
| 1786 | Mpi2SasPhyPage0_t phy_pg0; | ||
| 1787 | Mpi2ConfigReply_t mpi_reply; | ||
| 1788 | u16 ioc_status; | ||
| 1789 | u16 sz; | ||
| 1790 | int i; | ||
| 1791 | int rc = 0; | ||
| 1792 | unsigned long flags; | ||
| 1793 | |||
| 1794 | spin_lock_irqsave(&ioc->sas_node_lock, flags); | ||
| 1795 | if (_transport_sas_node_find_by_sas_address(ioc, | ||
| 1796 | phy->identify.sas_address) == NULL) { | ||
| 1797 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | ||
| 1798 | return -EINVAL; | ||
| 1799 | } | ||
| 1800 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | ||
| 1801 | |||
| 1802 | if (!rates->minimum_linkrate) | ||
| 1803 | rates->minimum_linkrate = phy->minimum_linkrate; | ||
| 1804 | else if (rates->minimum_linkrate < phy->minimum_linkrate_hw) | ||
| 1805 | rates->minimum_linkrate = phy->minimum_linkrate_hw; | ||
| 1806 | |||
| 1807 | if (!rates->maximum_linkrate) | ||
| 1808 | rates->maximum_linkrate = phy->maximum_linkrate; | ||
| 1809 | else if (rates->maximum_linkrate > phy->maximum_linkrate_hw) | ||
| 1810 | rates->maximum_linkrate = phy->maximum_linkrate_hw; | ||
| 1811 | |||
| 1812 | /* handle expander phys */ | ||
| 1813 | if (phy->identify.sas_address != ioc->sas_hba.sas_address) { | ||
| 1814 | phy->minimum_linkrate = rates->minimum_linkrate; | ||
| 1815 | phy->maximum_linkrate = rates->maximum_linkrate; | ||
| 1816 | return _transport_expander_phy_control(ioc, phy, | ||
| 1817 | SMP_PHY_CONTROL_LINK_RESET); | ||
| 1818 | } | ||
| 1819 | |||
| 1820 | /* handle hba phys */ | ||
| 1821 | |||
| 1822 | /* sas_iounit page 1 */ | ||
| 1823 | sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys * | ||
| 1824 | sizeof(Mpi2SasIOUnit1PhyData_t)); | ||
| 1825 | sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL); | ||
| 1826 | if (!sas_iounit_pg1) { | ||
| 1827 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 1828 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 1829 | rc = -ENOMEM; | ||
| 1830 | goto out; | ||
| 1831 | } | ||
| 1832 | if ((mpt2sas_config_get_sas_iounit_pg1(ioc, &mpi_reply, | ||
| 1833 | sas_iounit_pg1, sz))) { | ||
| 1834 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 1835 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 1836 | rc = -ENXIO; | ||
| 1837 | goto out; | ||
| 1838 | } | ||
| 1839 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
| 1840 | MPI2_IOCSTATUS_MASK; | ||
| 1841 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { | ||
| 1842 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 1843 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 1844 | rc = -EIO; | ||
| 1845 | goto out; | ||
| 1846 | } | ||
| 1847 | |||
| 1848 | for (i = 0; i < ioc->sas_hba.num_phys; i++) { | ||
| 1849 | if (phy->number != i) { | ||
| 1850 | sas_iounit_pg1->PhyData[i].MaxMinLinkRate = | ||
| 1851 | (ioc->sas_hba.phy[i].phy->minimum_linkrate + | ||
| 1852 | (ioc->sas_hba.phy[i].phy->maximum_linkrate << 4)); | ||
| 1853 | } else { | ||
| 1854 | sas_iounit_pg1->PhyData[i].MaxMinLinkRate = | ||
| 1855 | (rates->minimum_linkrate + | ||
| 1856 | (rates->maximum_linkrate << 4)); | ||
| 1857 | } | ||
| 1858 | } | ||
| 1859 | |||
| 1860 | if (mpt2sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1, | ||
| 1861 | sz)) { | ||
| 1862 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 1863 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 1864 | rc = -ENXIO; | ||
| 1865 | goto out; | ||
| 1866 | } | ||
| 1867 | |||
| 1868 | /* link reset */ | ||
| 1869 | _transport_phy_reset(phy, 0); | ||
| 1870 | |||
| 1871 | /* read phy page 0, then update the rates in the sas transport phy */ | ||
| 1872 | if (!mpt2sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0, | ||
| 1873 | phy->number)) { | ||
| 1874 | phy->minimum_linkrate = _transport_convert_phy_link_rate( | ||
| 1875 | phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK); | ||
| 1876 | phy->maximum_linkrate = _transport_convert_phy_link_rate( | ||
| 1877 | phy_pg0.ProgrammedLinkRate >> 4); | ||
| 1878 | phy->negotiated_linkrate = _transport_convert_phy_link_rate( | ||
| 1879 | phy_pg0.NegotiatedLinkRate & | ||
| 1880 | MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL); | ||
| 1881 | } | ||
| 1882 | |||
| 1883 | out: | ||
| 1884 | kfree(sas_iounit_pg1); | ||
| 1885 | return rc; | ||
| 1886 | } | ||
| 1887 | |||
| 1888 | |||
| 1889 | /** | ||
| 1890 | * _transport_smp_handler - transport portal for smp passthru | ||
| 1891 | * @shost: shost object | ||
| 1892 | * @rphy: sas transport rphy object | ||
| 1893 | * @req: | ||
| 1894 | * | ||
| 1895 | * This used primarily for smp_utils. | ||
| 1896 | * Example: | ||
| 1897 | * smp_rep_general /sys/class/bsg/expander-5:0 | ||
| 1898 | */ | ||
| 1899 | static int | ||
| 1900 | _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, | ||
| 1901 | struct request *req) | ||
| 1902 | { | ||
| 1903 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 1904 | Mpi2SmpPassthroughRequest_t *mpi_request; | ||
| 1905 | Mpi2SmpPassthroughReply_t *mpi_reply; | ||
| 1906 | int rc; | ||
| 1907 | u16 smid; | ||
| 1908 | u32 ioc_state; | ||
| 1909 | unsigned long timeleft; | ||
| 1910 | void *psge; | ||
| 1911 | u32 sgl_flags; | ||
| 1912 | u8 issue_reset = 0; | ||
| 1913 | dma_addr_t dma_addr_in = 0; | ||
| 1914 | dma_addr_t dma_addr_out = 0; | ||
| 1915 | dma_addr_t pci_dma_in = 0; | ||
| 1916 | dma_addr_t pci_dma_out = 0; | ||
| 1917 | void *pci_addr_in = NULL; | ||
| 1918 | void *pci_addr_out = NULL; | ||
| 1919 | u16 wait_state_count; | ||
| 1920 | struct request *rsp = req->next_rq; | ||
| 1921 | struct bio_vec bvec; | ||
| 1922 | struct bvec_iter iter; | ||
| 1923 | |||
| 1924 | if (!rsp) { | ||
| 1925 | printk(MPT2SAS_ERR_FMT "%s: the smp response space is " | ||
| 1926 | "missing\n", ioc->name, __func__); | ||
| 1927 | return -EINVAL; | ||
| 1928 | } | ||
| 1929 | if (ioc->shost_recovery || ioc->pci_error_recovery) { | ||
| 1930 | printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n", | ||
| 1931 | __func__, ioc->name); | ||
| 1932 | return -EFAULT; | ||
| 1933 | } | ||
| 1934 | |||
| 1935 | rc = mutex_lock_interruptible(&ioc->transport_cmds.mutex); | ||
| 1936 | if (rc) | ||
| 1937 | return rc; | ||
| 1938 | |||
| 1939 | if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) { | ||
| 1940 | printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n", ioc->name, | ||
| 1941 | __func__); | ||
| 1942 | rc = -EAGAIN; | ||
| 1943 | goto out; | ||
| 1944 | } | ||
| 1945 | ioc->transport_cmds.status = MPT2_CMD_PENDING; | ||
| 1946 | |||
| 1947 | /* Check if the request is split across multiple segments */ | ||
| 1948 | if (bio_multiple_segments(req->bio)) { | ||
| 1949 | u32 offset = 0; | ||
| 1950 | |||
| 1951 | /* Allocate memory and copy the request */ | ||
| 1952 | pci_addr_out = pci_alloc_consistent(ioc->pdev, | ||
| 1953 | blk_rq_bytes(req), &pci_dma_out); | ||
| 1954 | if (!pci_addr_out) { | ||
| 1955 | printk(MPT2SAS_INFO_FMT "%s(): PCI Addr out = NULL\n", | ||
| 1956 | ioc->name, __func__); | ||
| 1957 | rc = -ENOMEM; | ||
| 1958 | goto out; | ||
| 1959 | } | ||
| 1960 | |||
| 1961 | bio_for_each_segment(bvec, req->bio, iter) { | ||
| 1962 | memcpy(pci_addr_out + offset, | ||
| 1963 | page_address(bvec.bv_page) + bvec.bv_offset, | ||
| 1964 | bvec.bv_len); | ||
| 1965 | offset += bvec.bv_len; | ||
| 1966 | } | ||
| 1967 | } else { | ||
| 1968 | dma_addr_out = pci_map_single(ioc->pdev, bio_data(req->bio), | ||
| 1969 | blk_rq_bytes(req), PCI_DMA_BIDIRECTIONAL); | ||
| 1970 | if (!dma_addr_out) { | ||
| 1971 | printk(MPT2SAS_INFO_FMT "%s(): DMA Addr out = NULL\n", | ||
| 1972 | ioc->name, __func__); | ||
| 1973 | rc = -ENOMEM; | ||
| 1974 | goto free_pci; | ||
| 1975 | } | ||
| 1976 | } | ||
| 1977 | |||
| 1978 | /* Check if the response needs to be populated across | ||
| 1979 | * multiple segments */ | ||
| 1980 | if (bio_multiple_segments(rsp->bio)) { | ||
| 1981 | pci_addr_in = pci_alloc_consistent(ioc->pdev, blk_rq_bytes(rsp), | ||
| 1982 | &pci_dma_in); | ||
| 1983 | if (!pci_addr_in) { | ||
| 1984 | printk(MPT2SAS_INFO_FMT "%s(): PCI Addr in = NULL\n", | ||
| 1985 | ioc->name, __func__); | ||
| 1986 | rc = -ENOMEM; | ||
| 1987 | goto unmap; | ||
| 1988 | } | ||
| 1989 | } else { | ||
| 1990 | dma_addr_in = pci_map_single(ioc->pdev, bio_data(rsp->bio), | ||
| 1991 | blk_rq_bytes(rsp), PCI_DMA_BIDIRECTIONAL); | ||
| 1992 | if (!dma_addr_in) { | ||
| 1993 | printk(MPT2SAS_INFO_FMT "%s(): DMA Addr in = NULL\n", | ||
| 1994 | ioc->name, __func__); | ||
| 1995 | rc = -ENOMEM; | ||
| 1996 | goto unmap; | ||
| 1997 | } | ||
| 1998 | } | ||
| 1999 | |||
| 2000 | wait_state_count = 0; | ||
| 2001 | ioc_state = mpt2sas_base_get_iocstate(ioc, 1); | ||
| 2002 | while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { | ||
| 2003 | if (wait_state_count++ == 10) { | ||
| 2004 | printk(MPT2SAS_ERR_FMT | ||
| 2005 | "%s: failed due to ioc not operational\n", | ||
| 2006 | ioc->name, __func__); | ||
| 2007 | rc = -EFAULT; | ||
| 2008 | goto unmap; | ||
| 2009 | } | ||
| 2010 | ssleep(1); | ||
| 2011 | ioc_state = mpt2sas_base_get_iocstate(ioc, 1); | ||
| 2012 | printk(MPT2SAS_INFO_FMT "%s: waiting for " | ||
| 2013 | "operational state(count=%d)\n", ioc->name, | ||
| 2014 | __func__, wait_state_count); | ||
| 2015 | } | ||
| 2016 | if (wait_state_count) | ||
| 2017 | printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n", | ||
| 2018 | ioc->name, __func__); | ||
| 2019 | |||
| 2020 | smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx); | ||
| 2021 | if (!smid) { | ||
| 2022 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", | ||
| 2023 | ioc->name, __func__); | ||
| 2024 | rc = -EAGAIN; | ||
| 2025 | goto unmap; | ||
| 2026 | } | ||
| 2027 | |||
| 2028 | rc = 0; | ||
| 2029 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); | ||
| 2030 | ioc->transport_cmds.smid = smid; | ||
| 2031 | |||
| 2032 | memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t)); | ||
| 2033 | mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH; | ||
| 2034 | mpi_request->PhysicalPort = 0xFF; | ||
| 2035 | mpi_request->VF_ID = 0; /* TODO */ | ||
| 2036 | mpi_request->VP_ID = 0; | ||
| 2037 | mpi_request->SASAddress = (rphy) ? | ||
| 2038 | cpu_to_le64(rphy->identify.sas_address) : | ||
| 2039 | cpu_to_le64(ioc->sas_hba.sas_address); | ||
| 2040 | mpi_request->RequestDataLength = cpu_to_le16(blk_rq_bytes(req) - 4); | ||
| 2041 | psge = &mpi_request->SGL; | ||
| 2042 | |||
| 2043 | /* WRITE sgel first */ | ||
| 2044 | sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT | | ||
| 2045 | MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC); | ||
| 2046 | sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; | ||
| 2047 | if (bio_multiple_segments(req->bio)) { | ||
| 2048 | ioc->base_add_sg_single(psge, sgl_flags | | ||
| 2049 | (blk_rq_bytes(req) - 4), pci_dma_out); | ||
| 2050 | } else { | ||
| 2051 | ioc->base_add_sg_single(psge, sgl_flags | | ||
| 2052 | (blk_rq_bytes(req) - 4), dma_addr_out); | ||
| 2053 | } | ||
| 2054 | |||
| 2055 | /* incr sgel */ | ||
| 2056 | psge += ioc->sge_size; | ||
| 2057 | |||
| 2058 | /* READ sgel last */ | ||
| 2059 | sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT | | ||
| 2060 | MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER | | ||
| 2061 | MPI2_SGE_FLAGS_END_OF_LIST); | ||
| 2062 | sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; | ||
| 2063 | if (bio_multiple_segments(rsp->bio)) { | ||
| 2064 | ioc->base_add_sg_single(psge, sgl_flags | | ||
| 2065 | (blk_rq_bytes(rsp) + 4), pci_dma_in); | ||
| 2066 | } else { | ||
| 2067 | ioc->base_add_sg_single(psge, sgl_flags | | ||
| 2068 | (blk_rq_bytes(rsp) + 4), dma_addr_in); | ||
| 2069 | } | ||
| 2070 | |||
| 2071 | dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "%s - " | ||
| 2072 | "sending smp request\n", ioc->name, __func__)); | ||
| 2073 | |||
| 2074 | init_completion(&ioc->transport_cmds.done); | ||
| 2075 | mpt2sas_base_put_smid_default(ioc, smid); | ||
| 2076 | timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done, | ||
| 2077 | 10*HZ); | ||
| 2078 | |||
| 2079 | if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) { | ||
| 2080 | printk(MPT2SAS_ERR_FMT "%s : timeout\n", | ||
| 2081 | __func__, ioc->name); | ||
| 2082 | _debug_dump_mf(mpi_request, | ||
| 2083 | sizeof(Mpi2SmpPassthroughRequest_t)/4); | ||
| 2084 | if (!(ioc->transport_cmds.status & MPT2_CMD_RESET)) | ||
| 2085 | issue_reset = 1; | ||
| 2086 | goto issue_host_reset; | ||
| 2087 | } | ||
| 2088 | |||
| 2089 | dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "%s - " | ||
| 2090 | "complete\n", ioc->name, __func__)); | ||
| 2091 | |||
| 2092 | if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) { | ||
| 2093 | |||
| 2094 | mpi_reply = ioc->transport_cmds.reply; | ||
| 2095 | |||
| 2096 | dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 2097 | "%s - reply data transfer size(%d)\n", | ||
| 2098 | ioc->name, __func__, | ||
| 2099 | le16_to_cpu(mpi_reply->ResponseDataLength))); | ||
| 2100 | |||
| 2101 | memcpy(req->sense, mpi_reply, sizeof(*mpi_reply)); | ||
| 2102 | req->sense_len = sizeof(*mpi_reply); | ||
| 2103 | req->resid_len = 0; | ||
| 2104 | rsp->resid_len -= | ||
| 2105 | le16_to_cpu(mpi_reply->ResponseDataLength); | ||
| 2106 | /* check if the resp needs to be copied from the allocated | ||
| 2107 | * pci mem */ | ||
| 2108 | if (bio_multiple_segments(rsp->bio)) { | ||
| 2109 | u32 offset = 0; | ||
| 2110 | u32 bytes_to_copy = | ||
| 2111 | le16_to_cpu(mpi_reply->ResponseDataLength); | ||
| 2112 | bio_for_each_segment(bvec, rsp->bio, iter) { | ||
| 2113 | if (bytes_to_copy <= bvec.bv_len) { | ||
| 2114 | memcpy(page_address(bvec.bv_page) + | ||
| 2115 | bvec.bv_offset, pci_addr_in + | ||
| 2116 | offset, bytes_to_copy); | ||
| 2117 | break; | ||
| 2118 | } else { | ||
| 2119 | memcpy(page_address(bvec.bv_page) + | ||
| 2120 | bvec.bv_offset, pci_addr_in + | ||
| 2121 | offset, bvec.bv_len); | ||
| 2122 | bytes_to_copy -= bvec.bv_len; | ||
| 2123 | } | ||
| 2124 | offset += bvec.bv_len; | ||
| 2125 | } | ||
| 2126 | } | ||
| 2127 | } else { | ||
| 2128 | dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 2129 | "%s - no reply\n", ioc->name, __func__)); | ||
| 2130 | rc = -ENXIO; | ||
| 2131 | } | ||
| 2132 | |||
| 2133 | issue_host_reset: | ||
| 2134 | if (issue_reset) { | ||
| 2135 | mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, | ||
| 2136 | FORCE_BIG_HAMMER); | ||
| 2137 | rc = -ETIMEDOUT; | ||
| 2138 | } | ||
| 2139 | |||
| 2140 | unmap: | ||
| 2141 | if (dma_addr_out) | ||
| 2142 | pci_unmap_single(ioc->pdev, dma_addr_out, blk_rq_bytes(req), | ||
| 2143 | PCI_DMA_BIDIRECTIONAL); | ||
| 2144 | if (dma_addr_in) | ||
| 2145 | pci_unmap_single(ioc->pdev, dma_addr_in, blk_rq_bytes(rsp), | ||
| 2146 | PCI_DMA_BIDIRECTIONAL); | ||
| 2147 | |||
| 2148 | free_pci: | ||
| 2149 | if (pci_addr_out) | ||
| 2150 | pci_free_consistent(ioc->pdev, blk_rq_bytes(req), pci_addr_out, | ||
| 2151 | pci_dma_out); | ||
| 2152 | |||
| 2153 | if (pci_addr_in) | ||
| 2154 | pci_free_consistent(ioc->pdev, blk_rq_bytes(rsp), pci_addr_in, | ||
| 2155 | pci_dma_in); | ||
| 2156 | |||
| 2157 | out: | ||
| 2158 | ioc->transport_cmds.status = MPT2_CMD_NOT_USED; | ||
| 2159 | mutex_unlock(&ioc->transport_cmds.mutex); | ||
| 2160 | return rc; | ||
| 2161 | } | ||
| 2162 | |||
| 2163 | struct sas_function_template mpt2sas_transport_functions = { | ||
| 2164 | .get_linkerrors = _transport_get_linkerrors, | ||
| 2165 | .get_enclosure_identifier = _transport_get_enclosure_identifier, | ||
| 2166 | .get_bay_identifier = _transport_get_bay_identifier, | ||
| 2167 | .phy_reset = _transport_phy_reset, | ||
| 2168 | .phy_enable = _transport_phy_enable, | ||
| 2169 | .set_phy_speed = _transport_phy_speed, | ||
| 2170 | .smp_handler = _transport_smp_handler, | ||
| 2171 | }; | ||
| 2172 | |||
| 2173 | struct scsi_transport_template *mpt2sas_transport_template; | ||
diff --git a/drivers/scsi/mpt3sas/Kconfig b/drivers/scsi/mpt3sas/Kconfig index 4d235dd741bf..29061467cc17 100644 --- a/drivers/scsi/mpt3sas/Kconfig +++ b/drivers/scsi/mpt3sas/Kconfig | |||
| @@ -41,15 +41,15 @@ | |||
| 41 | # USA. | 41 | # USA. |
| 42 | 42 | ||
| 43 | config SCSI_MPT3SAS | 43 | config SCSI_MPT3SAS |
| 44 | tristate "LSI MPT Fusion SAS 3.0 Device Driver" | 44 | tristate "LSI MPT Fusion SAS 3.0 & SAS 2.0 Device Driver" |
| 45 | depends on PCI && SCSI | 45 | depends on PCI && SCSI |
| 46 | select SCSI_SAS_ATTRS | 46 | select SCSI_SAS_ATTRS |
| 47 | select RAID_ATTRS | 47 | select RAID_ATTRS |
| 48 | ---help--- | 48 | ---help--- |
| 49 | This driver supports PCI-Express SAS 12Gb/s Host Adapters. | 49 | This driver supports PCI-Express SAS 12Gb/s Host Adapters. |
| 50 | 50 | ||
| 51 | config SCSI_MPT3SAS_MAX_SGE | 51 | config SCSI_MPT2SAS_MAX_SGE |
| 52 | int "LSI MPT Fusion Max number of SG Entries (16 - 256)" | 52 | int "LSI MPT Fusion SAS 2.0 Max number of SG Entries (16 - 256)" |
| 53 | depends on PCI && SCSI && SCSI_MPT3SAS | 53 | depends on PCI && SCSI && SCSI_MPT3SAS |
| 54 | default "128" | 54 | default "128" |
| 55 | range 16 256 | 55 | range 16 256 |
| @@ -60,8 +60,14 @@ config SCSI_MPT3SAS_MAX_SGE | |||
| 60 | can be 256. However, it may decreased down to 16. Decreasing this | 60 | can be 256. However, it may decreased down to 16. Decreasing this |
| 61 | parameter will reduce memory requirements on a per controller instance. | 61 | parameter will reduce memory requirements on a per controller instance. |
| 62 | 62 | ||
| 63 | config SCSI_MPT3SAS_LOGGING | 63 | config SCSI_MPT3SAS_MAX_SGE |
| 64 | bool "LSI MPT Fusion logging facility" | 64 | int "LSI MPT Fusion SAS 3.0 Max number of SG Entries (16 - 256)" |
| 65 | depends on PCI && SCSI && SCSI_MPT3SAS | 65 | depends on PCI && SCSI && SCSI_MPT3SAS |
| 66 | default "128" | ||
| 67 | range 16 256 | ||
| 66 | ---help--- | 68 | ---help--- |
| 67 | This turns on a logging facility. | 69 | This option allows you to specify the maximum number of scatter- |
| 70 | gather entries per I/O. The driver default is 128, which matches | ||
| 71 | MAX_PHYS_SEGMENTS in most kernels. However in SuSE kernels this | ||
| 72 | can be 256. However, it may decreased down to 16. Decreasing this | ||
| 73 | parameter will reduce memory requirements on a per controller instance. | ||
diff --git a/drivers/scsi/mpt3sas/Makefile b/drivers/scsi/mpt3sas/Makefile index efb0c4c2e310..b7643f596c1e 100644 --- a/drivers/scsi/mpt3sas/Makefile +++ b/drivers/scsi/mpt3sas/Makefile | |||
| @@ -5,4 +5,5 @@ mpt3sas-y += mpt3sas_base.o \ | |||
| 5 | mpt3sas_scsih.o \ | 5 | mpt3sas_scsih.o \ |
| 6 | mpt3sas_transport.o \ | 6 | mpt3sas_transport.o \ |
| 7 | mpt3sas_ctl.o \ | 7 | mpt3sas_ctl.o \ |
| 8 | mpt3sas_trigger_diag.o | 8 | mpt3sas_trigger_diag.o \ |
| 9 | mpt3sas_warpdrive.o | ||
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index d4f1dcdb8361..11393ebf1a68 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c | |||
| @@ -108,9 +108,12 @@ _scsih_set_fwfault_debug(const char *val, struct kernel_param *kp) | |||
| 108 | if (ret) | 108 | if (ret) |
| 109 | return ret; | 109 | return ret; |
| 110 | 110 | ||
| 111 | /* global ioc spinlock to protect controller list on list operations */ | ||
| 111 | pr_info("setting fwfault_debug(%d)\n", mpt3sas_fwfault_debug); | 112 | pr_info("setting fwfault_debug(%d)\n", mpt3sas_fwfault_debug); |
| 113 | spin_lock(&gioc_lock); | ||
| 112 | list_for_each_entry(ioc, &mpt3sas_ioc_list, list) | 114 | list_for_each_entry(ioc, &mpt3sas_ioc_list, list) |
| 113 | ioc->fwfault_debug = mpt3sas_fwfault_debug; | 115 | ioc->fwfault_debug = mpt3sas_fwfault_debug; |
| 116 | spin_unlock(&gioc_lock); | ||
| 114 | return 0; | 117 | return 0; |
| 115 | } | 118 | } |
| 116 | module_param_call(mpt3sas_fwfault_debug, _scsih_set_fwfault_debug, | 119 | module_param_call(mpt3sas_fwfault_debug, _scsih_set_fwfault_debug, |
| @@ -157,7 +160,7 @@ _base_fault_reset_work(struct work_struct *work) | |||
| 157 | 160 | ||
| 158 | 161 | ||
| 159 | spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); | 162 | spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); |
| 160 | if (ioc->shost_recovery) | 163 | if (ioc->shost_recovery || ioc->pci_error_recovery) |
| 161 | goto rearm_timer; | 164 | goto rearm_timer; |
| 162 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); | 165 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); |
| 163 | 166 | ||
| @@ -166,6 +169,20 @@ _base_fault_reset_work(struct work_struct *work) | |||
| 166 | pr_err(MPT3SAS_FMT "SAS host is non-operational !!!!\n", | 169 | pr_err(MPT3SAS_FMT "SAS host is non-operational !!!!\n", |
| 167 | ioc->name); | 170 | ioc->name); |
| 168 | 171 | ||
| 172 | /* It may be possible that EEH recovery can resolve some of | ||
| 173 | * pci bus failure issues rather removing the dead ioc function | ||
| 174 | * by considering controller is in a non-operational state. So | ||
| 175 | * here priority is given to the EEH recovery. If it doesn't | ||
| 176 | * not resolve this issue, mpt3sas driver will consider this | ||
| 177 | * controller to non-operational state and remove the dead ioc | ||
| 178 | * function. | ||
| 179 | */ | ||
| 180 | if (ioc->non_operational_loop++ < 5) { | ||
| 181 | spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, | ||
| 182 | flags); | ||
| 183 | goto rearm_timer; | ||
| 184 | } | ||
| 185 | |||
| 169 | /* | 186 | /* |
| 170 | * Call _scsih_flush_pending_cmds callback so that we flush all | 187 | * Call _scsih_flush_pending_cmds callback so that we flush all |
| 171 | * pending commands back to OS. This call is required to aovid | 188 | * pending commands back to OS. This call is required to aovid |
| @@ -181,7 +198,7 @@ _base_fault_reset_work(struct work_struct *work) | |||
| 181 | ioc->remove_host = 1; | 198 | ioc->remove_host = 1; |
| 182 | /*Remove the Dead Host */ | 199 | /*Remove the Dead Host */ |
| 183 | p = kthread_run(mpt3sas_remove_dead_ioc_func, ioc, | 200 | p = kthread_run(mpt3sas_remove_dead_ioc_func, ioc, |
| 184 | "mpt3sas_dead_ioc_%d", ioc->id); | 201 | "%s_dead_ioc_%d", ioc->driver_name, ioc->id); |
| 185 | if (IS_ERR(p)) | 202 | if (IS_ERR(p)) |
| 186 | pr_err(MPT3SAS_FMT | 203 | pr_err(MPT3SAS_FMT |
| 187 | "%s: Running mpt3sas_dead_ioc thread failed !!!!\n", | 204 | "%s: Running mpt3sas_dead_ioc thread failed !!!!\n", |
| @@ -193,6 +210,8 @@ _base_fault_reset_work(struct work_struct *work) | |||
| 193 | return; /* don't rearm timer */ | 210 | return; /* don't rearm timer */ |
| 194 | } | 211 | } |
| 195 | 212 | ||
| 213 | ioc->non_operational_loop = 0; | ||
| 214 | |||
| 196 | if ((doorbell & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_OPERATIONAL) { | 215 | if ((doorbell & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_OPERATIONAL) { |
| 197 | rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | 216 | rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, |
| 198 | FORCE_BIG_HAMMER); | 217 | FORCE_BIG_HAMMER); |
| @@ -235,7 +254,8 @@ mpt3sas_base_start_watchdog(struct MPT3SAS_ADAPTER *ioc) | |||
| 235 | 254 | ||
| 236 | INIT_DELAYED_WORK(&ioc->fault_reset_work, _base_fault_reset_work); | 255 | INIT_DELAYED_WORK(&ioc->fault_reset_work, _base_fault_reset_work); |
| 237 | snprintf(ioc->fault_reset_work_q_name, | 256 | snprintf(ioc->fault_reset_work_q_name, |
| 238 | sizeof(ioc->fault_reset_work_q_name), "poll_%d_status", ioc->id); | 257 | sizeof(ioc->fault_reset_work_q_name), "poll_%s%d_status", |
| 258 | ioc->driver_name, ioc->id); | ||
| 239 | ioc->fault_reset_work_q = | 259 | ioc->fault_reset_work_q = |
| 240 | create_singlethread_workqueue(ioc->fault_reset_work_q_name); | 260 | create_singlethread_workqueue(ioc->fault_reset_work_q_name); |
| 241 | if (!ioc->fault_reset_work_q) { | 261 | if (!ioc->fault_reset_work_q) { |
| @@ -324,7 +344,6 @@ mpt3sas_halt_firmware(struct MPT3SAS_ADAPTER *ioc) | |||
| 324 | panic("panic in %s\n", __func__); | 344 | panic("panic in %s\n", __func__); |
| 325 | } | 345 | } |
| 326 | 346 | ||
| 327 | #ifdef CONFIG_SCSI_MPT3SAS_LOGGING | ||
| 328 | /** | 347 | /** |
| 329 | * _base_sas_ioc_info - verbose translation of the ioc status | 348 | * _base_sas_ioc_info - verbose translation of the ioc status |
| 330 | * @ioc: per adapter object | 349 | * @ioc: per adapter object |
| @@ -578,7 +597,8 @@ _base_display_event_data(struct MPT3SAS_ADAPTER *ioc, | |||
| 578 | desc = "Device Status Change"; | 597 | desc = "Device Status Change"; |
| 579 | break; | 598 | break; |
| 580 | case MPI2_EVENT_IR_OPERATION_STATUS: | 599 | case MPI2_EVENT_IR_OPERATION_STATUS: |
| 581 | desc = "IR Operation Status"; | 600 | if (!ioc->hide_ir_msg) |
| 601 | desc = "IR Operation Status"; | ||
| 582 | break; | 602 | break; |
| 583 | case MPI2_EVENT_SAS_DISCOVERY: | 603 | case MPI2_EVENT_SAS_DISCOVERY: |
| 584 | { | 604 | { |
| @@ -609,16 +629,20 @@ _base_display_event_data(struct MPT3SAS_ADAPTER *ioc, | |||
| 609 | desc = "SAS Enclosure Device Status Change"; | 629 | desc = "SAS Enclosure Device Status Change"; |
| 610 | break; | 630 | break; |
| 611 | case MPI2_EVENT_IR_VOLUME: | 631 | case MPI2_EVENT_IR_VOLUME: |
| 612 | desc = "IR Volume"; | 632 | if (!ioc->hide_ir_msg) |
| 633 | desc = "IR Volume"; | ||
| 613 | break; | 634 | break; |
| 614 | case MPI2_EVENT_IR_PHYSICAL_DISK: | 635 | case MPI2_EVENT_IR_PHYSICAL_DISK: |
| 615 | desc = "IR Physical Disk"; | 636 | if (!ioc->hide_ir_msg) |
| 637 | desc = "IR Physical Disk"; | ||
| 616 | break; | 638 | break; |
| 617 | case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST: | 639 | case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST: |
| 618 | desc = "IR Configuration Change List"; | 640 | if (!ioc->hide_ir_msg) |
| 641 | desc = "IR Configuration Change List"; | ||
| 619 | break; | 642 | break; |
| 620 | case MPI2_EVENT_LOG_ENTRY_ADDED: | 643 | case MPI2_EVENT_LOG_ENTRY_ADDED: |
| 621 | desc = "Log Entry Added"; | 644 | if (!ioc->hide_ir_msg) |
| 645 | desc = "Log Entry Added"; | ||
| 622 | break; | 646 | break; |
| 623 | case MPI2_EVENT_TEMP_THRESHOLD: | 647 | case MPI2_EVENT_TEMP_THRESHOLD: |
| 624 | desc = "Temperature Threshold"; | 648 | desc = "Temperature Threshold"; |
| @@ -630,7 +654,6 @@ _base_display_event_data(struct MPT3SAS_ADAPTER *ioc, | |||
| 630 | 654 | ||
| 631 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, desc); | 655 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, desc); |
| 632 | } | 656 | } |
| 633 | #endif | ||
| 634 | 657 | ||
| 635 | /** | 658 | /** |
| 636 | * _base_sas_log_info - verbose translation of firmware log info | 659 | * _base_sas_log_info - verbose translation of firmware log info |
| @@ -675,7 +698,10 @@ _base_sas_log_info(struct MPT3SAS_ADAPTER *ioc , u32 log_info) | |||
| 675 | originator_str = "PL"; | 698 | originator_str = "PL"; |
| 676 | break; | 699 | break; |
| 677 | case 2: | 700 | case 2: |
| 678 | originator_str = "IR"; | 701 | if (!ioc->hide_ir_msg) |
| 702 | originator_str = "IR"; | ||
| 703 | else | ||
| 704 | originator_str = "WarpDrive"; | ||
| 679 | break; | 705 | break; |
| 680 | } | 706 | } |
| 681 | 707 | ||
| @@ -710,13 +736,13 @@ _base_display_reply_info(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | |||
| 710 | return; | 736 | return; |
| 711 | } | 737 | } |
| 712 | ioc_status = le16_to_cpu(mpi_reply->IOCStatus); | 738 | ioc_status = le16_to_cpu(mpi_reply->IOCStatus); |
| 713 | #ifdef CONFIG_SCSI_MPT3SAS_LOGGING | 739 | |
| 714 | if ((ioc_status & MPI2_IOCSTATUS_MASK) && | 740 | if ((ioc_status & MPI2_IOCSTATUS_MASK) && |
| 715 | (ioc->logging_level & MPT_DEBUG_REPLY)) { | 741 | (ioc->logging_level & MPT_DEBUG_REPLY)) { |
| 716 | _base_sas_ioc_info(ioc , mpi_reply, | 742 | _base_sas_ioc_info(ioc , mpi_reply, |
| 717 | mpt3sas_base_get_msg_frame(ioc, smid)); | 743 | mpt3sas_base_get_msg_frame(ioc, smid)); |
| 718 | } | 744 | } |
| 719 | #endif | 745 | |
| 720 | if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) { | 746 | if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) { |
| 721 | loginfo = le32_to_cpu(mpi_reply->IOCLogInfo); | 747 | loginfo = le32_to_cpu(mpi_reply->IOCLogInfo); |
| 722 | _base_sas_log_info(ioc, loginfo); | 748 | _base_sas_log_info(ioc, loginfo); |
| @@ -783,9 +809,9 @@ _base_async_event(struct MPT3SAS_ADAPTER *ioc, u8 msix_index, u32 reply) | |||
| 783 | return 1; | 809 | return 1; |
| 784 | if (mpi_reply->Function != MPI2_FUNCTION_EVENT_NOTIFICATION) | 810 | if (mpi_reply->Function != MPI2_FUNCTION_EVENT_NOTIFICATION) |
| 785 | return 1; | 811 | return 1; |
| 786 | #ifdef CONFIG_SCSI_MPT3SAS_LOGGING | 812 | |
| 787 | _base_display_event_data(ioc, mpi_reply); | 813 | _base_display_event_data(ioc, mpi_reply); |
| 788 | #endif | 814 | |
| 789 | if (!(mpi_reply->AckRequired & MPI2_EVENT_NOTIFICATION_ACK_REQUIRED)) | 815 | if (!(mpi_reply->AckRequired & MPI2_EVENT_NOTIFICATION_ACK_REQUIRED)) |
| 790 | goto out; | 816 | goto out; |
| 791 | smid = mpt3sas_base_get_smid(ioc, ioc->base_cb_idx); | 817 | smid = mpt3sas_base_get_smid(ioc, ioc->base_cb_idx); |
| @@ -1009,6 +1035,12 @@ _base_interrupt(int irq, void *bus_id) | |||
| 1009 | } | 1035 | } |
| 1010 | 1036 | ||
| 1011 | wmb(); | 1037 | wmb(); |
| 1038 | if (ioc->is_warpdrive) { | ||
| 1039 | writel(reply_q->reply_post_host_index, | ||
| 1040 | ioc->reply_post_host_index[msix_index]); | ||
| 1041 | atomic_dec(&reply_q->busy); | ||
| 1042 | return IRQ_HANDLED; | ||
| 1043 | } | ||
| 1012 | 1044 | ||
| 1013 | /* Update Reply Post Host Index. | 1045 | /* Update Reply Post Host Index. |
| 1014 | * For those HBA's which support combined reply queue feature | 1046 | * For those HBA's which support combined reply queue feature |
| @@ -1320,6 +1352,149 @@ _base_build_zero_len_sge_ieee(struct MPT3SAS_ADAPTER *ioc, void *paddr) | |||
| 1320 | } | 1352 | } |
| 1321 | 1353 | ||
| 1322 | /** | 1354 | /** |
| 1355 | * _base_build_sg_scmd - main sg creation routine | ||
| 1356 | * @ioc: per adapter object | ||
| 1357 | * @scmd: scsi command | ||
| 1358 | * @smid: system request message index | ||
| 1359 | * Context: none. | ||
| 1360 | * | ||
| 1361 | * The main routine that builds scatter gather table from a given | ||
| 1362 | * scsi request sent via the .queuecommand main handler. | ||
| 1363 | * | ||
| 1364 | * Returns 0 success, anything else error | ||
| 1365 | */ | ||
| 1366 | static int | ||
| 1367 | _base_build_sg_scmd(struct MPT3SAS_ADAPTER *ioc, | ||
| 1368 | struct scsi_cmnd *scmd, u16 smid) | ||
| 1369 | { | ||
| 1370 | Mpi2SCSIIORequest_t *mpi_request; | ||
| 1371 | dma_addr_t chain_dma; | ||
| 1372 | struct scatterlist *sg_scmd; | ||
| 1373 | void *sg_local, *chain; | ||
| 1374 | u32 chain_offset; | ||
| 1375 | u32 chain_length; | ||
| 1376 | u32 chain_flags; | ||
| 1377 | int sges_left; | ||
| 1378 | u32 sges_in_segment; | ||
| 1379 | u32 sgl_flags; | ||
| 1380 | u32 sgl_flags_last_element; | ||
| 1381 | u32 sgl_flags_end_buffer; | ||
| 1382 | struct chain_tracker *chain_req; | ||
| 1383 | |||
| 1384 | mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); | ||
| 1385 | |||
| 1386 | /* init scatter gather flags */ | ||
| 1387 | sgl_flags = MPI2_SGE_FLAGS_SIMPLE_ELEMENT; | ||
| 1388 | if (scmd->sc_data_direction == DMA_TO_DEVICE) | ||
| 1389 | sgl_flags |= MPI2_SGE_FLAGS_HOST_TO_IOC; | ||
| 1390 | sgl_flags_last_element = (sgl_flags | MPI2_SGE_FLAGS_LAST_ELEMENT) | ||
| 1391 | << MPI2_SGE_FLAGS_SHIFT; | ||
| 1392 | sgl_flags_end_buffer = (sgl_flags | MPI2_SGE_FLAGS_LAST_ELEMENT | | ||
| 1393 | MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_END_OF_LIST) | ||
| 1394 | << MPI2_SGE_FLAGS_SHIFT; | ||
| 1395 | sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; | ||
| 1396 | |||
| 1397 | sg_scmd = scsi_sglist(scmd); | ||
| 1398 | sges_left = scsi_dma_map(scmd); | ||
| 1399 | if (sges_left < 0) { | ||
| 1400 | sdev_printk(KERN_ERR, scmd->device, | ||
| 1401 | "pci_map_sg failed: request for %d bytes!\n", | ||
| 1402 | scsi_bufflen(scmd)); | ||
| 1403 | return -ENOMEM; | ||
| 1404 | } | ||
| 1405 | |||
| 1406 | sg_local = &mpi_request->SGL; | ||
| 1407 | sges_in_segment = ioc->max_sges_in_main_message; | ||
| 1408 | if (sges_left <= sges_in_segment) | ||
| 1409 | goto fill_in_last_segment; | ||
| 1410 | |||
| 1411 | mpi_request->ChainOffset = (offsetof(Mpi2SCSIIORequest_t, SGL) + | ||
| 1412 | (sges_in_segment * ioc->sge_size))/4; | ||
| 1413 | |||
| 1414 | /* fill in main message segment when there is a chain following */ | ||
| 1415 | while (sges_in_segment) { | ||
| 1416 | if (sges_in_segment == 1) | ||
| 1417 | ioc->base_add_sg_single(sg_local, | ||
| 1418 | sgl_flags_last_element | sg_dma_len(sg_scmd), | ||
| 1419 | sg_dma_address(sg_scmd)); | ||
| 1420 | else | ||
| 1421 | ioc->base_add_sg_single(sg_local, sgl_flags | | ||
| 1422 | sg_dma_len(sg_scmd), sg_dma_address(sg_scmd)); | ||
| 1423 | sg_scmd = sg_next(sg_scmd); | ||
| 1424 | sg_local += ioc->sge_size; | ||
| 1425 | sges_left--; | ||
| 1426 | sges_in_segment--; | ||
| 1427 | } | ||
| 1428 | |||
| 1429 | /* initializing the chain flags and pointers */ | ||
| 1430 | chain_flags = MPI2_SGE_FLAGS_CHAIN_ELEMENT << MPI2_SGE_FLAGS_SHIFT; | ||
| 1431 | chain_req = _base_get_chain_buffer_tracker(ioc, smid); | ||
| 1432 | if (!chain_req) | ||
| 1433 | return -1; | ||
| 1434 | chain = chain_req->chain_buffer; | ||
| 1435 | chain_dma = chain_req->chain_buffer_dma; | ||
| 1436 | do { | ||
| 1437 | sges_in_segment = (sges_left <= | ||
| 1438 | ioc->max_sges_in_chain_message) ? sges_left : | ||
| 1439 | ioc->max_sges_in_chain_message; | ||
| 1440 | chain_offset = (sges_left == sges_in_segment) ? | ||
| 1441 | 0 : (sges_in_segment * ioc->sge_size)/4; | ||
| 1442 | chain_length = sges_in_segment * ioc->sge_size; | ||
| 1443 | if (chain_offset) { | ||
| 1444 | chain_offset = chain_offset << | ||
| 1445 | MPI2_SGE_CHAIN_OFFSET_SHIFT; | ||
| 1446 | chain_length += ioc->sge_size; | ||
| 1447 | } | ||
| 1448 | ioc->base_add_sg_single(sg_local, chain_flags | chain_offset | | ||
| 1449 | chain_length, chain_dma); | ||
| 1450 | sg_local = chain; | ||
| 1451 | if (!chain_offset) | ||
| 1452 | goto fill_in_last_segment; | ||
| 1453 | |||
| 1454 | /* fill in chain segments */ | ||
| 1455 | while (sges_in_segment) { | ||
| 1456 | if (sges_in_segment == 1) | ||
| 1457 | ioc->base_add_sg_single(sg_local, | ||
| 1458 | sgl_flags_last_element | | ||
| 1459 | sg_dma_len(sg_scmd), | ||
| 1460 | sg_dma_address(sg_scmd)); | ||
| 1461 | else | ||
| 1462 | ioc->base_add_sg_single(sg_local, sgl_flags | | ||
| 1463 | sg_dma_len(sg_scmd), | ||
| 1464 | sg_dma_address(sg_scmd)); | ||
| 1465 | sg_scmd = sg_next(sg_scmd); | ||
| 1466 | sg_local += ioc->sge_size; | ||
| 1467 | sges_left--; | ||
| 1468 | sges_in_segment--; | ||
| 1469 | } | ||
| 1470 | |||
| 1471 | chain_req = _base_get_chain_buffer_tracker(ioc, smid); | ||
| 1472 | if (!chain_req) | ||
| 1473 | return -1; | ||
| 1474 | chain = chain_req->chain_buffer; | ||
| 1475 | chain_dma = chain_req->chain_buffer_dma; | ||
| 1476 | } while (1); | ||
| 1477 | |||
| 1478 | |||
| 1479 | fill_in_last_segment: | ||
| 1480 | |||
| 1481 | /* fill the last segment */ | ||
| 1482 | while (sges_left) { | ||
| 1483 | if (sges_left == 1) | ||
| 1484 | ioc->base_add_sg_single(sg_local, sgl_flags_end_buffer | | ||
| 1485 | sg_dma_len(sg_scmd), sg_dma_address(sg_scmd)); | ||
| 1486 | else | ||
| 1487 | ioc->base_add_sg_single(sg_local, sgl_flags | | ||
| 1488 | sg_dma_len(sg_scmd), sg_dma_address(sg_scmd)); | ||
| 1489 | sg_scmd = sg_next(sg_scmd); | ||
| 1490 | sg_local += ioc->sge_size; | ||
| 1491 | sges_left--; | ||
| 1492 | } | ||
| 1493 | |||
| 1494 | return 0; | ||
| 1495 | } | ||
| 1496 | |||
| 1497 | /** | ||
| 1323 | * _base_build_sg_scmd_ieee - main sg creation routine for IEEE format | 1498 | * _base_build_sg_scmd_ieee - main sg creation routine for IEEE format |
| 1324 | * @ioc: per adapter object | 1499 | * @ioc: per adapter object |
| 1325 | * @scmd: scsi command | 1500 | * @scmd: scsi command |
| @@ -1571,6 +1746,14 @@ _base_check_enable_msix(struct MPT3SAS_ADAPTER *ioc) | |||
| 1571 | int base; | 1746 | int base; |
| 1572 | u16 message_control; | 1747 | u16 message_control; |
| 1573 | 1748 | ||
| 1749 | /* Check whether controller SAS2008 B0 controller, | ||
| 1750 | * if it is SAS2008 B0 controller use IO-APIC instead of MSIX | ||
| 1751 | */ | ||
| 1752 | if (ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2008 && | ||
| 1753 | ioc->pdev->revision == SAS2_PCI_DEVICE_B0_REVISION) { | ||
| 1754 | return -EINVAL; | ||
| 1755 | } | ||
| 1756 | |||
| 1574 | base = pci_find_capability(ioc->pdev, PCI_CAP_ID_MSIX); | 1757 | base = pci_find_capability(ioc->pdev, PCI_CAP_ID_MSIX); |
| 1575 | if (!base) { | 1758 | if (!base) { |
| 1576 | dfailprintk(ioc, pr_info(MPT3SAS_FMT "msix not supported\n", | 1759 | dfailprintk(ioc, pr_info(MPT3SAS_FMT "msix not supported\n", |
| @@ -1579,9 +1762,19 @@ _base_check_enable_msix(struct MPT3SAS_ADAPTER *ioc) | |||
| 1579 | } | 1762 | } |
| 1580 | 1763 | ||
| 1581 | /* get msix vector count */ | 1764 | /* get msix vector count */ |
| 1582 | 1765 | /* NUMA_IO not supported for older controllers */ | |
| 1583 | pci_read_config_word(ioc->pdev, base + 2, &message_control); | 1766 | if (ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2004 || |
| 1584 | ioc->msix_vector_count = (message_control & 0x3FF) + 1; | 1767 | ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2008 || |
| 1768 | ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2108_1 || | ||
| 1769 | ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2108_2 || | ||
| 1770 | ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2108_3 || | ||
| 1771 | ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2116_1 || | ||
| 1772 | ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2116_2) | ||
| 1773 | ioc->msix_vector_count = 1; | ||
| 1774 | else { | ||
| 1775 | pci_read_config_word(ioc->pdev, base + 2, &message_control); | ||
| 1776 | ioc->msix_vector_count = (message_control & 0x3FF) + 1; | ||
| 1777 | } | ||
| 1585 | dinitprintk(ioc, pr_info(MPT3SAS_FMT | 1778 | dinitprintk(ioc, pr_info(MPT3SAS_FMT |
| 1586 | "msix is supported, vector_count(%d)\n", | 1779 | "msix is supported, vector_count(%d)\n", |
| 1587 | ioc->name, ioc->msix_vector_count)); | 1780 | ioc->name, ioc->msix_vector_count)); |
| @@ -1643,10 +1836,10 @@ _base_request_irq(struct MPT3SAS_ADAPTER *ioc, u8 index, u32 vector) | |||
| 1643 | atomic_set(&reply_q->busy, 0); | 1836 | atomic_set(&reply_q->busy, 0); |
| 1644 | if (ioc->msix_enable) | 1837 | if (ioc->msix_enable) |
| 1645 | snprintf(reply_q->name, MPT_NAME_LENGTH, "%s%d-msix%d", | 1838 | snprintf(reply_q->name, MPT_NAME_LENGTH, "%s%d-msix%d", |
| 1646 | MPT3SAS_DRIVER_NAME, ioc->id, index); | 1839 | ioc->driver_name, ioc->id, index); |
| 1647 | else | 1840 | else |
| 1648 | snprintf(reply_q->name, MPT_NAME_LENGTH, "%s%d", | 1841 | snprintf(reply_q->name, MPT_NAME_LENGTH, "%s%d", |
| 1649 | MPT3SAS_DRIVER_NAME, ioc->id); | 1842 | ioc->driver_name, ioc->id); |
| 1650 | r = request_irq(vector, _base_interrupt, IRQF_SHARED, reply_q->name, | 1843 | r = request_irq(vector, _base_interrupt, IRQF_SHARED, reply_q->name, |
| 1651 | reply_q); | 1844 | reply_q); |
| 1652 | if (r) { | 1845 | if (r) { |
| @@ -1872,7 +2065,7 @@ mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc) | |||
| 1872 | 2065 | ||
| 1873 | 2066 | ||
| 1874 | if (pci_request_selected_regions(pdev, ioc->bars, | 2067 | if (pci_request_selected_regions(pdev, ioc->bars, |
| 1875 | MPT3SAS_DRIVER_NAME)) { | 2068 | ioc->driver_name)) { |
| 1876 | pr_warn(MPT3SAS_FMT "pci_request_selected_regions: failed\n", | 2069 | pr_warn(MPT3SAS_FMT "pci_request_selected_regions: failed\n", |
| 1877 | ioc->name); | 2070 | ioc->name); |
| 1878 | ioc->bars = 0; | 2071 | ioc->bars = 0; |
| @@ -2158,6 +2351,7 @@ mpt3sas_base_free_smid(struct MPT3SAS_ADAPTER *ioc, u16 smid) | |||
| 2158 | } | 2351 | } |
| 2159 | ioc->scsi_lookup[i].cb_idx = 0xFF; | 2352 | ioc->scsi_lookup[i].cb_idx = 0xFF; |
| 2160 | ioc->scsi_lookup[i].scmd = NULL; | 2353 | ioc->scsi_lookup[i].scmd = NULL; |
| 2354 | ioc->scsi_lookup[i].direct_io = 0; | ||
| 2161 | list_add(&ioc->scsi_lookup[i].tracker_list, &ioc->free_list); | 2355 | list_add(&ioc->scsi_lookup[i].tracker_list, &ioc->free_list); |
| 2162 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | 2356 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); |
| 2163 | 2357 | ||
| @@ -2318,143 +2512,261 @@ mpt3sas_base_put_smid_default(struct MPT3SAS_ADAPTER *ioc, u16 smid) | |||
| 2318 | } | 2512 | } |
| 2319 | 2513 | ||
| 2320 | /** | 2514 | /** |
| 2321 | * _base_display_intel_branding - Display branding string | 2515 | * _base_display_OEMs_branding - Display branding string |
| 2322 | * @ioc: per adapter object | 2516 | * @ioc: per adapter object |
| 2323 | * | 2517 | * |
| 2324 | * Return nothing. | 2518 | * Return nothing. |
| 2325 | */ | 2519 | */ |
| 2326 | static void | 2520 | static void |
| 2327 | _base_display_intel_branding(struct MPT3SAS_ADAPTER *ioc) | 2521 | _base_display_OEMs_branding(struct MPT3SAS_ADAPTER *ioc) |
| 2328 | { | 2522 | { |
| 2329 | if (ioc->pdev->subsystem_vendor != PCI_VENDOR_ID_INTEL) | 2523 | if (ioc->pdev->subsystem_vendor != PCI_VENDOR_ID_INTEL) |
| 2330 | return; | 2524 | return; |
| 2331 | 2525 | ||
| 2332 | switch (ioc->pdev->device) { | 2526 | switch (ioc->pdev->subsystem_vendor) { |
| 2333 | case MPI25_MFGPAGE_DEVID_SAS3008: | 2527 | case PCI_VENDOR_ID_INTEL: |
| 2334 | switch (ioc->pdev->subsystem_device) { | 2528 | switch (ioc->pdev->device) { |
| 2335 | case MPT3SAS_INTEL_RMS3JC080_SSDID: | 2529 | case MPI2_MFGPAGE_DEVID_SAS2008: |
| 2336 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | 2530 | switch (ioc->pdev->subsystem_device) { |
| 2337 | MPT3SAS_INTEL_RMS3JC080_BRANDING); | 2531 | case MPT2SAS_INTEL_RMS2LL080_SSDID: |
| 2338 | break; | 2532 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, |
| 2339 | 2533 | MPT2SAS_INTEL_RMS2LL080_BRANDING); | |
| 2340 | case MPT3SAS_INTEL_RS3GC008_SSDID: | 2534 | break; |
| 2341 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | 2535 | case MPT2SAS_INTEL_RMS2LL040_SSDID: |
| 2342 | MPT3SAS_INTEL_RS3GC008_BRANDING); | 2536 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, |
| 2343 | break; | 2537 | MPT2SAS_INTEL_RMS2LL040_BRANDING); |
| 2344 | case MPT3SAS_INTEL_RS3FC044_SSDID: | 2538 | break; |
| 2345 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | 2539 | case MPT2SAS_INTEL_SSD910_SSDID: |
| 2346 | MPT3SAS_INTEL_RS3FC044_BRANDING); | 2540 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, |
| 2347 | break; | 2541 | MPT2SAS_INTEL_SSD910_BRANDING); |
| 2348 | case MPT3SAS_INTEL_RS3UC080_SSDID: | 2542 | break; |
| 2349 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | 2543 | default: |
| 2350 | MPT3SAS_INTEL_RS3UC080_BRANDING); | 2544 | pr_info(MPT3SAS_FMT |
| 2545 | "Intel(R) Controller: Subsystem ID: 0x%X\n", | ||
| 2546 | ioc->name, ioc->pdev->subsystem_device); | ||
| 2547 | break; | ||
| 2548 | } | ||
| 2549 | case MPI2_MFGPAGE_DEVID_SAS2308_2: | ||
| 2550 | switch (ioc->pdev->subsystem_device) { | ||
| 2551 | case MPT2SAS_INTEL_RS25GB008_SSDID: | ||
| 2552 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | ||
| 2553 | MPT2SAS_INTEL_RS25GB008_BRANDING); | ||
| 2554 | break; | ||
| 2555 | case MPT2SAS_INTEL_RMS25JB080_SSDID: | ||
| 2556 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | ||
| 2557 | MPT2SAS_INTEL_RMS25JB080_BRANDING); | ||
| 2558 | break; | ||
| 2559 | case MPT2SAS_INTEL_RMS25JB040_SSDID: | ||
| 2560 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | ||
| 2561 | MPT2SAS_INTEL_RMS25JB040_BRANDING); | ||
| 2562 | break; | ||
| 2563 | case MPT2SAS_INTEL_RMS25KB080_SSDID: | ||
| 2564 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | ||
| 2565 | MPT2SAS_INTEL_RMS25KB080_BRANDING); | ||
| 2566 | break; | ||
| 2567 | case MPT2SAS_INTEL_RMS25KB040_SSDID: | ||
| 2568 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | ||
| 2569 | MPT2SAS_INTEL_RMS25KB040_BRANDING); | ||
| 2570 | break; | ||
| 2571 | case MPT2SAS_INTEL_RMS25LB040_SSDID: | ||
| 2572 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | ||
| 2573 | MPT2SAS_INTEL_RMS25LB040_BRANDING); | ||
| 2574 | break; | ||
| 2575 | case MPT2SAS_INTEL_RMS25LB080_SSDID: | ||
| 2576 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | ||
| 2577 | MPT2SAS_INTEL_RMS25LB080_BRANDING); | ||
| 2578 | break; | ||
| 2579 | default: | ||
| 2580 | pr_info(MPT3SAS_FMT | ||
| 2581 | "Intel(R) Controller: Subsystem ID: 0x%X\n", | ||
| 2582 | ioc->name, ioc->pdev->subsystem_device); | ||
| 2583 | break; | ||
| 2584 | } | ||
| 2585 | case MPI25_MFGPAGE_DEVID_SAS3008: | ||
| 2586 | switch (ioc->pdev->subsystem_device) { | ||
| 2587 | case MPT3SAS_INTEL_RMS3JC080_SSDID: | ||
| 2588 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | ||
| 2589 | MPT3SAS_INTEL_RMS3JC080_BRANDING); | ||
| 2590 | break; | ||
| 2591 | |||
| 2592 | case MPT3SAS_INTEL_RS3GC008_SSDID: | ||
| 2593 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | ||
| 2594 | MPT3SAS_INTEL_RS3GC008_BRANDING); | ||
| 2595 | break; | ||
| 2596 | case MPT3SAS_INTEL_RS3FC044_SSDID: | ||
| 2597 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | ||
| 2598 | MPT3SAS_INTEL_RS3FC044_BRANDING); | ||
| 2599 | break; | ||
| 2600 | case MPT3SAS_INTEL_RS3UC080_SSDID: | ||
| 2601 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | ||
| 2602 | MPT3SAS_INTEL_RS3UC080_BRANDING); | ||
| 2603 | break; | ||
| 2604 | default: | ||
| 2605 | pr_info(MPT3SAS_FMT | ||
| 2606 | "Intel(R) Controller: Subsystem ID: 0x%X\n", | ||
| 2607 | ioc->name, ioc->pdev->subsystem_device); | ||
| 2608 | break; | ||
| 2609 | } | ||
| 2351 | break; | 2610 | break; |
| 2352 | default: | 2611 | default: |
| 2353 | pr_info(MPT3SAS_FMT | 2612 | pr_info(MPT3SAS_FMT |
| 2354 | "Intel(R) Controller: Subsystem ID: 0x%X\n", | 2613 | "Intel(R) Controller: Subsystem ID: 0x%X\n", |
| 2355 | ioc->name, ioc->pdev->subsystem_device); | 2614 | ioc->name, ioc->pdev->subsystem_device); |
| 2356 | break; | 2615 | break; |
| 2357 | } | 2616 | } |
| 2358 | break; | 2617 | break; |
| 2359 | default: | 2618 | case PCI_VENDOR_ID_DELL: |
| 2360 | pr_info(MPT3SAS_FMT | 2619 | switch (ioc->pdev->device) { |
| 2361 | "Intel(R) Controller: Subsystem ID: 0x%X\n", | 2620 | case MPI2_MFGPAGE_DEVID_SAS2008: |
| 2362 | ioc->name, ioc->pdev->subsystem_device); | 2621 | switch (ioc->pdev->subsystem_device) { |
| 2363 | break; | 2622 | case MPT2SAS_DELL_6GBPS_SAS_HBA_SSDID: |
| 2364 | } | 2623 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, |
| 2365 | } | 2624 | MPT2SAS_DELL_6GBPS_SAS_HBA_BRANDING); |
| 2366 | 2625 | break; | |
| 2367 | 2626 | case MPT2SAS_DELL_PERC_H200_ADAPTER_SSDID: | |
| 2368 | 2627 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | |
| 2369 | /** | 2628 | MPT2SAS_DELL_PERC_H200_ADAPTER_BRANDING); |
| 2370 | * _base_display_dell_branding - Display branding string | 2629 | break; |
| 2371 | * @ioc: per adapter object | 2630 | case MPT2SAS_DELL_PERC_H200_INTEGRATED_SSDID: |
| 2372 | * | 2631 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, |
| 2373 | * Return nothing. | 2632 | MPT2SAS_DELL_PERC_H200_INTEGRATED_BRANDING); |
| 2374 | */ | 2633 | break; |
| 2375 | static void | 2634 | case MPT2SAS_DELL_PERC_H200_MODULAR_SSDID: |
| 2376 | _base_display_dell_branding(struct MPT3SAS_ADAPTER *ioc) | 2635 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, |
| 2377 | { | 2636 | MPT2SAS_DELL_PERC_H200_MODULAR_BRANDING); |
| 2378 | if (ioc->pdev->subsystem_vendor != PCI_VENDOR_ID_DELL) | 2637 | break; |
| 2379 | return; | 2638 | case MPT2SAS_DELL_PERC_H200_EMBEDDED_SSDID: |
| 2380 | 2639 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | |
| 2381 | switch (ioc->pdev->device) { | 2640 | MPT2SAS_DELL_PERC_H200_EMBEDDED_BRANDING); |
| 2382 | case MPI25_MFGPAGE_DEVID_SAS3008: | 2641 | break; |
| 2383 | switch (ioc->pdev->subsystem_device) { | 2642 | case MPT2SAS_DELL_PERC_H200_SSDID: |
| 2384 | case MPT3SAS_DELL_12G_HBA_SSDID: | 2643 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, |
| 2385 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | 2644 | MPT2SAS_DELL_PERC_H200_BRANDING); |
| 2386 | MPT3SAS_DELL_12G_HBA_BRANDING); | 2645 | break; |
| 2646 | case MPT2SAS_DELL_6GBPS_SAS_SSDID: | ||
| 2647 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | ||
| 2648 | MPT2SAS_DELL_6GBPS_SAS_BRANDING); | ||
| 2649 | break; | ||
| 2650 | default: | ||
| 2651 | pr_info(MPT3SAS_FMT | ||
| 2652 | "Dell 6Gbps HBA: Subsystem ID: 0x%X\n", | ||
| 2653 | ioc->name, ioc->pdev->subsystem_device); | ||
| 2654 | break; | ||
| 2655 | } | ||
| 2656 | break; | ||
| 2657 | case MPI25_MFGPAGE_DEVID_SAS3008: | ||
| 2658 | switch (ioc->pdev->subsystem_device) { | ||
| 2659 | case MPT3SAS_DELL_12G_HBA_SSDID: | ||
| 2660 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | ||
| 2661 | MPT3SAS_DELL_12G_HBA_BRANDING); | ||
| 2662 | break; | ||
| 2663 | default: | ||
| 2664 | pr_info(MPT3SAS_FMT | ||
| 2665 | "Dell 12Gbps HBA: Subsystem ID: 0x%X\n", | ||
| 2666 | ioc->name, ioc->pdev->subsystem_device); | ||
| 2667 | break; | ||
| 2668 | } | ||
| 2387 | break; | 2669 | break; |
| 2388 | default: | 2670 | default: |
| 2389 | pr_info(MPT3SAS_FMT | 2671 | pr_info(MPT3SAS_FMT |
| 2390 | "Dell 12Gbps HBA: Subsystem ID: 0x%X\n", ioc->name, | 2672 | "Dell HBA: Subsystem ID: 0x%X\n", ioc->name, |
| 2391 | ioc->pdev->subsystem_device); | 2673 | ioc->pdev->subsystem_device); |
| 2392 | break; | 2674 | break; |
| 2393 | } | 2675 | } |
| 2394 | break; | 2676 | break; |
| 2395 | default: | 2677 | case PCI_VENDOR_ID_CISCO: |
| 2396 | pr_info(MPT3SAS_FMT | 2678 | switch (ioc->pdev->device) { |
| 2397 | "Dell 12Gbps HBA: Subsystem ID: 0x%X\n", ioc->name, | 2679 | case MPI25_MFGPAGE_DEVID_SAS3008: |
| 2398 | ioc->pdev->subsystem_device); | 2680 | switch (ioc->pdev->subsystem_device) { |
| 2399 | break; | 2681 | case MPT3SAS_CISCO_12G_8E_HBA_SSDID: |
| 2400 | } | 2682 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, |
| 2401 | } | 2683 | MPT3SAS_CISCO_12G_8E_HBA_BRANDING); |
| 2402 | 2684 | break; | |
| 2403 | /** | 2685 | case MPT3SAS_CISCO_12G_8I_HBA_SSDID: |
| 2404 | * _base_display_cisco_branding - Display branding string | 2686 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, |
| 2405 | * @ioc: per adapter object | 2687 | MPT3SAS_CISCO_12G_8I_HBA_BRANDING); |
| 2406 | * | 2688 | break; |
| 2407 | * Return nothing. | 2689 | case MPT3SAS_CISCO_12G_AVILA_HBA_SSDID: |
| 2408 | */ | 2690 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, |
| 2409 | static void | 2691 | MPT3SAS_CISCO_12G_AVILA_HBA_BRANDING); |
| 2410 | _base_display_cisco_branding(struct MPT3SAS_ADAPTER *ioc) | 2692 | break; |
| 2411 | { | 2693 | default: |
| 2412 | if (ioc->pdev->subsystem_vendor != PCI_VENDOR_ID_CISCO) | 2694 | pr_info(MPT3SAS_FMT |
| 2413 | return; | 2695 | "Cisco 12Gbps SAS HBA: Subsystem ID: 0x%X\n", |
| 2414 | 2696 | ioc->name, ioc->pdev->subsystem_device); | |
| 2415 | switch (ioc->pdev->device) { | 2697 | break; |
| 2416 | case MPI25_MFGPAGE_DEVID_SAS3008: | 2698 | } |
| 2417 | switch (ioc->pdev->subsystem_device) { | ||
| 2418 | case MPT3SAS_CISCO_12G_8E_HBA_SSDID: | ||
| 2419 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | ||
| 2420 | MPT3SAS_CISCO_12G_8E_HBA_BRANDING); | ||
| 2421 | break; | ||
| 2422 | case MPT3SAS_CISCO_12G_8I_HBA_SSDID: | ||
| 2423 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | ||
| 2424 | MPT3SAS_CISCO_12G_8I_HBA_BRANDING); | ||
| 2425 | break; | 2699 | break; |
| 2426 | case MPT3SAS_CISCO_12G_AVILA_HBA_SSDID: | 2700 | case MPI25_MFGPAGE_DEVID_SAS3108_1: |
| 2427 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | 2701 | switch (ioc->pdev->subsystem_device) { |
| 2702 | case MPT3SAS_CISCO_12G_AVILA_HBA_SSDID: | ||
| 2703 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | ||
| 2428 | MPT3SAS_CISCO_12G_AVILA_HBA_BRANDING); | 2704 | MPT3SAS_CISCO_12G_AVILA_HBA_BRANDING); |
| 2705 | break; | ||
| 2706 | case MPT3SAS_CISCO_12G_COLUSA_MEZZANINE_HBA_SSDID: | ||
| 2707 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | ||
| 2708 | MPT3SAS_CISCO_12G_COLUSA_MEZZANINE_HBA_BRANDING | ||
| 2709 | ); | ||
| 2710 | break; | ||
| 2711 | default: | ||
| 2712 | pr_info(MPT3SAS_FMT | ||
| 2713 | "Cisco 12Gbps SAS HBA: Subsystem ID: 0x%X\n", | ||
| 2714 | ioc->name, ioc->pdev->subsystem_device); | ||
| 2715 | break; | ||
| 2716 | } | ||
| 2429 | break; | 2717 | break; |
| 2430 | default: | 2718 | default: |
| 2431 | pr_info(MPT3SAS_FMT | 2719 | pr_info(MPT3SAS_FMT |
| 2432 | "Cisco 12Gbps SAS HBA: Subsystem ID: 0x%X\n", | 2720 | "Cisco SAS HBA: Subsystem ID: 0x%X\n", |
| 2433 | ioc->name, ioc->pdev->subsystem_device); | 2721 | ioc->name, ioc->pdev->subsystem_device); |
| 2434 | break; | 2722 | break; |
| 2435 | } | 2723 | } |
| 2436 | break; | 2724 | break; |
| 2437 | case MPI25_MFGPAGE_DEVID_SAS3108_1: | 2725 | case MPT2SAS_HP_3PAR_SSVID: |
| 2438 | switch (ioc->pdev->subsystem_device) { | 2726 | switch (ioc->pdev->device) { |
| 2439 | case MPT3SAS_CISCO_12G_AVILA_HBA_SSDID: | 2727 | case MPI2_MFGPAGE_DEVID_SAS2004: |
| 2440 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | 2728 | switch (ioc->pdev->subsystem_device) { |
| 2441 | MPT3SAS_CISCO_12G_AVILA_HBA_BRANDING); | 2729 | case MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_SSDID: |
| 2442 | break; | 2730 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, |
| 2443 | case MPT3SAS_CISCO_12G_COLUSA_MEZZANINE_HBA_SSDID: | 2731 | MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_BRANDING); |
| 2444 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | 2732 | break; |
| 2445 | MPT3SAS_CISCO_12G_COLUSA_MEZZANINE_HBA_BRANDING); | 2733 | default: |
| 2446 | break; | 2734 | pr_info(MPT3SAS_FMT |
| 2735 | "HP 6Gbps SAS HBA: Subsystem ID: 0x%X\n", | ||
| 2736 | ioc->name, ioc->pdev->subsystem_device); | ||
| 2737 | break; | ||
| 2738 | } | ||
| 2739 | case MPI2_MFGPAGE_DEVID_SAS2308_2: | ||
| 2740 | switch (ioc->pdev->subsystem_device) { | ||
| 2741 | case MPT2SAS_HP_2_4_INTERNAL_SSDID: | ||
| 2742 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | ||
| 2743 | MPT2SAS_HP_2_4_INTERNAL_BRANDING); | ||
| 2744 | break; | ||
| 2745 | case MPT2SAS_HP_2_4_EXTERNAL_SSDID: | ||
| 2746 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | ||
| 2747 | MPT2SAS_HP_2_4_EXTERNAL_BRANDING); | ||
| 2748 | break; | ||
| 2749 | case MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_SSDID: | ||
| 2750 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | ||
| 2751 | MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_BRANDING); | ||
| 2752 | break; | ||
| 2753 | case MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_SSDID: | ||
| 2754 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | ||
| 2755 | MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_BRANDING); | ||
| 2756 | break; | ||
| 2757 | default: | ||
| 2758 | pr_info(MPT3SAS_FMT | ||
| 2759 | "HP 6Gbps SAS HBA: Subsystem ID: 0x%X\n", | ||
| 2760 | ioc->name, ioc->pdev->subsystem_device); | ||
| 2761 | break; | ||
| 2762 | } | ||
| 2447 | default: | 2763 | default: |
| 2448 | pr_info(MPT3SAS_FMT | 2764 | pr_info(MPT3SAS_FMT |
| 2449 | "Cisco 12Gbps SAS HBA: Subsystem ID: 0x%X\n", | 2765 | "HP SAS HBA: Subsystem ID: 0x%X\n", |
| 2450 | ioc->name, ioc->pdev->subsystem_device); | 2766 | ioc->name, ioc->pdev->subsystem_device); |
| 2451 | break; | 2767 | break; |
| 2452 | } | 2768 | } |
| 2453 | break; | ||
| 2454 | default: | 2769 | default: |
| 2455 | pr_info(MPT3SAS_FMT | ||
| 2456 | "Cisco 12Gbps SAS HBA: Subsystem ID: 0x%X\n", | ||
| 2457 | ioc->name, ioc->pdev->subsystem_device); | ||
| 2458 | break; | 2770 | break; |
| 2459 | } | 2771 | } |
| 2460 | } | 2772 | } |
| @@ -2488,9 +2800,7 @@ _base_display_ioc_capabilities(struct MPT3SAS_ADAPTER *ioc) | |||
| 2488 | (bios_version & 0x0000FF00) >> 8, | 2800 | (bios_version & 0x0000FF00) >> 8, |
| 2489 | bios_version & 0x000000FF); | 2801 | bios_version & 0x000000FF); |
| 2490 | 2802 | ||
| 2491 | _base_display_intel_branding(ioc); | 2803 | _base_display_OEMs_branding(ioc); |
| 2492 | _base_display_dell_branding(ioc); | ||
| 2493 | _base_display_cisco_branding(ioc); | ||
| 2494 | 2804 | ||
| 2495 | pr_info(MPT3SAS_FMT "Protocol=(", ioc->name); | 2805 | pr_info(MPT3SAS_FMT "Protocol=(", ioc->name); |
| 2496 | 2806 | ||
| @@ -2508,10 +2818,12 @@ _base_display_ioc_capabilities(struct MPT3SAS_ADAPTER *ioc) | |||
| 2508 | pr_info("), "); | 2818 | pr_info("), "); |
| 2509 | pr_info("Capabilities=("); | 2819 | pr_info("Capabilities=("); |
| 2510 | 2820 | ||
| 2511 | if (ioc->facts.IOCCapabilities & | 2821 | if (!ioc->hide_ir_msg) { |
| 2822 | if (ioc->facts.IOCCapabilities & | ||
| 2512 | MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID) { | 2823 | MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID) { |
| 2513 | pr_info("Raid"); | 2824 | pr_info("Raid"); |
| 2514 | i++; | 2825 | i++; |
| 2826 | } | ||
| 2515 | } | 2827 | } |
| 2516 | 2828 | ||
| 2517 | if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR) { | 2829 | if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR) { |
| @@ -2852,18 +3164,22 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) | |||
| 2852 | /* command line tunables for max sgl entries */ | 3164 | /* command line tunables for max sgl entries */ |
| 2853 | if (max_sgl_entries != -1) | 3165 | if (max_sgl_entries != -1) |
| 2854 | sg_tablesize = max_sgl_entries; | 3166 | sg_tablesize = max_sgl_entries; |
| 2855 | else | 3167 | else { |
| 2856 | sg_tablesize = MPT3SAS_SG_DEPTH; | 3168 | if (ioc->hba_mpi_version_belonged == MPI2_VERSION) |
| 3169 | sg_tablesize = MPT2SAS_SG_DEPTH; | ||
| 3170 | else | ||
| 3171 | sg_tablesize = MPT3SAS_SG_DEPTH; | ||
| 3172 | } | ||
| 2857 | 3173 | ||
| 2858 | if (sg_tablesize < MPT3SAS_MIN_PHYS_SEGMENTS) | 3174 | if (sg_tablesize < MPT_MIN_PHYS_SEGMENTS) |
| 2859 | sg_tablesize = MPT3SAS_MIN_PHYS_SEGMENTS; | 3175 | sg_tablesize = MPT_MIN_PHYS_SEGMENTS; |
| 2860 | else if (sg_tablesize > MPT3SAS_MAX_PHYS_SEGMENTS) { | 3176 | else if (sg_tablesize > MPT_MAX_PHYS_SEGMENTS) { |
| 2861 | sg_tablesize = min_t(unsigned short, sg_tablesize, | 3177 | sg_tablesize = min_t(unsigned short, sg_tablesize, |
| 2862 | SCSI_MAX_SG_CHAIN_SEGMENTS); | 3178 | SCSI_MAX_SG_CHAIN_SEGMENTS); |
| 2863 | pr_warn(MPT3SAS_FMT | 3179 | pr_warn(MPT3SAS_FMT |
| 2864 | "sg_tablesize(%u) is bigger than kernel" | 3180 | "sg_tablesize(%u) is bigger than kernel" |
| 2865 | " defined SCSI_MAX_SG_SEGMENTS(%u)\n", ioc->name, | 3181 | " defined SCSI_MAX_SG_SEGMENTS(%u)\n", ioc->name, |
| 2866 | sg_tablesize, MPT3SAS_MAX_PHYS_SEGMENTS); | 3182 | sg_tablesize, MPT_MAX_PHYS_SEGMENTS); |
| 2867 | } | 3183 | } |
| 2868 | ioc->shost->sg_tablesize = sg_tablesize; | 3184 | ioc->shost->sg_tablesize = sg_tablesize; |
| 2869 | 3185 | ||
| @@ -4021,7 +4337,7 @@ _base_send_ioc_init(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) | |||
| 4021 | mpi_request.WhoInit = MPI2_WHOINIT_HOST_DRIVER; | 4337 | mpi_request.WhoInit = MPI2_WHOINIT_HOST_DRIVER; |
| 4022 | mpi_request.VF_ID = 0; /* TODO */ | 4338 | mpi_request.VF_ID = 0; /* TODO */ |
| 4023 | mpi_request.VP_ID = 0; | 4339 | mpi_request.VP_ID = 0; |
| 4024 | mpi_request.MsgVersion = cpu_to_le16(MPI25_VERSION); | 4340 | mpi_request.MsgVersion = cpu_to_le16(ioc->hba_mpi_version_belonged); |
| 4025 | mpi_request.HeaderVersion = cpu_to_le16(MPI2_HEADER_VERSION); | 4341 | mpi_request.HeaderVersion = cpu_to_le16(MPI2_HEADER_VERSION); |
| 4026 | 4342 | ||
| 4027 | if (_base_is_controller_msix_enabled(ioc)) | 4343 | if (_base_is_controller_msix_enabled(ioc)) |
| @@ -4655,6 +4971,7 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) | |||
| 4655 | u32 reply_address; | 4971 | u32 reply_address; |
| 4656 | u16 smid; | 4972 | u16 smid; |
| 4657 | struct _tr_list *delayed_tr, *delayed_tr_next; | 4973 | struct _tr_list *delayed_tr, *delayed_tr_next; |
| 4974 | u8 hide_flag; | ||
| 4658 | struct adapter_reply_queue *reply_q; | 4975 | struct adapter_reply_queue *reply_q; |
| 4659 | long reply_post_free; | 4976 | long reply_post_free; |
| 4660 | u32 reply_post_free_sz, index = 0; | 4977 | u32 reply_post_free_sz, index = 0; |
| @@ -4685,6 +5002,7 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) | |||
| 4685 | ioc->scsi_lookup[i].cb_idx = 0xFF; | 5002 | ioc->scsi_lookup[i].cb_idx = 0xFF; |
| 4686 | ioc->scsi_lookup[i].smid = smid; | 5003 | ioc->scsi_lookup[i].smid = smid; |
| 4687 | ioc->scsi_lookup[i].scmd = NULL; | 5004 | ioc->scsi_lookup[i].scmd = NULL; |
| 5005 | ioc->scsi_lookup[i].direct_io = 0; | ||
| 4688 | list_add_tail(&ioc->scsi_lookup[i].tracker_list, | 5006 | list_add_tail(&ioc->scsi_lookup[i].tracker_list, |
| 4689 | &ioc->free_list); | 5007 | &ioc->free_list); |
| 4690 | } | 5008 | } |
| @@ -4787,6 +5105,16 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) | |||
| 4787 | 5105 | ||
| 4788 | 5106 | ||
| 4789 | if (ioc->is_driver_loading) { | 5107 | if (ioc->is_driver_loading) { |
| 5108 | |||
| 5109 | if (ioc->is_warpdrive && ioc->manu_pg10.OEMIdentifier | ||
| 5110 | == 0x80) { | ||
| 5111 | hide_flag = (u8) ( | ||
| 5112 | le32_to_cpu(ioc->manu_pg10.OEMSpecificFlags0) & | ||
| 5113 | MFG_PAGE10_HIDE_SSDS_MASK); | ||
| 5114 | if (hide_flag != MFG_PAGE10_HIDE_SSDS_MASK) | ||
| 5115 | ioc->mfg_pg10_hide_flag = hide_flag; | ||
| 5116 | } | ||
| 5117 | |||
| 4790 | ioc->wait_for_discovery_to_complete = | 5118 | ioc->wait_for_discovery_to_complete = |
| 4791 | _base_determine_wait_on_discovery(ioc); | 5119 | _base_determine_wait_on_discovery(ioc); |
| 4792 | 5120 | ||
| @@ -4812,6 +5140,8 @@ mpt3sas_base_free_resources(struct MPT3SAS_ADAPTER *ioc) | |||
| 4812 | dexitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, | 5140 | dexitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, |
| 4813 | __func__)); | 5141 | __func__)); |
| 4814 | 5142 | ||
| 5143 | /* synchronizing freeing resource with pci_access_mutex lock */ | ||
| 5144 | mutex_lock(&ioc->pci_access_mutex); | ||
| 4815 | if (ioc->chip_phys && ioc->chip) { | 5145 | if (ioc->chip_phys && ioc->chip) { |
| 4816 | _base_mask_interrupts(ioc); | 5146 | _base_mask_interrupts(ioc); |
| 4817 | ioc->shost_recovery = 1; | 5147 | ioc->shost_recovery = 1; |
| @@ -4820,6 +5150,7 @@ mpt3sas_base_free_resources(struct MPT3SAS_ADAPTER *ioc) | |||
| 4820 | } | 5150 | } |
| 4821 | 5151 | ||
| 4822 | mpt3sas_base_unmap_resources(ioc); | 5152 | mpt3sas_base_unmap_resources(ioc); |
| 5153 | mutex_unlock(&ioc->pci_access_mutex); | ||
| 4823 | return; | 5154 | return; |
| 4824 | } | 5155 | } |
| 4825 | 5156 | ||
| @@ -4834,7 +5165,6 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) | |||
| 4834 | { | 5165 | { |
| 4835 | int r, i; | 5166 | int r, i; |
| 4836 | int cpu_id, last_cpu_id = 0; | 5167 | int cpu_id, last_cpu_id = 0; |
| 4837 | u8 revision; | ||
| 4838 | 5168 | ||
| 4839 | dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, | 5169 | dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, |
| 4840 | __func__)); | 5170 | __func__)); |
| @@ -4854,19 +5184,16 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) | |||
| 4854 | goto out_free_resources; | 5184 | goto out_free_resources; |
| 4855 | } | 5185 | } |
| 4856 | 5186 | ||
| 4857 | /* Check whether the controller revision is C0 or above. | 5187 | if (ioc->is_warpdrive) { |
| 4858 | * only C0 and above revision controllers support 96 MSI-X vectors. | 5188 | ioc->reply_post_host_index = kcalloc(ioc->cpu_msix_table_sz, |
| 4859 | */ | 5189 | sizeof(resource_size_t *), GFP_KERNEL); |
| 4860 | revision = ioc->pdev->revision; | 5190 | if (!ioc->reply_post_host_index) { |
| 4861 | 5191 | dfailprintk(ioc, pr_info(MPT3SAS_FMT "allocation " | |
| 4862 | if ((ioc->pdev->device == MPI25_MFGPAGE_DEVID_SAS3004 || | 5192 | "for cpu_msix_table failed!!!\n", ioc->name)); |
| 4863 | ioc->pdev->device == MPI25_MFGPAGE_DEVID_SAS3008 || | 5193 | r = -ENOMEM; |
| 4864 | ioc->pdev->device == MPI25_MFGPAGE_DEVID_SAS3108_1 || | 5194 | goto out_free_resources; |
| 4865 | ioc->pdev->device == MPI25_MFGPAGE_DEVID_SAS3108_2 || | 5195 | } |
| 4866 | ioc->pdev->device == MPI25_MFGPAGE_DEVID_SAS3108_5 || | 5196 | } |
| 4867 | ioc->pdev->device == MPI25_MFGPAGE_DEVID_SAS3108_6) && | ||
| 4868 | (revision >= 0x02)) | ||
| 4869 | ioc->msix96_vector = 1; | ||
| 4870 | 5197 | ||
| 4871 | ioc->rdpq_array_enable_assigned = 0; | 5198 | ioc->rdpq_array_enable_assigned = 0; |
| 4872 | ioc->dma_mask = 0; | 5199 | ioc->dma_mask = 0; |
| @@ -4874,23 +5201,41 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) | |||
| 4874 | if (r) | 5201 | if (r) |
| 4875 | goto out_free_resources; | 5202 | goto out_free_resources; |
| 4876 | 5203 | ||
| 5204 | if (ioc->is_warpdrive) { | ||
| 5205 | ioc->reply_post_host_index[0] = (resource_size_t __iomem *) | ||
| 5206 | &ioc->chip->ReplyPostHostIndex; | ||
| 5207 | |||
| 5208 | for (i = 1; i < ioc->cpu_msix_table_sz; i++) | ||
| 5209 | ioc->reply_post_host_index[i] = | ||
| 5210 | (resource_size_t __iomem *) | ||
| 5211 | ((u8 __iomem *)&ioc->chip->Doorbell + (0x4000 + ((i - 1) | ||
| 5212 | * 4))); | ||
| 5213 | } | ||
| 4877 | 5214 | ||
| 4878 | pci_set_drvdata(ioc->pdev, ioc->shost); | 5215 | pci_set_drvdata(ioc->pdev, ioc->shost); |
| 4879 | r = _base_get_ioc_facts(ioc, CAN_SLEEP); | 5216 | r = _base_get_ioc_facts(ioc, CAN_SLEEP); |
| 4880 | if (r) | 5217 | if (r) |
| 4881 | goto out_free_resources; | 5218 | goto out_free_resources; |
| 4882 | 5219 | ||
| 4883 | /* | 5220 | switch (ioc->hba_mpi_version_belonged) { |
| 4884 | * In SAS3.0, | 5221 | case MPI2_VERSION: |
| 4885 | * SCSI_IO, SMP_PASSTHRU, SATA_PASSTHRU, Target Assist, and | 5222 | ioc->build_sg_scmd = &_base_build_sg_scmd; |
| 4886 | * Target Status - all require the IEEE formated scatter gather | 5223 | ioc->build_sg = &_base_build_sg; |
| 4887 | * elements. | 5224 | ioc->build_zero_len_sge = &_base_build_zero_len_sge; |
| 4888 | */ | 5225 | break; |
| 4889 | 5226 | case MPI25_VERSION: | |
| 4890 | ioc->build_sg_scmd = &_base_build_sg_scmd_ieee; | 5227 | /* |
| 4891 | ioc->build_sg = &_base_build_sg_ieee; | 5228 | * In SAS3.0, |
| 4892 | ioc->build_zero_len_sge = &_base_build_zero_len_sge_ieee; | 5229 | * SCSI_IO, SMP_PASSTHRU, SATA_PASSTHRU, Target Assist, and |
| 4893 | ioc->sge_size_ieee = sizeof(Mpi2IeeeSgeSimple64_t); | 5230 | * Target Status - all require the IEEE formated scatter gather |
| 5231 | * elements. | ||
| 5232 | */ | ||
| 5233 | ioc->build_sg_scmd = &_base_build_sg_scmd_ieee; | ||
| 5234 | ioc->build_sg = &_base_build_sg_ieee; | ||
| 5235 | ioc->build_zero_len_sge = &_base_build_zero_len_sge_ieee; | ||
| 5236 | ioc->sge_size_ieee = sizeof(Mpi2IeeeSgeSimple64_t); | ||
| 5237 | break; | ||
| 5238 | } | ||
| 4894 | 5239 | ||
| 4895 | /* | 5240 | /* |
| 4896 | * These function pointers for other requests that don't | 5241 | * These function pointers for other requests that don't |
| @@ -5006,6 +5351,7 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) | |||
| 5006 | if (r) | 5351 | if (r) |
| 5007 | goto out_free_resources; | 5352 | goto out_free_resources; |
| 5008 | 5353 | ||
| 5354 | ioc->non_operational_loop = 0; | ||
| 5009 | return 0; | 5355 | return 0; |
| 5010 | 5356 | ||
| 5011 | out_free_resources: | 5357 | out_free_resources: |
| @@ -5016,6 +5362,8 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) | |||
| 5016 | _base_release_memory_pools(ioc); | 5362 | _base_release_memory_pools(ioc); |
| 5017 | pci_set_drvdata(ioc->pdev, NULL); | 5363 | pci_set_drvdata(ioc->pdev, NULL); |
| 5018 | kfree(ioc->cpu_msix_table); | 5364 | kfree(ioc->cpu_msix_table); |
| 5365 | if (ioc->is_warpdrive) | ||
| 5366 | kfree(ioc->reply_post_host_index); | ||
| 5019 | kfree(ioc->pd_handles); | 5367 | kfree(ioc->pd_handles); |
| 5020 | kfree(ioc->blocking_handles); | 5368 | kfree(ioc->blocking_handles); |
| 5021 | kfree(ioc->tm_cmds.reply); | 5369 | kfree(ioc->tm_cmds.reply); |
| @@ -5055,6 +5403,8 @@ mpt3sas_base_detach(struct MPT3SAS_ADAPTER *ioc) | |||
| 5055 | _base_release_memory_pools(ioc); | 5403 | _base_release_memory_pools(ioc); |
| 5056 | pci_set_drvdata(ioc->pdev, NULL); | 5404 | pci_set_drvdata(ioc->pdev, NULL); |
| 5057 | kfree(ioc->cpu_msix_table); | 5405 | kfree(ioc->cpu_msix_table); |
| 5406 | if (ioc->is_warpdrive) | ||
| 5407 | kfree(ioc->reply_post_host_index); | ||
| 5058 | kfree(ioc->pd_handles); | 5408 | kfree(ioc->pd_handles); |
| 5059 | kfree(ioc->blocking_handles); | 5409 | kfree(ioc->blocking_handles); |
| 5060 | kfree(ioc->pfacts); | 5410 | kfree(ioc->pfacts); |
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index f0e462b0880d..a17bea95b0c5 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h | |||
| @@ -63,6 +63,8 @@ | |||
| 63 | #include <scsi/scsi_transport_sas.h> | 63 | #include <scsi/scsi_transport_sas.h> |
| 64 | #include <scsi/scsi_dbg.h> | 64 | #include <scsi/scsi_dbg.h> |
| 65 | #include <scsi/scsi_eh.h> | 65 | #include <scsi/scsi_eh.h> |
| 66 | #include <linux/pci.h> | ||
| 67 | #include <linux/poll.h> | ||
| 66 | 68 | ||
| 67 | #include "mpt3sas_debug.h" | 69 | #include "mpt3sas_debug.h" |
| 68 | #include "mpt3sas_trigger_diag.h" | 70 | #include "mpt3sas_trigger_diag.h" |
| @@ -71,23 +73,37 @@ | |||
| 71 | #define MPT3SAS_DRIVER_NAME "mpt3sas" | 73 | #define MPT3SAS_DRIVER_NAME "mpt3sas" |
| 72 | #define MPT3SAS_AUTHOR "Avago Technologies <MPT-FusionLinux.pdl@avagotech.com>" | 74 | #define MPT3SAS_AUTHOR "Avago Technologies <MPT-FusionLinux.pdl@avagotech.com>" |
| 73 | #define MPT3SAS_DESCRIPTION "LSI MPT Fusion SAS 3.0 Device Driver" | 75 | #define MPT3SAS_DESCRIPTION "LSI MPT Fusion SAS 3.0 Device Driver" |
| 74 | #define MPT3SAS_DRIVER_VERSION "09.100.00.00" | 76 | #define MPT3SAS_DRIVER_VERSION "09.102.00.00" |
| 75 | #define MPT3SAS_MAJOR_VERSION 9 | 77 | #define MPT3SAS_MAJOR_VERSION 9 |
| 76 | #define MPT3SAS_MINOR_VERSION 100 | 78 | #define MPT3SAS_MINOR_VERSION 102 |
| 77 | #define MPT3SAS_BUILD_VERSION 0 | 79 | #define MPT3SAS_BUILD_VERSION 0 |
| 78 | #define MPT3SAS_RELEASE_VERSION 00 | 80 | #define MPT3SAS_RELEASE_VERSION 00 |
| 79 | 81 | ||
| 82 | #define MPT2SAS_DRIVER_NAME "mpt2sas" | ||
| 83 | #define MPT2SAS_DESCRIPTION "LSI MPT Fusion SAS 2.0 Device Driver" | ||
| 84 | #define MPT2SAS_DRIVER_VERSION "20.102.00.00" | ||
| 85 | #define MPT2SAS_MAJOR_VERSION 20 | ||
| 86 | #define MPT2SAS_MINOR_VERSION 102 | ||
| 87 | #define MPT2SAS_BUILD_VERSION 0 | ||
| 88 | #define MPT2SAS_RELEASE_VERSION 00 | ||
| 89 | |||
| 80 | /* | 90 | /* |
| 81 | * Set MPT3SAS_SG_DEPTH value based on user input. | 91 | * Set MPT3SAS_SG_DEPTH value based on user input. |
| 82 | */ | 92 | */ |
| 83 | #define MPT3SAS_MAX_PHYS_SEGMENTS SCSI_MAX_SG_SEGMENTS | 93 | #define MPT_MAX_PHYS_SEGMENTS SCSI_MAX_SG_SEGMENTS |
| 84 | #define MPT3SAS_MIN_PHYS_SEGMENTS 16 | 94 | #define MPT_MIN_PHYS_SEGMENTS 16 |
| 95 | |||
| 85 | #ifdef CONFIG_SCSI_MPT3SAS_MAX_SGE | 96 | #ifdef CONFIG_SCSI_MPT3SAS_MAX_SGE |
| 86 | #define MPT3SAS_SG_DEPTH CONFIG_SCSI_MPT3SAS_MAX_SGE | 97 | #define MPT3SAS_SG_DEPTH CONFIG_SCSI_MPT3SAS_MAX_SGE |
| 87 | #else | 98 | #else |
| 88 | #define MPT3SAS_SG_DEPTH MPT3SAS_MAX_PHYS_SEGMENTS | 99 | #define MPT3SAS_SG_DEPTH MPT_MAX_PHYS_SEGMENTS |
| 89 | #endif | 100 | #endif |
| 90 | 101 | ||
| 102 | #ifdef CONFIG_SCSI_MPT2SAS_MAX_SGE | ||
| 103 | #define MPT2SAS_SG_DEPTH CONFIG_SCSI_MPT2SAS_MAX_SGE | ||
| 104 | #else | ||
| 105 | #define MPT2SAS_SG_DEPTH MPT_MAX_PHYS_SEGMENTS | ||
| 106 | #endif | ||
| 91 | 107 | ||
| 92 | /* | 108 | /* |
| 93 | * Generic Defines | 109 | * Generic Defines |
| @@ -124,6 +140,16 @@ | |||
| 124 | #define MPT3SAS_FMT "%s: " | 140 | #define MPT3SAS_FMT "%s: " |
| 125 | 141 | ||
| 126 | /* | 142 | /* |
| 143 | * WarpDrive Specific Log codes | ||
| 144 | */ | ||
| 145 | |||
| 146 | #define MPT2_WARPDRIVE_LOGENTRY (0x8002) | ||
| 147 | #define MPT2_WARPDRIVE_LC_SSDT (0x41) | ||
| 148 | #define MPT2_WARPDRIVE_LC_SSDLW (0x43) | ||
| 149 | #define MPT2_WARPDRIVE_LC_SSDLF (0x44) | ||
| 150 | #define MPT2_WARPDRIVE_LC_BRMF (0x4D) | ||
| 151 | |||
| 152 | /* | ||
| 127 | * per target private data | 153 | * per target private data |
| 128 | */ | 154 | */ |
| 129 | #define MPT_TARGET_FLAGS_RAID_COMPONENT 0x01 | 155 | #define MPT_TARGET_FLAGS_RAID_COMPONENT 0x01 |
| @@ -131,9 +157,33 @@ | |||
| 131 | #define MPT_TARGET_FLAGS_DELETED 0x04 | 157 | #define MPT_TARGET_FLAGS_DELETED 0x04 |
| 132 | #define MPT_TARGET_FASTPATH_IO 0x08 | 158 | #define MPT_TARGET_FASTPATH_IO 0x08 |
| 133 | 159 | ||
| 160 | #define SAS2_PCI_DEVICE_B0_REVISION (0x01) | ||
| 161 | #define SAS3_PCI_DEVICE_C0_REVISION (0x02) | ||
| 162 | |||
| 134 | /* | 163 | /* |
| 135 | * Intel HBA branding | 164 | * Intel HBA branding |
| 136 | */ | 165 | */ |
| 166 | #define MPT2SAS_INTEL_RMS25JB080_BRANDING \ | ||
| 167 | "Intel(R) Integrated RAID Module RMS25JB080" | ||
| 168 | #define MPT2SAS_INTEL_RMS25JB040_BRANDING \ | ||
| 169 | "Intel(R) Integrated RAID Module RMS25JB040" | ||
| 170 | #define MPT2SAS_INTEL_RMS25KB080_BRANDING \ | ||
| 171 | "Intel(R) Integrated RAID Module RMS25KB080" | ||
| 172 | #define MPT2SAS_INTEL_RMS25KB040_BRANDING \ | ||
| 173 | "Intel(R) Integrated RAID Module RMS25KB040" | ||
| 174 | #define MPT2SAS_INTEL_RMS25LB040_BRANDING \ | ||
| 175 | "Intel(R) Integrated RAID Module RMS25LB040" | ||
| 176 | #define MPT2SAS_INTEL_RMS25LB080_BRANDING \ | ||
| 177 | "Intel(R) Integrated RAID Module RMS25LB080" | ||
| 178 | #define MPT2SAS_INTEL_RMS2LL080_BRANDING \ | ||
| 179 | "Intel Integrated RAID Module RMS2LL080" | ||
| 180 | #define MPT2SAS_INTEL_RMS2LL040_BRANDING \ | ||
| 181 | "Intel Integrated RAID Module RMS2LL040" | ||
| 182 | #define MPT2SAS_INTEL_RS25GB008_BRANDING \ | ||
| 183 | "Intel(R) RAID Controller RS25GB008" | ||
| 184 | #define MPT2SAS_INTEL_SSD910_BRANDING \ | ||
| 185 | "Intel(R) SSD 910 Series" | ||
| 186 | |||
| 137 | #define MPT3SAS_INTEL_RMS3JC080_BRANDING \ | 187 | #define MPT3SAS_INTEL_RMS3JC080_BRANDING \ |
| 138 | "Intel(R) Integrated RAID Module RMS3JC080" | 188 | "Intel(R) Integrated RAID Module RMS3JC080" |
| 139 | #define MPT3SAS_INTEL_RS3GC008_BRANDING \ | 189 | #define MPT3SAS_INTEL_RS3GC008_BRANDING \ |
| @@ -146,33 +196,62 @@ | |||
| 146 | /* | 196 | /* |
| 147 | * Intel HBA SSDIDs | 197 | * Intel HBA SSDIDs |
| 148 | */ | 198 | */ |
| 149 | #define MPT3SAS_INTEL_RMS3JC080_SSDID 0x3521 | 199 | #define MPT2SAS_INTEL_RMS25JB080_SSDID 0x3516 |
| 150 | #define MPT3SAS_INTEL_RS3GC008_SSDID 0x3522 | 200 | #define MPT2SAS_INTEL_RMS25JB040_SSDID 0x3517 |
| 151 | #define MPT3SAS_INTEL_RS3FC044_SSDID 0x3523 | 201 | #define MPT2SAS_INTEL_RMS25KB080_SSDID 0x3518 |
| 152 | #define MPT3SAS_INTEL_RS3UC080_SSDID 0x3524 | 202 | #define MPT2SAS_INTEL_RMS25KB040_SSDID 0x3519 |
| 203 | #define MPT2SAS_INTEL_RMS25LB040_SSDID 0x351A | ||
| 204 | #define MPT2SAS_INTEL_RMS25LB080_SSDID 0x351B | ||
| 205 | #define MPT2SAS_INTEL_RMS2LL080_SSDID 0x350E | ||
| 206 | #define MPT2SAS_INTEL_RMS2LL040_SSDID 0x350F | ||
| 207 | #define MPT2SAS_INTEL_RS25GB008_SSDID 0x3000 | ||
| 208 | #define MPT2SAS_INTEL_SSD910_SSDID 0x3700 | ||
| 209 | |||
| 210 | #define MPT3SAS_INTEL_RMS3JC080_SSDID 0x3521 | ||
| 211 | #define MPT3SAS_INTEL_RS3GC008_SSDID 0x3522 | ||
| 212 | #define MPT3SAS_INTEL_RS3FC044_SSDID 0x3523 | ||
| 213 | #define MPT3SAS_INTEL_RS3UC080_SSDID 0x3524 | ||
| 153 | 214 | ||
| 154 | /* | 215 | /* |
| 155 | * Dell HBA branding | 216 | * Dell HBA branding |
| 156 | */ | 217 | */ |
| 218 | #define MPT2SAS_DELL_BRANDING_SIZE 32 | ||
| 219 | |||
| 220 | #define MPT2SAS_DELL_6GBPS_SAS_HBA_BRANDING "Dell 6Gbps SAS HBA" | ||
| 221 | #define MPT2SAS_DELL_PERC_H200_ADAPTER_BRANDING "Dell PERC H200 Adapter" | ||
| 222 | #define MPT2SAS_DELL_PERC_H200_INTEGRATED_BRANDING "Dell PERC H200 Integrated" | ||
| 223 | #define MPT2SAS_DELL_PERC_H200_MODULAR_BRANDING "Dell PERC H200 Modular" | ||
| 224 | #define MPT2SAS_DELL_PERC_H200_EMBEDDED_BRANDING "Dell PERC H200 Embedded" | ||
| 225 | #define MPT2SAS_DELL_PERC_H200_BRANDING "Dell PERC H200" | ||
| 226 | #define MPT2SAS_DELL_6GBPS_SAS_BRANDING "Dell 6Gbps SAS" | ||
| 227 | |||
| 157 | #define MPT3SAS_DELL_12G_HBA_BRANDING \ | 228 | #define MPT3SAS_DELL_12G_HBA_BRANDING \ |
| 158 | "Dell 12Gbps HBA" | 229 | "Dell 12Gbps HBA" |
| 159 | 230 | ||
| 160 | /* | 231 | /* |
| 161 | * Dell HBA SSDIDs | 232 | * Dell HBA SSDIDs |
| 162 | */ | 233 | */ |
| 163 | #define MPT3SAS_DELL_12G_HBA_SSDID 0x1F46 | 234 | #define MPT2SAS_DELL_6GBPS_SAS_HBA_SSDID 0x1F1C |
| 235 | #define MPT2SAS_DELL_PERC_H200_ADAPTER_SSDID 0x1F1D | ||
| 236 | #define MPT2SAS_DELL_PERC_H200_INTEGRATED_SSDID 0x1F1E | ||
| 237 | #define MPT2SAS_DELL_PERC_H200_MODULAR_SSDID 0x1F1F | ||
| 238 | #define MPT2SAS_DELL_PERC_H200_EMBEDDED_SSDID 0x1F20 | ||
| 239 | #define MPT2SAS_DELL_PERC_H200_SSDID 0x1F21 | ||
| 240 | #define MPT2SAS_DELL_6GBPS_SAS_SSDID 0x1F22 | ||
| 241 | |||
| 242 | #define MPT3SAS_DELL_12G_HBA_SSDID 0x1F46 | ||
| 164 | 243 | ||
| 165 | /* | 244 | /* |
| 166 | * Cisco HBA branding | 245 | * Cisco HBA branding |
| 167 | */ | 246 | */ |
| 168 | #define MPT3SAS_CISCO_12G_8E_HBA_BRANDING \ | 247 | #define MPT3SAS_CISCO_12G_8E_HBA_BRANDING \ |
| 169 | "Cisco 9300-8E 12G SAS HBA" | 248 | "Cisco 9300-8E 12G SAS HBA" |
| 170 | #define MPT3SAS_CISCO_12G_8I_HBA_BRANDING \ | 249 | #define MPT3SAS_CISCO_12G_8I_HBA_BRANDING \ |
| 171 | "Cisco 9300-8i 12G SAS HBA" | 250 | "Cisco 9300-8i 12G SAS HBA" |
| 172 | #define MPT3SAS_CISCO_12G_AVILA_HBA_BRANDING \ | 251 | #define MPT3SAS_CISCO_12G_AVILA_HBA_BRANDING \ |
| 173 | "Cisco 12G Modular SAS Pass through Controller" | 252 | "Cisco 12G Modular SAS Pass through Controller" |
| 174 | #define MPT3SAS_CISCO_12G_COLUSA_MEZZANINE_HBA_BRANDING \ | 253 | #define MPT3SAS_CISCO_12G_COLUSA_MEZZANINE_HBA_BRANDING \ |
| 175 | "UCS C3X60 12G SAS Pass through Controller" | 254 | "UCS C3X60 12G SAS Pass through Controller" |
| 176 | /* | 255 | /* |
| 177 | * Cisco HBA SSSDIDs | 256 | * Cisco HBA SSSDIDs |
| 178 | */ | 257 | */ |
| @@ -189,6 +268,31 @@ | |||
| 189 | #define MPT3_DIAG_BUFFER_IS_DIAG_RESET (0x04) | 268 | #define MPT3_DIAG_BUFFER_IS_DIAG_RESET (0x04) |
| 190 | 269 | ||
| 191 | /* | 270 | /* |
| 271 | * HP HBA branding | ||
| 272 | */ | ||
| 273 | #define MPT2SAS_HP_3PAR_SSVID 0x1590 | ||
| 274 | |||
| 275 | #define MPT2SAS_HP_2_4_INTERNAL_BRANDING \ | ||
| 276 | "HP H220 Host Bus Adapter" | ||
| 277 | #define MPT2SAS_HP_2_4_EXTERNAL_BRANDING \ | ||
| 278 | "HP H221 Host Bus Adapter" | ||
| 279 | #define MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_BRANDING \ | ||
| 280 | "HP H222 Host Bus Adapter" | ||
| 281 | #define MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_BRANDING \ | ||
| 282 | "HP H220i Host Bus Adapter" | ||
| 283 | #define MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_BRANDING \ | ||
| 284 | "HP H210i Host Bus Adapter" | ||
| 285 | |||
| 286 | /* | ||
| 287 | * HO HBA SSDIDs | ||
| 288 | */ | ||
| 289 | #define MPT2SAS_HP_2_4_INTERNAL_SSDID 0x0041 | ||
| 290 | #define MPT2SAS_HP_2_4_EXTERNAL_SSDID 0x0042 | ||
| 291 | #define MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_SSDID 0x0043 | ||
| 292 | #define MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_SSDID 0x0044 | ||
| 293 | #define MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_SSDID 0x0046 | ||
| 294 | |||
| 295 | /* | ||
| 192 | * Combined Reply Queue constants, | 296 | * Combined Reply Queue constants, |
| 193 | * There are twelve Supplemental Reply Post Host Index Registers | 297 | * There are twelve Supplemental Reply Post Host Index Registers |
| 194 | * and each register is at offset 0x10 bytes from the previous one. | 298 | * and each register is at offset 0x10 bytes from the previous one. |
| @@ -243,20 +347,24 @@ struct Mpi2ManufacturingPage11_t { | |||
| 243 | * struct MPT3SAS_TARGET - starget private hostdata | 347 | * struct MPT3SAS_TARGET - starget private hostdata |
| 244 | * @starget: starget object | 348 | * @starget: starget object |
| 245 | * @sas_address: target sas address | 349 | * @sas_address: target sas address |
| 350 | * @raid_device: raid_device pointer to access volume data | ||
| 246 | * @handle: device handle | 351 | * @handle: device handle |
| 247 | * @num_luns: number luns | 352 | * @num_luns: number luns |
| 248 | * @flags: MPT_TARGET_FLAGS_XXX flags | 353 | * @flags: MPT_TARGET_FLAGS_XXX flags |
| 249 | * @deleted: target flaged for deletion | 354 | * @deleted: target flaged for deletion |
| 250 | * @tm_busy: target is busy with TM request. | 355 | * @tm_busy: target is busy with TM request. |
| 356 | * @sdev: The sas_device associated with this target | ||
| 251 | */ | 357 | */ |
| 252 | struct MPT3SAS_TARGET { | 358 | struct MPT3SAS_TARGET { |
| 253 | struct scsi_target *starget; | 359 | struct scsi_target *starget; |
| 254 | u64 sas_address; | 360 | u64 sas_address; |
| 361 | struct _raid_device *raid_device; | ||
| 255 | u16 handle; | 362 | u16 handle; |
| 256 | int num_luns; | 363 | int num_luns; |
| 257 | u32 flags; | 364 | u32 flags; |
| 258 | u8 deleted; | 365 | u8 deleted; |
| 259 | u8 tm_busy; | 366 | u8 tm_busy; |
| 367 | struct _sas_device *sdev; | ||
| 260 | }; | 368 | }; |
| 261 | 369 | ||
| 262 | 370 | ||
| @@ -266,6 +374,11 @@ struct MPT3SAS_TARGET { | |||
| 266 | #define MPT_DEVICE_FLAGS_INIT 0x01 | 374 | #define MPT_DEVICE_FLAGS_INIT 0x01 |
| 267 | #define MPT_DEVICE_TLR_ON 0x02 | 375 | #define MPT_DEVICE_TLR_ON 0x02 |
| 268 | 376 | ||
| 377 | #define MFG_PAGE10_HIDE_SSDS_MASK (0x00000003) | ||
| 378 | #define MFG_PAGE10_HIDE_ALL_DISKS (0x00) | ||
| 379 | #define MFG_PAGE10_EXPOSE_ALL_DISKS (0x01) | ||
| 380 | #define MFG_PAGE10_HIDE_IF_VOL_PRESENT (0x02) | ||
| 381 | |||
| 269 | /** | 382 | /** |
| 270 | * struct MPT3SAS_DEVICE - sdev private hostdata | 383 | * struct MPT3SAS_DEVICE - sdev private hostdata |
| 271 | * @sas_target: starget private hostdata | 384 | * @sas_target: starget private hostdata |
| @@ -358,8 +471,24 @@ struct _sas_device { | |||
| 358 | u8 pend_sas_rphy_add; | 471 | u8 pend_sas_rphy_add; |
| 359 | u8 enclosure_level; | 472 | u8 enclosure_level; |
| 360 | u8 connector_name[4]; | 473 | u8 connector_name[4]; |
| 474 | struct kref refcount; | ||
| 361 | }; | 475 | }; |
| 362 | 476 | ||
| 477 | static inline void sas_device_get(struct _sas_device *s) | ||
| 478 | { | ||
| 479 | kref_get(&s->refcount); | ||
| 480 | } | ||
| 481 | |||
| 482 | static inline void sas_device_free(struct kref *r) | ||
| 483 | { | ||
| 484 | kfree(container_of(r, struct _sas_device, refcount)); | ||
| 485 | } | ||
| 486 | |||
| 487 | static inline void sas_device_put(struct _sas_device *s) | ||
| 488 | { | ||
| 489 | kref_put(&s->refcount, sas_device_free); | ||
| 490 | } | ||
| 491 | |||
| 363 | /** | 492 | /** |
| 364 | * struct _raid_device - raid volume link list | 493 | * struct _raid_device - raid volume link list |
| 365 | * @list: sas device list | 494 | * @list: sas device list |
| @@ -367,6 +496,7 @@ struct _sas_device { | |||
| 367 | * @sdev: scsi device struct (volumes are single lun) | 496 | * @sdev: scsi device struct (volumes are single lun) |
| 368 | * @wwid: unique identifier for the volume | 497 | * @wwid: unique identifier for the volume |
| 369 | * @handle: device handle | 498 | * @handle: device handle |
| 499 | * @block_size: Block size of the volume | ||
| 370 | * @id: target id | 500 | * @id: target id |
| 371 | * @channel: target channel | 501 | * @channel: target channel |
| 372 | * @volume_type: the raid level | 502 | * @volume_type: the raid level |
| @@ -374,6 +504,13 @@ struct _sas_device { | |||
| 374 | * @num_pds: number of hidden raid components | 504 | * @num_pds: number of hidden raid components |
| 375 | * @responding: used in _scsih_raid_device_mark_responding | 505 | * @responding: used in _scsih_raid_device_mark_responding |
| 376 | * @percent_complete: resync percent complete | 506 | * @percent_complete: resync percent complete |
| 507 | * @direct_io_enabled: Whether direct io to PDs are allowed or not | ||
| 508 | * @stripe_exponent: X where 2powX is the stripe sz in blocks | ||
| 509 | * @block_exponent: X where 2powX is the block sz in bytes | ||
| 510 | * @max_lba: Maximum number of LBA in the volume | ||
| 511 | * @stripe_sz: Stripe Size of the volume | ||
| 512 | * @device_info: Device info of the volume member disk | ||
| 513 | * @pd_handle: Array of handles of the physical drives for direct I/O in le16 | ||
| 377 | */ | 514 | */ |
| 378 | #define MPT_MAX_WARPDRIVE_PDS 8 | 515 | #define MPT_MAX_WARPDRIVE_PDS 8 |
| 379 | struct _raid_device { | 516 | struct _raid_device { |
| @@ -382,13 +519,20 @@ struct _raid_device { | |||
| 382 | struct scsi_device *sdev; | 519 | struct scsi_device *sdev; |
| 383 | u64 wwid; | 520 | u64 wwid; |
| 384 | u16 handle; | 521 | u16 handle; |
| 522 | u16 block_sz; | ||
| 385 | int id; | 523 | int id; |
| 386 | int channel; | 524 | int channel; |
| 387 | u8 volume_type; | 525 | u8 volume_type; |
| 388 | u8 num_pds; | 526 | u8 num_pds; |
| 389 | u8 responding; | 527 | u8 responding; |
| 390 | u8 percent_complete; | 528 | u8 percent_complete; |
| 529 | u8 direct_io_enabled; | ||
| 530 | u8 stripe_exponent; | ||
| 531 | u8 block_exponent; | ||
| 532 | u64 max_lba; | ||
| 533 | u32 stripe_sz; | ||
| 391 | u32 device_info; | 534 | u32 device_info; |
| 535 | u16 pd_handle[MPT_MAX_WARPDRIVE_PDS]; | ||
| 392 | }; | 536 | }; |
| 393 | 537 | ||
| 394 | /** | 538 | /** |
| @@ -497,12 +641,14 @@ struct chain_tracker { | |||
| 497 | * @smid: system message id | 641 | * @smid: system message id |
| 498 | * @scmd: scsi request pointer | 642 | * @scmd: scsi request pointer |
| 499 | * @cb_idx: callback index | 643 | * @cb_idx: callback index |
| 644 | * @direct_io: To indicate whether I/O is direct (WARPDRIVE) | ||
| 500 | * @tracker_list: list of free request (ioc->free_list) | 645 | * @tracker_list: list of free request (ioc->free_list) |
| 501 | */ | 646 | */ |
| 502 | struct scsiio_tracker { | 647 | struct scsiio_tracker { |
| 503 | u16 smid; | 648 | u16 smid; |
| 504 | struct scsi_cmnd *scmd; | 649 | struct scsi_cmnd *scmd; |
| 505 | u8 cb_idx; | 650 | u8 cb_idx; |
| 651 | u8 direct_io; | ||
| 506 | struct list_head chain_list; | 652 | struct list_head chain_list; |
| 507 | struct list_head tracker_list; | 653 | struct list_head tracker_list; |
| 508 | }; | 654 | }; |
| @@ -775,7 +921,13 @@ typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc); | |||
| 775 | * @replyPostRegisterIndex: index of next position in Reply Desc Post Queue | 921 | * @replyPostRegisterIndex: index of next position in Reply Desc Post Queue |
| 776 | * @delayed_tr_list: target reset link list | 922 | * @delayed_tr_list: target reset link list |
| 777 | * @delayed_tr_volume_list: volume target reset link list | 923 | * @delayed_tr_volume_list: volume target reset link list |
| 778 | * @@temp_sensors_count: flag to carry the number of temperature sensors | 924 | * @temp_sensors_count: flag to carry the number of temperature sensors |
| 925 | * @pci_access_mutex: Mutex to synchronize ioctl,sysfs show path and | ||
| 926 | * pci resource handling. PCI resource freeing will lead to free | ||
| 927 | * vital hardware/memory resource, which might be in use by cli/sysfs | ||
| 928 | * path functions resulting in Null pointer reference followed by kernel | ||
| 929 | * crash. To avoid the above race condition we use mutex syncrhonization | ||
| 930 | * which ensures the syncrhonization between cli/sysfs_show path. | ||
| 779 | */ | 931 | */ |
| 780 | struct MPT3SAS_ADAPTER { | 932 | struct MPT3SAS_ADAPTER { |
| 781 | struct list_head list; | 933 | struct list_head list; |
| @@ -783,6 +935,7 @@ struct MPT3SAS_ADAPTER { | |||
| 783 | u8 id; | 935 | u8 id; |
| 784 | int cpu_count; | 936 | int cpu_count; |
| 785 | char name[MPT_NAME_LENGTH]; | 937 | char name[MPT_NAME_LENGTH]; |
| 938 | char driver_name[MPT_NAME_LENGTH]; | ||
| 786 | char tmp_string[MPT_STRING_LENGTH]; | 939 | char tmp_string[MPT_STRING_LENGTH]; |
| 787 | struct pci_dev *pdev; | 940 | struct pci_dev *pdev; |
| 788 | Mpi2SystemInterfaceRegs_t __iomem *chip; | 941 | Mpi2SystemInterfaceRegs_t __iomem *chip; |
| @@ -829,8 +982,10 @@ struct MPT3SAS_ADAPTER { | |||
| 829 | u16 msix_vector_count; | 982 | u16 msix_vector_count; |
| 830 | u8 *cpu_msix_table; | 983 | u8 *cpu_msix_table; |
| 831 | u16 cpu_msix_table_sz; | 984 | u16 cpu_msix_table_sz; |
| 985 | resource_size_t __iomem **reply_post_host_index; | ||
| 832 | u32 ioc_reset_count; | 986 | u32 ioc_reset_count; |
| 833 | MPT3SAS_FLUSH_RUNNING_CMDS schedule_dead_ioc_flush_running_cmds; | 987 | MPT3SAS_FLUSH_RUNNING_CMDS schedule_dead_ioc_flush_running_cmds; |
| 988 | u32 non_operational_loop; | ||
| 834 | 989 | ||
| 835 | /* internal commands, callback index */ | 990 | /* internal commands, callback index */ |
| 836 | u8 scsi_io_cb_idx; | 991 | u8 scsi_io_cb_idx; |
| @@ -859,6 +1014,7 @@ struct MPT3SAS_ADAPTER { | |||
| 859 | MPT_BUILD_SG build_sg; | 1014 | MPT_BUILD_SG build_sg; |
| 860 | MPT_BUILD_ZERO_LEN_SGE build_zero_len_sge; | 1015 | MPT_BUILD_ZERO_LEN_SGE build_zero_len_sge; |
| 861 | u16 sge_size_ieee; | 1016 | u16 sge_size_ieee; |
| 1017 | u16 hba_mpi_version_belonged; | ||
| 862 | 1018 | ||
| 863 | /* function ptr for MPI sg elements only */ | 1019 | /* function ptr for MPI sg elements only */ |
| 864 | MPT_BUILD_SG build_sg_mpi; | 1020 | MPT_BUILD_SG build_sg_mpi; |
| @@ -987,6 +1143,7 @@ struct MPT3SAS_ADAPTER { | |||
| 987 | struct list_head delayed_tr_list; | 1143 | struct list_head delayed_tr_list; |
| 988 | struct list_head delayed_tr_volume_list; | 1144 | struct list_head delayed_tr_volume_list; |
| 989 | u8 temp_sensors_count; | 1145 | u8 temp_sensors_count; |
| 1146 | struct mutex pci_access_mutex; | ||
| 990 | 1147 | ||
| 991 | /* diag buffer support */ | 1148 | /* diag buffer support */ |
| 992 | u8 *diag_buffer[MPI2_DIAG_BUF_TYPE_COUNT]; | 1149 | u8 *diag_buffer[MPI2_DIAG_BUF_TYPE_COUNT]; |
| @@ -998,6 +1155,10 @@ struct MPT3SAS_ADAPTER { | |||
| 998 | u32 diagnostic_flags[MPI2_DIAG_BUF_TYPE_COUNT]; | 1155 | u32 diagnostic_flags[MPI2_DIAG_BUF_TYPE_COUNT]; |
| 999 | u32 ring_buffer_offset; | 1156 | u32 ring_buffer_offset; |
| 1000 | u32 ring_buffer_sz; | 1157 | u32 ring_buffer_sz; |
| 1158 | u8 is_warpdrive; | ||
| 1159 | u8 hide_ir_msg; | ||
| 1160 | u8 mfg_pg10_hide_flag; | ||
| 1161 | u8 hide_drives; | ||
| 1001 | spinlock_t diag_trigger_lock; | 1162 | spinlock_t diag_trigger_lock; |
| 1002 | u8 diag_trigger_active; | 1163 | u8 diag_trigger_active; |
| 1003 | struct SL_WH_MASTER_TRIGGER_T diag_trigger_master; | 1164 | struct SL_WH_MASTER_TRIGGER_T diag_trigger_master; |
| @@ -1012,6 +1173,19 @@ typedef u8 (*MPT_CALLBACK)(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | |||
| 1012 | 1173 | ||
| 1013 | /* base shared API */ | 1174 | /* base shared API */ |
| 1014 | extern struct list_head mpt3sas_ioc_list; | 1175 | extern struct list_head mpt3sas_ioc_list; |
| 1176 | extern char driver_name[MPT_NAME_LENGTH]; | ||
| 1177 | /* spinlock on list operations over IOCs | ||
| 1178 | * Case: when multiple warpdrive cards(IOCs) are in use | ||
| 1179 | * Each IOC will added to the ioc list structure on initialization. | ||
| 1180 | * Watchdog threads run at regular intervals to check IOC for any | ||
| 1181 | * fault conditions which will trigger the dead_ioc thread to | ||
| 1182 | * deallocate pci resource, resulting deleting the IOC netry from list, | ||
| 1183 | * this deletion need to protected by spinlock to enusre that | ||
| 1184 | * ioc removal is syncrhonized, if not synchronized it might lead to | ||
| 1185 | * list_del corruption as the ioc list is traversed in cli path. | ||
| 1186 | */ | ||
| 1187 | extern spinlock_t gioc_lock; | ||
| 1188 | |||
| 1015 | void mpt3sas_base_start_watchdog(struct MPT3SAS_ADAPTER *ioc); | 1189 | void mpt3sas_base_start_watchdog(struct MPT3SAS_ADAPTER *ioc); |
| 1016 | void mpt3sas_base_stop_watchdog(struct MPT3SAS_ADAPTER *ioc); | 1190 | void mpt3sas_base_stop_watchdog(struct MPT3SAS_ADAPTER *ioc); |
| 1017 | 1191 | ||
| @@ -1090,10 +1264,14 @@ struct _sas_node *mpt3sas_scsih_expander_find_by_handle( | |||
| 1090 | struct MPT3SAS_ADAPTER *ioc, u16 handle); | 1264 | struct MPT3SAS_ADAPTER *ioc, u16 handle); |
| 1091 | struct _sas_node *mpt3sas_scsih_expander_find_by_sas_address( | 1265 | struct _sas_node *mpt3sas_scsih_expander_find_by_sas_address( |
| 1092 | struct MPT3SAS_ADAPTER *ioc, u64 sas_address); | 1266 | struct MPT3SAS_ADAPTER *ioc, u64 sas_address); |
| 1093 | struct _sas_device *mpt3sas_scsih_sas_device_find_by_sas_address( | 1267 | struct _sas_device *mpt3sas_get_sdev_by_addr( |
| 1094 | struct MPT3SAS_ADAPTER *ioc, u64 sas_address); | 1268 | struct MPT3SAS_ADAPTER *ioc, u64 sas_address); |
| 1269 | struct _sas_device *__mpt3sas_get_sdev_by_addr( | ||
| 1270 | struct MPT3SAS_ADAPTER *ioc, u64 sas_address); | ||
| 1095 | 1271 | ||
| 1096 | void mpt3sas_port_enable_complete(struct MPT3SAS_ADAPTER *ioc); | 1272 | void mpt3sas_port_enable_complete(struct MPT3SAS_ADAPTER *ioc); |
| 1273 | struct _raid_device * | ||
| 1274 | mpt3sas_raid_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle); | ||
| 1097 | 1275 | ||
| 1098 | /* config shared API */ | 1276 | /* config shared API */ |
| 1099 | u8 mpt3sas_config_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | 1277 | u8 mpt3sas_config_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, |
| @@ -1133,6 +1311,8 @@ int mpt3sas_config_get_sas_iounit_pg0(struct MPT3SAS_ADAPTER *ioc, | |||
| 1133 | u16 sz); | 1311 | u16 sz); |
| 1134 | int mpt3sas_config_get_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t | 1312 | int mpt3sas_config_get_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t |
| 1135 | *mpi_reply, Mpi2IOUnitPage1_t *config_page); | 1313 | *mpi_reply, Mpi2IOUnitPage1_t *config_page); |
| 1314 | int mpt3sas_config_get_iounit_pg3(struct MPT3SAS_ADAPTER *ioc, | ||
| 1315 | Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage3_t *config_page, u16 sz); | ||
| 1136 | int mpt3sas_config_set_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t | 1316 | int mpt3sas_config_set_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t |
| 1137 | *mpi_reply, Mpi2IOUnitPage1_t *config_page); | 1317 | *mpi_reply, Mpi2IOUnitPage1_t *config_page); |
| 1138 | int mpt3sas_config_get_iounit_pg8(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t | 1318 | int mpt3sas_config_get_iounit_pg8(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t |
| @@ -1177,8 +1357,8 @@ int mpt3sas_config_get_volume_wwid(struct MPT3SAS_ADAPTER *ioc, | |||
| 1177 | /* ctl shared API */ | 1357 | /* ctl shared API */ |
| 1178 | extern struct device_attribute *mpt3sas_host_attrs[]; | 1358 | extern struct device_attribute *mpt3sas_host_attrs[]; |
| 1179 | extern struct device_attribute *mpt3sas_dev_attrs[]; | 1359 | extern struct device_attribute *mpt3sas_dev_attrs[]; |
| 1180 | void mpt3sas_ctl_init(void); | 1360 | void mpt3sas_ctl_init(ushort hbas_to_enumerate); |
| 1181 | void mpt3sas_ctl_exit(void); | 1361 | void mpt3sas_ctl_exit(ushort hbas_to_enumerate); |
| 1182 | u8 mpt3sas_ctl_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | 1362 | u8 mpt3sas_ctl_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, |
| 1183 | u32 reply); | 1363 | u32 reply); |
| 1184 | void mpt3sas_ctl_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase); | 1364 | void mpt3sas_ctl_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase); |
| @@ -1193,6 +1373,7 @@ int mpt3sas_send_diag_release(struct MPT3SAS_ADAPTER *ioc, u8 buffer_type, | |||
| 1193 | u8 *issue_reset); | 1373 | u8 *issue_reset); |
| 1194 | 1374 | ||
| 1195 | /* transport shared API */ | 1375 | /* transport shared API */ |
| 1376 | extern struct scsi_transport_template *mpt3sas_transport_template; | ||
| 1196 | u8 mpt3sas_transport_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | 1377 | u8 mpt3sas_transport_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, |
| 1197 | u32 reply); | 1378 | u32 reply); |
| 1198 | struct _sas_port *mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, | 1379 | struct _sas_port *mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, |
| @@ -1224,4 +1405,18 @@ void mpt3sas_trigger_scsi(struct MPT3SAS_ADAPTER *ioc, u8 sense_key, | |||
| 1224 | u8 asc, u8 ascq); | 1405 | u8 asc, u8 ascq); |
| 1225 | void mpt3sas_trigger_mpi(struct MPT3SAS_ADAPTER *ioc, u16 ioc_status, | 1406 | void mpt3sas_trigger_mpi(struct MPT3SAS_ADAPTER *ioc, u16 ioc_status, |
| 1226 | u32 loginfo); | 1407 | u32 loginfo); |
| 1408 | |||
| 1409 | /* warpdrive APIs */ | ||
| 1410 | u8 mpt3sas_get_num_volumes(struct MPT3SAS_ADAPTER *ioc); | ||
| 1411 | void mpt3sas_init_warpdrive_properties(struct MPT3SAS_ADAPTER *ioc, | ||
| 1412 | struct _raid_device *raid_device); | ||
| 1413 | inline u8 | ||
| 1414 | mpt3sas_scsi_direct_io_get(struct MPT3SAS_ADAPTER *ioc, u16 smid); | ||
| 1415 | inline void | ||
| 1416 | mpt3sas_scsi_direct_io_set(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 direct_io); | ||
| 1417 | void | ||
| 1418 | mpt3sas_setup_direct_io(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, | ||
| 1419 | struct _raid_device *raid_device, Mpi2SCSIIORequest_t *mpi_request, | ||
| 1420 | u16 smid); | ||
| 1421 | |||
| 1227 | #endif /* MPT3SAS_BASE_H_INCLUDED */ | 1422 | #endif /* MPT3SAS_BASE_H_INCLUDED */ |
diff --git a/drivers/scsi/mpt3sas/mpt3sas_config.c b/drivers/scsi/mpt3sas/mpt3sas_config.c index e45c4613ef0c..a6914ec99cc0 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_config.c +++ b/drivers/scsi/mpt3sas/mpt3sas_config.c | |||
| @@ -83,7 +83,6 @@ struct config_request { | |||
| 83 | dma_addr_t page_dma; | 83 | dma_addr_t page_dma; |
| 84 | }; | 84 | }; |
| 85 | 85 | ||
| 86 | #ifdef CONFIG_SCSI_MPT3SAS_LOGGING | ||
| 87 | /** | 86 | /** |
| 88 | * _config_display_some_debug - debug routine | 87 | * _config_display_some_debug - debug routine |
| 89 | * @ioc: per adapter object | 88 | * @ioc: per adapter object |
| @@ -173,7 +172,6 @@ _config_display_some_debug(struct MPT3SAS_ADAPTER *ioc, u16 smid, | |||
| 173 | ioc->name, le16_to_cpu(mpi_reply->IOCStatus), | 172 | ioc->name, le16_to_cpu(mpi_reply->IOCStatus), |
| 174 | le32_to_cpu(mpi_reply->IOCLogInfo)); | 173 | le32_to_cpu(mpi_reply->IOCLogInfo)); |
| 175 | } | 174 | } |
| 176 | #endif | ||
| 177 | 175 | ||
| 178 | /** | 176 | /** |
| 179 | * _config_alloc_config_dma_memory - obtain physical memory | 177 | * _config_alloc_config_dma_memory - obtain physical memory |
| @@ -255,9 +253,7 @@ mpt3sas_config_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | |||
| 255 | mpi_reply->MsgLength*4); | 253 | mpi_reply->MsgLength*4); |
| 256 | } | 254 | } |
| 257 | ioc->config_cmds.status &= ~MPT3_CMD_PENDING; | 255 | ioc->config_cmds.status &= ~MPT3_CMD_PENDING; |
| 258 | #ifdef CONFIG_SCSI_MPT3SAS_LOGGING | ||
| 259 | _config_display_some_debug(ioc, smid, "config_done", mpi_reply); | 256 | _config_display_some_debug(ioc, smid, "config_done", mpi_reply); |
| 260 | #endif | ||
| 261 | ioc->config_cmds.smid = USHRT_MAX; | 257 | ioc->config_cmds.smid = USHRT_MAX; |
| 262 | complete(&ioc->config_cmds.done); | 258 | complete(&ioc->config_cmds.done); |
| 263 | return 1; | 259 | return 1; |
| @@ -387,9 +383,7 @@ _config_request(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigRequest_t | |||
| 387 | config_request = mpt3sas_base_get_msg_frame(ioc, smid); | 383 | config_request = mpt3sas_base_get_msg_frame(ioc, smid); |
| 388 | ioc->config_cmds.smid = smid; | 384 | ioc->config_cmds.smid = smid; |
| 389 | memcpy(config_request, mpi_request, sizeof(Mpi2ConfigRequest_t)); | 385 | memcpy(config_request, mpi_request, sizeof(Mpi2ConfigRequest_t)); |
| 390 | #ifdef CONFIG_SCSI_MPT3SAS_LOGGING | ||
| 391 | _config_display_some_debug(ioc, smid, "config_request", NULL); | 386 | _config_display_some_debug(ioc, smid, "config_request", NULL); |
| 392 | #endif | ||
| 393 | init_completion(&ioc->config_cmds.done); | 387 | init_completion(&ioc->config_cmds.done); |
| 394 | mpt3sas_base_put_smid_default(ioc, smid); | 388 | mpt3sas_base_put_smid_default(ioc, smid); |
| 395 | timeleft = wait_for_completion_timeout(&ioc->config_cmds.done, | 389 | timeleft = wait_for_completion_timeout(&ioc->config_cmds.done, |
| @@ -872,6 +866,42 @@ mpt3sas_config_set_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, | |||
| 872 | } | 866 | } |
| 873 | 867 | ||
| 874 | /** | 868 | /** |
| 869 | * mpt3sas_config_get_iounit_pg3 - obtain iounit page 3 | ||
| 870 | * @ioc: per adapter object | ||
| 871 | * @mpi_reply: reply mf payload returned from firmware | ||
| 872 | * @config_page: contents of the config page | ||
| 873 | * @sz: size of buffer passed in config_page | ||
| 874 | * Context: sleep. | ||
| 875 | * | ||
| 876 | * Returns 0 for success, non-zero for failure. | ||
| 877 | */ | ||
| 878 | int | ||
| 879 | mpt3sas_config_get_iounit_pg3(struct MPT3SAS_ADAPTER *ioc, | ||
| 880 | Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage3_t *config_page, u16 sz) | ||
| 881 | { | ||
| 882 | Mpi2ConfigRequest_t mpi_request; | ||
| 883 | int r; | ||
| 884 | |||
| 885 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
| 886 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
| 887 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
| 888 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; | ||
| 889 | mpi_request.Header.PageNumber = 3; | ||
| 890 | mpi_request.Header.PageVersion = MPI2_IOUNITPAGE3_PAGEVERSION; | ||
| 891 | ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); | ||
| 892 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 893 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | ||
| 894 | if (r) | ||
| 895 | goto out; | ||
| 896 | |||
| 897 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
| 898 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
| 899 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); | ||
| 900 | out: | ||
| 901 | return r; | ||
| 902 | } | ||
| 903 | |||
| 904 | /** | ||
| 875 | * mpt3sas_config_get_iounit_pg8 - obtain iounit page 8 | 905 | * mpt3sas_config_get_iounit_pg8 - obtain iounit page 8 |
| 876 | * @ioc: per adapter object | 906 | * @ioc: per adapter object |
| 877 | * @mpi_reply: reply mf payload returned from firmware | 907 | * @mpi_reply: reply mf payload returned from firmware |
diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c index 080c8a76d23d..d8366b056b70 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c +++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c | |||
| @@ -78,7 +78,6 @@ enum block_state { | |||
| 78 | BLOCKING, | 78 | BLOCKING, |
| 79 | }; | 79 | }; |
| 80 | 80 | ||
| 81 | #ifdef CONFIG_SCSI_MPT3SAS_LOGGING | ||
| 82 | /** | 81 | /** |
| 83 | * _ctl_sas_device_find_by_handle - sas device search | 82 | * _ctl_sas_device_find_by_handle - sas device search |
| 84 | * @ioc: per adapter object | 83 | * @ioc: per adapter object |
| @@ -254,8 +253,6 @@ _ctl_display_some_debug(struct MPT3SAS_ADAPTER *ioc, u16 smid, | |||
| 254 | } | 253 | } |
| 255 | } | 254 | } |
| 256 | 255 | ||
| 257 | #endif | ||
| 258 | |||
| 259 | /** | 256 | /** |
| 260 | * mpt3sas_ctl_done - ctl module completion routine | 257 | * mpt3sas_ctl_done - ctl module completion routine |
| 261 | * @ioc: per adapter object | 258 | * @ioc: per adapter object |
| @@ -302,9 +299,7 @@ mpt3sas_ctl_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | |||
| 302 | } | 299 | } |
| 303 | } | 300 | } |
| 304 | } | 301 | } |
| 305 | #ifdef CONFIG_SCSI_MPT3SAS_LOGGING | ||
| 306 | _ctl_display_some_debug(ioc, smid, "ctl_done", mpi_reply); | 302 | _ctl_display_some_debug(ioc, smid, "ctl_done", mpi_reply); |
| 307 | #endif | ||
| 308 | ioc->ctl_cmds.status &= ~MPT3_CMD_PENDING; | 303 | ioc->ctl_cmds.status &= ~MPT3_CMD_PENDING; |
| 309 | complete(&ioc->ctl_cmds.done); | 304 | complete(&ioc->ctl_cmds.done); |
| 310 | return 1; | 305 | return 1; |
| @@ -414,20 +409,31 @@ mpt3sas_ctl_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index, | |||
| 414 | * _ctl_verify_adapter - validates ioc_number passed from application | 409 | * _ctl_verify_adapter - validates ioc_number passed from application |
| 415 | * @ioc: per adapter object | 410 | * @ioc: per adapter object |
| 416 | * @iocpp: The ioc pointer is returned in this. | 411 | * @iocpp: The ioc pointer is returned in this. |
| 412 | * @mpi_version: will be MPI2_VERSION for mpt2ctl ioctl device & | ||
| 413 | * MPI25_VERSION for mpt3ctl ioctl device. | ||
| 417 | * | 414 | * |
| 418 | * Return (-1) means error, else ioc_number. | 415 | * Return (-1) means error, else ioc_number. |
| 419 | */ | 416 | */ |
| 420 | static int | 417 | static int |
| 421 | _ctl_verify_adapter(int ioc_number, struct MPT3SAS_ADAPTER **iocpp) | 418 | _ctl_verify_adapter(int ioc_number, struct MPT3SAS_ADAPTER **iocpp, |
| 419 | int mpi_version) | ||
| 422 | { | 420 | { |
| 423 | struct MPT3SAS_ADAPTER *ioc; | 421 | struct MPT3SAS_ADAPTER *ioc; |
| 424 | 422 | /* global ioc lock to protect controller on list operations */ | |
| 423 | spin_lock(&gioc_lock); | ||
| 425 | list_for_each_entry(ioc, &mpt3sas_ioc_list, list) { | 424 | list_for_each_entry(ioc, &mpt3sas_ioc_list, list) { |
| 426 | if (ioc->id != ioc_number) | 425 | if (ioc->id != ioc_number) |
| 427 | continue; | 426 | continue; |
| 427 | /* Check whether this ioctl command is from right | ||
| 428 | * ioctl device or not, if not continue the search. | ||
| 429 | */ | ||
| 430 | if (ioc->hba_mpi_version_belonged != mpi_version) | ||
| 431 | continue; | ||
| 432 | spin_unlock(&gioc_lock); | ||
| 428 | *iocpp = ioc; | 433 | *iocpp = ioc; |
| 429 | return ioc_number; | 434 | return ioc_number; |
| 430 | } | 435 | } |
| 436 | spin_unlock(&gioc_lock); | ||
| 431 | *iocpp = NULL; | 437 | *iocpp = NULL; |
| 432 | return -1; | 438 | return -1; |
| 433 | } | 439 | } |
| @@ -497,7 +503,7 @@ mpt3sas_ctl_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase) | |||
| 497 | * | 503 | * |
| 498 | * Called when application request fasyn callback handler. | 504 | * Called when application request fasyn callback handler. |
| 499 | */ | 505 | */ |
| 500 | static int | 506 | int |
| 501 | _ctl_fasync(int fd, struct file *filep, int mode) | 507 | _ctl_fasync(int fd, struct file *filep, int mode) |
| 502 | { | 508 | { |
| 503 | return fasync_helper(fd, filep, mode, &async_queue); | 509 | return fasync_helper(fd, filep, mode, &async_queue); |
| @@ -509,17 +515,22 @@ _ctl_fasync(int fd, struct file *filep, int mode) | |||
| 509 | * @wait - | 515 | * @wait - |
| 510 | * | 516 | * |
| 511 | */ | 517 | */ |
| 512 | static unsigned int | 518 | unsigned int |
| 513 | _ctl_poll(struct file *filep, poll_table *wait) | 519 | _ctl_poll(struct file *filep, poll_table *wait) |
| 514 | { | 520 | { |
| 515 | struct MPT3SAS_ADAPTER *ioc; | 521 | struct MPT3SAS_ADAPTER *ioc; |
| 516 | 522 | ||
| 517 | poll_wait(filep, &ctl_poll_wait, wait); | 523 | poll_wait(filep, &ctl_poll_wait, wait); |
| 518 | 524 | ||
| 525 | /* global ioc lock to protect controller on list operations */ | ||
| 526 | spin_lock(&gioc_lock); | ||
| 519 | list_for_each_entry(ioc, &mpt3sas_ioc_list, list) { | 527 | list_for_each_entry(ioc, &mpt3sas_ioc_list, list) { |
| 520 | if (ioc->aen_event_read_flag) | 528 | if (ioc->aen_event_read_flag) { |
| 529 | spin_unlock(&gioc_lock); | ||
| 521 | return POLLIN | POLLRDNORM; | 530 | return POLLIN | POLLRDNORM; |
| 531 | } | ||
| 522 | } | 532 | } |
| 533 | spin_unlock(&gioc_lock); | ||
| 523 | return 0; | 534 | return 0; |
| 524 | } | 535 | } |
| 525 | 536 | ||
| @@ -759,9 +770,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, | |||
| 759 | psge = (void *)request + (karg.data_sge_offset*4); | 770 | psge = (void *)request + (karg.data_sge_offset*4); |
| 760 | 771 | ||
| 761 | /* send command to firmware */ | 772 | /* send command to firmware */ |
| 762 | #ifdef CONFIG_SCSI_MPT3SAS_LOGGING | ||
| 763 | _ctl_display_some_debug(ioc, smid, "ctl_request", NULL); | 773 | _ctl_display_some_debug(ioc, smid, "ctl_request", NULL); |
| 764 | #endif | ||
| 765 | 774 | ||
| 766 | init_completion(&ioc->ctl_cmds.done); | 775 | init_completion(&ioc->ctl_cmds.done); |
| 767 | switch (mpi_request->Function) { | 776 | switch (mpi_request->Function) { |
| @@ -916,7 +925,6 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, | |||
| 916 | mpi_reply = ioc->ctl_cmds.reply; | 925 | mpi_reply = ioc->ctl_cmds.reply; |
| 917 | ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK; | 926 | ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK; |
| 918 | 927 | ||
| 919 | #ifdef CONFIG_SCSI_MPT3SAS_LOGGING | ||
| 920 | if (mpi_reply->Function == MPI2_FUNCTION_SCSI_TASK_MGMT && | 928 | if (mpi_reply->Function == MPI2_FUNCTION_SCSI_TASK_MGMT && |
| 921 | (ioc->logging_level & MPT_DEBUG_TM)) { | 929 | (ioc->logging_level & MPT_DEBUG_TM)) { |
| 922 | Mpi2SCSITaskManagementReply_t *tm_reply = | 930 | Mpi2SCSITaskManagementReply_t *tm_reply = |
| @@ -929,7 +937,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, | |||
| 929 | le32_to_cpu(tm_reply->IOCLogInfo), | 937 | le32_to_cpu(tm_reply->IOCLogInfo), |
| 930 | le32_to_cpu(tm_reply->TerminationCount)); | 938 | le32_to_cpu(tm_reply->TerminationCount)); |
| 931 | } | 939 | } |
| 932 | #endif | 940 | |
| 933 | /* copy out xdata to user */ | 941 | /* copy out xdata to user */ |
| 934 | if (data_in_sz) { | 942 | if (data_in_sz) { |
| 935 | if (copy_to_user(karg.data_in_buf_ptr, data_in, | 943 | if (copy_to_user(karg.data_in_buf_ptr, data_in, |
| @@ -1023,7 +1031,6 @@ _ctl_getiocinfo(struct MPT3SAS_ADAPTER *ioc, void __user *arg) | |||
| 1023 | __func__)); | 1031 | __func__)); |
| 1024 | 1032 | ||
| 1025 | memset(&karg, 0 , sizeof(karg)); | 1033 | memset(&karg, 0 , sizeof(karg)); |
| 1026 | karg.adapter_type = MPT3_IOCTL_INTERFACE_SAS3; | ||
| 1027 | if (ioc->pfacts) | 1034 | if (ioc->pfacts) |
| 1028 | karg.port_number = ioc->pfacts[0].PortNumber; | 1035 | karg.port_number = ioc->pfacts[0].PortNumber; |
| 1029 | karg.hw_rev = ioc->pdev->revision; | 1036 | karg.hw_rev = ioc->pdev->revision; |
| @@ -1035,9 +1042,21 @@ _ctl_getiocinfo(struct MPT3SAS_ADAPTER *ioc, void __user *arg) | |||
| 1035 | karg.pci_information.u.bits.function = PCI_FUNC(ioc->pdev->devfn); | 1042 | karg.pci_information.u.bits.function = PCI_FUNC(ioc->pdev->devfn); |
| 1036 | karg.pci_information.segment_id = pci_domain_nr(ioc->pdev->bus); | 1043 | karg.pci_information.segment_id = pci_domain_nr(ioc->pdev->bus); |
| 1037 | karg.firmware_version = ioc->facts.FWVersion.Word; | 1044 | karg.firmware_version = ioc->facts.FWVersion.Word; |
| 1038 | strcpy(karg.driver_version, MPT3SAS_DRIVER_NAME); | 1045 | strcpy(karg.driver_version, ioc->driver_name); |
| 1039 | strcat(karg.driver_version, "-"); | 1046 | strcat(karg.driver_version, "-"); |
| 1040 | strcat(karg.driver_version, MPT3SAS_DRIVER_VERSION); | 1047 | switch (ioc->hba_mpi_version_belonged) { |
| 1048 | case MPI2_VERSION: | ||
| 1049 | if (ioc->is_warpdrive) | ||
| 1050 | karg.adapter_type = MPT2_IOCTL_INTERFACE_SAS2_SSS6200; | ||
| 1051 | else | ||
| 1052 | karg.adapter_type = MPT2_IOCTL_INTERFACE_SAS2; | ||
| 1053 | strcat(karg.driver_version, MPT2SAS_DRIVER_VERSION); | ||
| 1054 | break; | ||
| 1055 | case MPI25_VERSION: | ||
| 1056 | karg.adapter_type = MPT3_IOCTL_INTERFACE_SAS3; | ||
| 1057 | strcat(karg.driver_version, MPT3SAS_DRIVER_VERSION); | ||
| 1058 | break; | ||
| 1059 | } | ||
| 1041 | karg.bios_version = le32_to_cpu(ioc->bios_pg3.BiosVersion); | 1060 | karg.bios_version = le32_to_cpu(ioc->bios_pg3.BiosVersion); |
| 1042 | 1061 | ||
| 1043 | if (copy_to_user(arg, &karg, sizeof(karg))) { | 1062 | if (copy_to_user(arg, &karg, sizeof(karg))) { |
| @@ -2181,12 +2200,14 @@ _ctl_compat_mpt_command(struct MPT3SAS_ADAPTER *ioc, unsigned cmd, | |||
| 2181 | * _ctl_ioctl_main - main ioctl entry point | 2200 | * _ctl_ioctl_main - main ioctl entry point |
| 2182 | * @file - (struct file) | 2201 | * @file - (struct file) |
| 2183 | * @cmd - ioctl opcode | 2202 | * @cmd - ioctl opcode |
| 2184 | * @arg - | 2203 | * @arg - user space data buffer |
| 2185 | * compat - handles 32 bit applications in 64bit os | 2204 | * @compat - handles 32 bit applications in 64bit os |
| 2205 | * @mpi_version: will be MPI2_VERSION for mpt2ctl ioctl device & | ||
| 2206 | * MPI25_VERSION for mpt3ctl ioctl device. | ||
| 2186 | */ | 2207 | */ |
| 2187 | static long | 2208 | static long |
| 2188 | _ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg, | 2209 | _ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg, |
| 2189 | u8 compat) | 2210 | u8 compat, u16 mpi_version) |
| 2190 | { | 2211 | { |
| 2191 | struct MPT3SAS_ADAPTER *ioc; | 2212 | struct MPT3SAS_ADAPTER *ioc; |
| 2192 | struct mpt3_ioctl_header ioctl_header; | 2213 | struct mpt3_ioctl_header ioctl_header; |
| @@ -2201,19 +2222,29 @@ _ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg, | |||
| 2201 | return -EFAULT; | 2222 | return -EFAULT; |
| 2202 | } | 2223 | } |
| 2203 | 2224 | ||
| 2204 | if (_ctl_verify_adapter(ioctl_header.ioc_number, &ioc) == -1 || !ioc) | 2225 | if (_ctl_verify_adapter(ioctl_header.ioc_number, |
| 2226 | &ioc, mpi_version) == -1 || !ioc) | ||
| 2205 | return -ENODEV; | 2227 | return -ENODEV; |
| 2206 | 2228 | ||
| 2229 | /* pci_access_mutex lock acquired by ioctl path */ | ||
| 2230 | mutex_lock(&ioc->pci_access_mutex); | ||
| 2231 | |||
| 2207 | if (ioc->shost_recovery || ioc->pci_error_recovery || | 2232 | if (ioc->shost_recovery || ioc->pci_error_recovery || |
| 2208 | ioc->is_driver_loading) | 2233 | ioc->is_driver_loading || ioc->remove_host) { |
| 2209 | return -EAGAIN; | 2234 | ret = -EAGAIN; |
| 2235 | goto out_unlock_pciaccess; | ||
| 2236 | } | ||
| 2210 | 2237 | ||
| 2211 | state = (file->f_flags & O_NONBLOCK) ? NON_BLOCKING : BLOCKING; | 2238 | state = (file->f_flags & O_NONBLOCK) ? NON_BLOCKING : BLOCKING; |
| 2212 | if (state == NON_BLOCKING) { | 2239 | if (state == NON_BLOCKING) { |
| 2213 | if (!mutex_trylock(&ioc->ctl_cmds.mutex)) | 2240 | if (!mutex_trylock(&ioc->ctl_cmds.mutex)) { |
| 2214 | return -EAGAIN; | 2241 | ret = -EAGAIN; |
| 2215 | } else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex)) | 2242 | goto out_unlock_pciaccess; |
| 2216 | return -ERESTARTSYS; | 2243 | } |
| 2244 | } else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex)) { | ||
| 2245 | ret = -ERESTARTSYS; | ||
| 2246 | goto out_unlock_pciaccess; | ||
| 2247 | } | ||
| 2217 | 2248 | ||
| 2218 | 2249 | ||
| 2219 | switch (cmd) { | 2250 | switch (cmd) { |
| @@ -2294,39 +2325,78 @@ _ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg, | |||
| 2294 | } | 2325 | } |
| 2295 | 2326 | ||
| 2296 | mutex_unlock(&ioc->ctl_cmds.mutex); | 2327 | mutex_unlock(&ioc->ctl_cmds.mutex); |
| 2328 | out_unlock_pciaccess: | ||
| 2329 | mutex_unlock(&ioc->pci_access_mutex); | ||
| 2297 | return ret; | 2330 | return ret; |
| 2298 | } | 2331 | } |
| 2299 | 2332 | ||
| 2300 | /** | 2333 | /** |
| 2301 | * _ctl_ioctl - main ioctl entry point (unlocked) | 2334 | * _ctl_ioctl - mpt3ctl main ioctl entry point (unlocked) |
| 2302 | * @file - (struct file) | 2335 | * @file - (struct file) |
| 2303 | * @cmd - ioctl opcode | 2336 | * @cmd - ioctl opcode |
| 2304 | * @arg - | 2337 | * @arg - |
| 2305 | */ | 2338 | */ |
| 2306 | static long | 2339 | long |
| 2307 | _ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 2340 | _ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
| 2308 | { | 2341 | { |
| 2309 | long ret; | 2342 | long ret; |
| 2310 | 2343 | ||
| 2311 | ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 0); | 2344 | /* pass MPI25_VERSION value, to indicate that this ioctl cmd |
| 2345 | * came from mpt3ctl ioctl device. | ||
| 2346 | */ | ||
| 2347 | ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 0, MPI25_VERSION); | ||
| 2312 | return ret; | 2348 | return ret; |
| 2313 | } | 2349 | } |
| 2314 | 2350 | ||
| 2351 | /** | ||
| 2352 | * _ctl_mpt2_ioctl - mpt2ctl main ioctl entry point (unlocked) | ||
| 2353 | * @file - (struct file) | ||
| 2354 | * @cmd - ioctl opcode | ||
| 2355 | * @arg - | ||
| 2356 | */ | ||
| 2357 | long | ||
| 2358 | _ctl_mpt2_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
| 2359 | { | ||
| 2360 | long ret; | ||
| 2361 | |||
| 2362 | /* pass MPI2_VERSION value, to indicate that this ioctl cmd | ||
| 2363 | * came from mpt2ctl ioctl device. | ||
| 2364 | */ | ||
| 2365 | ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 0, MPI2_VERSION); | ||
| 2366 | return ret; | ||
| 2367 | } | ||
| 2315 | #ifdef CONFIG_COMPAT | 2368 | #ifdef CONFIG_COMPAT |
| 2316 | /** | 2369 | /** |
| 2317 | * _ctl_ioctl_compat - main ioctl entry point (compat) | 2370 | *_ ctl_ioctl_compat - main ioctl entry point (compat) |
| 2318 | * @file - | 2371 | * @file - |
| 2319 | * @cmd - | 2372 | * @cmd - |
| 2320 | * @arg - | 2373 | * @arg - |
| 2321 | * | 2374 | * |
| 2322 | * This routine handles 32 bit applications in 64bit os. | 2375 | * This routine handles 32 bit applications in 64bit os. |
| 2323 | */ | 2376 | */ |
| 2324 | static long | 2377 | long |
| 2325 | _ctl_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg) | 2378 | _ctl_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg) |
| 2326 | { | 2379 | { |
| 2327 | long ret; | 2380 | long ret; |
| 2328 | 2381 | ||
| 2329 | ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 1); | 2382 | ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 1, MPI25_VERSION); |
| 2383 | return ret; | ||
| 2384 | } | ||
| 2385 | |||
| 2386 | /** | ||
| 2387 | *_ ctl_mpt2_ioctl_compat - main ioctl entry point (compat) | ||
| 2388 | * @file - | ||
| 2389 | * @cmd - | ||
| 2390 | * @arg - | ||
| 2391 | * | ||
| 2392 | * This routine handles 32 bit applications in 64bit os. | ||
| 2393 | */ | ||
| 2394 | long | ||
| 2395 | _ctl_mpt2_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg) | ||
| 2396 | { | ||
| 2397 | long ret; | ||
| 2398 | |||
| 2399 | ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 1, MPI2_VERSION); | ||
| 2330 | return ret; | 2400 | return ret; |
| 2331 | } | 2401 | } |
| 2332 | #endif | 2402 | #endif |
| @@ -2713,6 +2783,82 @@ _ctl_ioc_reply_queue_count_show(struct device *cdev, | |||
| 2713 | static DEVICE_ATTR(reply_queue_count, S_IRUGO, _ctl_ioc_reply_queue_count_show, | 2783 | static DEVICE_ATTR(reply_queue_count, S_IRUGO, _ctl_ioc_reply_queue_count_show, |
| 2714 | NULL); | 2784 | NULL); |
| 2715 | 2785 | ||
| 2786 | /** | ||
| 2787 | * _ctl_BRM_status_show - Backup Rail Monitor Status | ||
| 2788 | * @cdev - pointer to embedded class device | ||
| 2789 | * @buf - the buffer returned | ||
| 2790 | * | ||
| 2791 | * This is number of reply queues | ||
| 2792 | * | ||
| 2793 | * A sysfs 'read-only' shost attribute. | ||
| 2794 | */ | ||
| 2795 | static ssize_t | ||
| 2796 | _ctl_BRM_status_show(struct device *cdev, struct device_attribute *attr, | ||
| 2797 | char *buf) | ||
| 2798 | { | ||
| 2799 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
| 2800 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 2801 | Mpi2IOUnitPage3_t *io_unit_pg3 = NULL; | ||
| 2802 | Mpi2ConfigReply_t mpi_reply; | ||
| 2803 | u16 backup_rail_monitor_status = 0; | ||
| 2804 | u16 ioc_status; | ||
| 2805 | int sz; | ||
| 2806 | ssize_t rc = 0; | ||
| 2807 | |||
| 2808 | if (!ioc->is_warpdrive) { | ||
| 2809 | pr_err(MPT3SAS_FMT "%s: BRM attribute is only for" | ||
| 2810 | " warpdrive\n", ioc->name, __func__); | ||
| 2811 | goto out; | ||
| 2812 | } | ||
| 2813 | /* pci_access_mutex lock acquired by sysfs show path */ | ||
| 2814 | mutex_lock(&ioc->pci_access_mutex); | ||
| 2815 | if (ioc->pci_error_recovery || ioc->remove_host) { | ||
| 2816 | mutex_unlock(&ioc->pci_access_mutex); | ||
| 2817 | return 0; | ||
| 2818 | } | ||
| 2819 | |||
| 2820 | /* allocate upto GPIOVal 36 entries */ | ||
| 2821 | sz = offsetof(Mpi2IOUnitPage3_t, GPIOVal) + (sizeof(u16) * 36); | ||
| 2822 | io_unit_pg3 = kzalloc(sz, GFP_KERNEL); | ||
| 2823 | if (!io_unit_pg3) { | ||
| 2824 | pr_err(MPT3SAS_FMT "%s: failed allocating memory " | ||
| 2825 | "for iounit_pg3: (%d) bytes\n", ioc->name, __func__, sz); | ||
| 2826 | goto out; | ||
| 2827 | } | ||
| 2828 | |||
| 2829 | if (mpt3sas_config_get_iounit_pg3(ioc, &mpi_reply, io_unit_pg3, sz) != | ||
| 2830 | 0) { | ||
| 2831 | pr_err(MPT3SAS_FMT | ||
| 2832 | "%s: failed reading iounit_pg3\n", ioc->name, | ||
| 2833 | __func__); | ||
| 2834 | goto out; | ||
| 2835 | } | ||
| 2836 | |||
| 2837 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; | ||
| 2838 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { | ||
| 2839 | pr_err(MPT3SAS_FMT "%s: iounit_pg3 failed with " | ||
| 2840 | "ioc_status(0x%04x)\n", ioc->name, __func__, ioc_status); | ||
| 2841 | goto out; | ||
| 2842 | } | ||
| 2843 | |||
| 2844 | if (io_unit_pg3->GPIOCount < 25) { | ||
| 2845 | pr_err(MPT3SAS_FMT "%s: iounit_pg3->GPIOCount less than " | ||
| 2846 | "25 entries, detected (%d) entries\n", ioc->name, __func__, | ||
| 2847 | io_unit_pg3->GPIOCount); | ||
| 2848 | goto out; | ||
| 2849 | } | ||
| 2850 | |||
| 2851 | /* BRM status is in bit zero of GPIOVal[24] */ | ||
| 2852 | backup_rail_monitor_status = le16_to_cpu(io_unit_pg3->GPIOVal[24]); | ||
| 2853 | rc = snprintf(buf, PAGE_SIZE, "%d\n", (backup_rail_monitor_status & 1)); | ||
| 2854 | |||
| 2855 | out: | ||
| 2856 | kfree(io_unit_pg3); | ||
| 2857 | mutex_unlock(&ioc->pci_access_mutex); | ||
| 2858 | return rc; | ||
| 2859 | } | ||
| 2860 | static DEVICE_ATTR(BRM_status, S_IRUGO, _ctl_BRM_status_show, NULL); | ||
| 2861 | |||
| 2716 | struct DIAG_BUFFER_START { | 2862 | struct DIAG_BUFFER_START { |
| 2717 | __le32 Size; | 2863 | __le32 Size; |
| 2718 | __le32 DiagVersion; | 2864 | __le32 DiagVersion; |
| @@ -3165,6 +3311,7 @@ struct device_attribute *mpt3sas_host_attrs[] = { | |||
| 3165 | &dev_attr_diag_trigger_event, | 3311 | &dev_attr_diag_trigger_event, |
| 3166 | &dev_attr_diag_trigger_scsi, | 3312 | &dev_attr_diag_trigger_scsi, |
| 3167 | &dev_attr_diag_trigger_mpi, | 3313 | &dev_attr_diag_trigger_mpi, |
| 3314 | &dev_attr_BRM_status, | ||
| 3168 | NULL, | 3315 | NULL, |
| 3169 | }; | 3316 | }; |
| 3170 | 3317 | ||
| @@ -3218,6 +3365,7 @@ struct device_attribute *mpt3sas_dev_attrs[] = { | |||
| 3218 | NULL, | 3365 | NULL, |
| 3219 | }; | 3366 | }; |
| 3220 | 3367 | ||
| 3368 | /* file operations table for mpt3ctl device */ | ||
| 3221 | static const struct file_operations ctl_fops = { | 3369 | static const struct file_operations ctl_fops = { |
| 3222 | .owner = THIS_MODULE, | 3370 | .owner = THIS_MODULE, |
| 3223 | .unlocked_ioctl = _ctl_ioctl, | 3371 | .unlocked_ioctl = _ctl_ioctl, |
| @@ -3228,23 +3376,53 @@ static const struct file_operations ctl_fops = { | |||
| 3228 | #endif | 3376 | #endif |
| 3229 | }; | 3377 | }; |
| 3230 | 3378 | ||
| 3379 | /* file operations table for mpt2ctl device */ | ||
| 3380 | static const struct file_operations ctl_gen2_fops = { | ||
| 3381 | .owner = THIS_MODULE, | ||
| 3382 | .unlocked_ioctl = _ctl_mpt2_ioctl, | ||
| 3383 | .poll = _ctl_poll, | ||
| 3384 | .fasync = _ctl_fasync, | ||
| 3385 | #ifdef CONFIG_COMPAT | ||
| 3386 | .compat_ioctl = _ctl_mpt2_ioctl_compat, | ||
| 3387 | #endif | ||
| 3388 | }; | ||
| 3389 | |||
| 3231 | static struct miscdevice ctl_dev = { | 3390 | static struct miscdevice ctl_dev = { |
| 3232 | .minor = MPT3SAS_MINOR, | 3391 | .minor = MPT3SAS_MINOR, |
| 3233 | .name = MPT3SAS_DEV_NAME, | 3392 | .name = MPT3SAS_DEV_NAME, |
| 3234 | .fops = &ctl_fops, | 3393 | .fops = &ctl_fops, |
| 3235 | }; | 3394 | }; |
| 3236 | 3395 | ||
| 3396 | static struct miscdevice gen2_ctl_dev = { | ||
| 3397 | .minor = MPT2SAS_MINOR, | ||
| 3398 | .name = MPT2SAS_DEV_NAME, | ||
| 3399 | .fops = &ctl_gen2_fops, | ||
| 3400 | }; | ||
| 3401 | |||
| 3237 | /** | 3402 | /** |
| 3238 | * mpt3sas_ctl_init - main entry point for ctl. | 3403 | * mpt3sas_ctl_init - main entry point for ctl. |
| 3239 | * | 3404 | * |
| 3240 | */ | 3405 | */ |
| 3241 | void | 3406 | void |
| 3242 | mpt3sas_ctl_init(void) | 3407 | mpt3sas_ctl_init(ushort hbas_to_enumerate) |
| 3243 | { | 3408 | { |
| 3244 | async_queue = NULL; | 3409 | async_queue = NULL; |
| 3245 | if (misc_register(&ctl_dev) < 0) | 3410 | |
| 3246 | pr_err("%s can't register misc device [minor=%d]\n", | 3411 | /* Don't register mpt3ctl ioctl device if |
| 3247 | MPT3SAS_DRIVER_NAME, MPT3SAS_MINOR); | 3412 | * hbas_to_enumarate is one. |
| 3413 | */ | ||
| 3414 | if (hbas_to_enumerate != 1) | ||
| 3415 | if (misc_register(&ctl_dev) < 0) | ||
| 3416 | pr_err("%s can't register misc device [minor=%d]\n", | ||
| 3417 | MPT3SAS_DRIVER_NAME, MPT3SAS_MINOR); | ||
| 3418 | |||
| 3419 | /* Don't register mpt3ctl ioctl device if | ||
| 3420 | * hbas_to_enumarate is two. | ||
| 3421 | */ | ||
| 3422 | if (hbas_to_enumerate != 2) | ||
| 3423 | if (misc_register(&gen2_ctl_dev) < 0) | ||
| 3424 | pr_err("%s can't register misc device [minor=%d]\n", | ||
| 3425 | MPT2SAS_DRIVER_NAME, MPT2SAS_MINOR); | ||
| 3248 | 3426 | ||
| 3249 | init_waitqueue_head(&ctl_poll_wait); | 3427 | init_waitqueue_head(&ctl_poll_wait); |
| 3250 | } | 3428 | } |
| @@ -3254,7 +3432,7 @@ mpt3sas_ctl_init(void) | |||
| 3254 | * | 3432 | * |
| 3255 | */ | 3433 | */ |
| 3256 | void | 3434 | void |
| 3257 | mpt3sas_ctl_exit(void) | 3435 | mpt3sas_ctl_exit(ushort hbas_to_enumerate) |
| 3258 | { | 3436 | { |
| 3259 | struct MPT3SAS_ADAPTER *ioc; | 3437 | struct MPT3SAS_ADAPTER *ioc; |
| 3260 | int i; | 3438 | int i; |
| @@ -3279,5 +3457,8 @@ mpt3sas_ctl_exit(void) | |||
| 3279 | 3457 | ||
| 3280 | kfree(ioc->event_log); | 3458 | kfree(ioc->event_log); |
| 3281 | } | 3459 | } |
| 3282 | misc_deregister(&ctl_dev); | 3460 | if (hbas_to_enumerate != 1) |
| 3461 | misc_deregister(&ctl_dev); | ||
| 3462 | if (hbas_to_enumerate != 2) | ||
| 3463 | misc_deregister(&gen2_ctl_dev); | ||
| 3283 | } | 3464 | } |
diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.h b/drivers/scsi/mpt3sas/mpt3sas_ctl.h index aee99ce67e54..89408356d252 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_ctl.h +++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.h | |||
| @@ -50,10 +50,13 @@ | |||
| 50 | #include <linux/miscdevice.h> | 50 | #include <linux/miscdevice.h> |
| 51 | #endif | 51 | #endif |
| 52 | 52 | ||
| 53 | 53 | #ifndef MPT2SAS_MINOR | |
| 54 | #define MPT2SAS_MINOR (MPT_MINOR + 1) | ||
| 55 | #endif | ||
| 54 | #ifndef MPT3SAS_MINOR | 56 | #ifndef MPT3SAS_MINOR |
| 55 | #define MPT3SAS_MINOR (MPT_MINOR + 2) | 57 | #define MPT3SAS_MINOR (MPT_MINOR + 2) |
| 56 | #endif | 58 | #endif |
| 59 | #define MPT2SAS_DEV_NAME "mpt2ctl" | ||
| 57 | #define MPT3SAS_DEV_NAME "mpt3ctl" | 60 | #define MPT3SAS_DEV_NAME "mpt3ctl" |
| 58 | #define MPT3_MAGIC_NUMBER 'L' | 61 | #define MPT3_MAGIC_NUMBER 'L' |
| 59 | #define MPT3_IOCTL_DEFAULT_TIMEOUT (10) /* in seconds */ | 62 | #define MPT3_IOCTL_DEFAULT_TIMEOUT (10) /* in seconds */ |
| @@ -138,6 +141,7 @@ struct mpt3_ioctl_pci_info { | |||
| 138 | #define MPT2_IOCTL_INTERFACE_FC_IP (0x02) | 141 | #define MPT2_IOCTL_INTERFACE_FC_IP (0x02) |
| 139 | #define MPT2_IOCTL_INTERFACE_SAS (0x03) | 142 | #define MPT2_IOCTL_INTERFACE_SAS (0x03) |
| 140 | #define MPT2_IOCTL_INTERFACE_SAS2 (0x04) | 143 | #define MPT2_IOCTL_INTERFACE_SAS2 (0x04) |
| 144 | #define MPT2_IOCTL_INTERFACE_SAS2_SSS6200 (0x05) | ||
| 141 | #define MPT3_IOCTL_INTERFACE_SAS3 (0x06) | 145 | #define MPT3_IOCTL_INTERFACE_SAS3 (0x06) |
| 142 | #define MPT2_IOCTL_VERSION_LENGTH (32) | 146 | #define MPT2_IOCTL_VERSION_LENGTH (32) |
| 143 | 147 | ||
diff --git a/drivers/scsi/mpt3sas/mpt3sas_debug.h b/drivers/scsi/mpt3sas/mpt3sas_debug.h index 4e8a63fdb304..cceeb2c16e64 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_debug.h +++ b/drivers/scsi/mpt3sas/mpt3sas_debug.h | |||
| @@ -68,20 +68,11 @@ | |||
| 68 | #define MPT_DEBUG_TRIGGER_DIAG 0x00200000 | 68 | #define MPT_DEBUG_TRIGGER_DIAG 0x00200000 |
| 69 | 69 | ||
| 70 | 70 | ||
| 71 | /* | ||
| 72 | * CONFIG_SCSI_MPT3SAS_LOGGING - enabled in Kconfig | ||
| 73 | */ | ||
| 74 | |||
| 75 | #ifdef CONFIG_SCSI_MPT3SAS_LOGGING | ||
| 76 | #define MPT_CHECK_LOGGING(IOC, CMD, BITS) \ | 71 | #define MPT_CHECK_LOGGING(IOC, CMD, BITS) \ |
| 77 | { \ | 72 | { \ |
| 78 | if (IOC->logging_level & BITS) \ | 73 | if (IOC->logging_level & BITS) \ |
| 79 | CMD; \ | 74 | CMD; \ |
| 80 | } | 75 | } |
| 81 | #else | ||
| 82 | #define MPT_CHECK_LOGGING(IOC, CMD, BITS) | ||
| 83 | #endif /* CONFIG_SCSI_MPT3SAS_LOGGING */ | ||
| 84 | |||
| 85 | 76 | ||
| 86 | /* | 77 | /* |
| 87 | * debug macros | 78 | * debug macros |
| @@ -153,7 +144,7 @@ | |||
| 153 | 144 | ||
| 154 | 145 | ||
| 155 | /* inline functions for dumping debug data*/ | 146 | /* inline functions for dumping debug data*/ |
| 156 | #ifdef CONFIG_SCSI_MPT3SAS_LOGGING | 147 | |
| 157 | /** | 148 | /** |
| 158 | * _debug_dump_mf - print message frame contents | 149 | * _debug_dump_mf - print message frame contents |
| 159 | * @mpi_request: pointer to message frame | 150 | * @mpi_request: pointer to message frame |
| @@ -211,10 +202,5 @@ _debug_dump_config(void *mpi_request, int sz) | |||
| 211 | } | 202 | } |
| 212 | pr_info("\n"); | 203 | pr_info("\n"); |
| 213 | } | 204 | } |
| 214 | #else | ||
| 215 | #define _debug_dump_mf(mpi_request, sz) | ||
| 216 | #define _debug_dump_reply(mpi_request, sz) | ||
| 217 | #define _debug_dump_config(mpi_request, sz) | ||
| 218 | #endif /* CONFIG_SCSI_MPT3SAS_LOGGING */ | ||
| 219 | 205 | ||
| 220 | #endif /* MPT3SAS_DEBUG_H_INCLUDED */ | 206 | #endif /* MPT3SAS_DEBUG_H_INCLUDED */ |
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 8ccef38523fa..d95206b7e116 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c | |||
| @@ -54,14 +54,10 @@ | |||
| 54 | #include <linux/interrupt.h> | 54 | #include <linux/interrupt.h> |
| 55 | #include <linux/aer.h> | 55 | #include <linux/aer.h> |
| 56 | #include <linux/raid_class.h> | 56 | #include <linux/raid_class.h> |
| 57 | #include <asm/unaligned.h> | ||
| 57 | 58 | ||
| 58 | #include "mpt3sas_base.h" | 59 | #include "mpt3sas_base.h" |
| 59 | 60 | ||
| 60 | MODULE_AUTHOR(MPT3SAS_AUTHOR); | ||
| 61 | MODULE_DESCRIPTION(MPT3SAS_DESCRIPTION); | ||
| 62 | MODULE_LICENSE("GPL"); | ||
| 63 | MODULE_VERSION(MPT3SAS_DRIVER_VERSION); | ||
| 64 | |||
| 65 | #define RAID_CHANNEL 1 | 61 | #define RAID_CHANNEL 1 |
| 66 | /* forward proto's */ | 62 | /* forward proto's */ |
| 67 | static void _scsih_expander_node_remove(struct MPT3SAS_ADAPTER *ioc, | 63 | static void _scsih_expander_node_remove(struct MPT3SAS_ADAPTER *ioc, |
| @@ -75,11 +71,16 @@ static int _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, | |||
| 75 | 71 | ||
| 76 | static u8 _scsih_check_for_pending_tm(struct MPT3SAS_ADAPTER *ioc, u16 smid); | 72 | static u8 _scsih_check_for_pending_tm(struct MPT3SAS_ADAPTER *ioc, u16 smid); |
| 77 | 73 | ||
| 78 | static void _scsih_scan_start(struct Scsi_Host *shost); | ||
| 79 | static int _scsih_scan_finished(struct Scsi_Host *shost, unsigned long time); | ||
| 80 | |||
| 81 | /* global parameters */ | 74 | /* global parameters */ |
| 82 | LIST_HEAD(mpt3sas_ioc_list); | 75 | LIST_HEAD(mpt3sas_ioc_list); |
| 76 | /* global ioc lock for list operations */ | ||
| 77 | DEFINE_SPINLOCK(gioc_lock); | ||
| 78 | |||
| 79 | MODULE_AUTHOR(MPT3SAS_AUTHOR); | ||
| 80 | MODULE_DESCRIPTION(MPT3SAS_DESCRIPTION); | ||
| 81 | MODULE_LICENSE("GPL"); | ||
| 82 | MODULE_VERSION(MPT3SAS_DRIVER_VERSION); | ||
| 83 | MODULE_ALIAS("mpt2sas"); | ||
| 83 | 84 | ||
| 84 | /* local parameters */ | 85 | /* local parameters */ |
| 85 | static u8 scsi_io_cb_idx = -1; | 86 | static u8 scsi_io_cb_idx = -1; |
| @@ -90,7 +91,8 @@ static u8 port_enable_cb_idx = -1; | |||
| 90 | static u8 transport_cb_idx = -1; | 91 | static u8 transport_cb_idx = -1; |
| 91 | static u8 scsih_cb_idx = -1; | 92 | static u8 scsih_cb_idx = -1; |
| 92 | static u8 config_cb_idx = -1; | 93 | static u8 config_cb_idx = -1; |
| 93 | static int mpt_ids; | 94 | static int mpt2_ids; |
| 95 | static int mpt3_ids; | ||
| 94 | 96 | ||
| 95 | static u8 tm_tr_cb_idx = -1 ; | 97 | static u8 tm_tr_cb_idx = -1 ; |
| 96 | static u8 tm_tr_volume_cb_idx = -1 ; | 98 | static u8 tm_tr_volume_cb_idx = -1 ; |
| @@ -117,8 +119,12 @@ static u64 max_lun = MPT3SAS_MAX_LUN; | |||
| 117 | module_param(max_lun, ullong, 0); | 119 | module_param(max_lun, ullong, 0); |
| 118 | MODULE_PARM_DESC(max_lun, " max lun, default=16895 "); | 120 | MODULE_PARM_DESC(max_lun, " max lun, default=16895 "); |
| 119 | 121 | ||
| 120 | 122 | static ushort hbas_to_enumerate; | |
| 121 | 123 | module_param(hbas_to_enumerate, ushort, 0); | |
| 124 | MODULE_PARM_DESC(hbas_to_enumerate, | ||
| 125 | " 0 - enumerates both SAS 2.0 & SAS 3.0 generation HBAs\n \ | ||
| 126 | 1 - enumerates only SAS 2.0 generation HBAs\n \ | ||
| 127 | 2 - enumerates only SAS 3.0 generation HBAs (default=0)"); | ||
| 122 | 128 | ||
| 123 | /* diag_buffer_enable is bitwise | 129 | /* diag_buffer_enable is bitwise |
| 124 | * bit 0 set = TRACE | 130 | * bit 0 set = TRACE |
| @@ -143,8 +149,8 @@ MODULE_PARM_DESC(prot_mask, " host protection capabilities mask, def=7 "); | |||
| 143 | 149 | ||
| 144 | 150 | ||
| 145 | /* raid transport support */ | 151 | /* raid transport support */ |
| 146 | 152 | struct raid_template *mpt3sas_raid_template; | |
| 147 | static struct raid_template *mpt3sas_raid_template; | 153 | struct raid_template *mpt2sas_raid_template; |
| 148 | 154 | ||
| 149 | 155 | ||
| 150 | /** | 156 | /** |
| @@ -191,11 +197,36 @@ struct fw_event_work { | |||
| 191 | u8 VP_ID; | 197 | u8 VP_ID; |
| 192 | u8 ignore; | 198 | u8 ignore; |
| 193 | u16 event; | 199 | u16 event; |
| 200 | struct kref refcount; | ||
| 194 | char event_data[0] __aligned(4); | 201 | char event_data[0] __aligned(4); |
| 195 | }; | 202 | }; |
| 196 | 203 | ||
| 197 | /* raid transport support */ | 204 | static void fw_event_work_free(struct kref *r) |
| 198 | static struct raid_template *mpt3sas_raid_template; | 205 | { |
| 206 | kfree(container_of(r, struct fw_event_work, refcount)); | ||
| 207 | } | ||
| 208 | |||
| 209 | static void fw_event_work_get(struct fw_event_work *fw_work) | ||
| 210 | { | ||
| 211 | kref_get(&fw_work->refcount); | ||
| 212 | } | ||
| 213 | |||
| 214 | static void fw_event_work_put(struct fw_event_work *fw_work) | ||
| 215 | { | ||
| 216 | kref_put(&fw_work->refcount, fw_event_work_free); | ||
| 217 | } | ||
| 218 | |||
| 219 | static struct fw_event_work *alloc_fw_event_work(int len) | ||
| 220 | { | ||
| 221 | struct fw_event_work *fw_event; | ||
| 222 | |||
| 223 | fw_event = kzalloc(sizeof(*fw_event) + len, GFP_ATOMIC); | ||
| 224 | if (!fw_event) | ||
| 225 | return NULL; | ||
| 226 | |||
| 227 | kref_init(&fw_event->refcount); | ||
| 228 | return fw_event; | ||
| 229 | } | ||
| 199 | 230 | ||
| 200 | /** | 231 | /** |
| 201 | * struct _scsi_io_transfer - scsi io transfer | 232 | * struct _scsi_io_transfer - scsi io transfer |
| @@ -245,28 +276,6 @@ struct _scsi_io_transfer { | |||
| 245 | u32 transfer_length; | 276 | u32 transfer_length; |
| 246 | }; | 277 | }; |
| 247 | 278 | ||
| 248 | /* | ||
| 249 | * The pci device ids are defined in mpi/mpi2_cnfg.h. | ||
| 250 | */ | ||
| 251 | static const struct pci_device_id scsih_pci_table[] = { | ||
| 252 | /* Fury ~ 3004 and 3008 */ | ||
| 253 | { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3004, | ||
| 254 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 255 | { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3008, | ||
| 256 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 257 | /* Invader ~ 3108 */ | ||
| 258 | { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_1, | ||
| 259 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 260 | { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_2, | ||
| 261 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 262 | { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_5, | ||
| 263 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 264 | { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_6, | ||
| 265 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 266 | {0} /* Terminating entry */ | ||
| 267 | }; | ||
| 268 | MODULE_DEVICE_TABLE(pci, scsih_pci_table); | ||
| 269 | |||
| 270 | /** | 279 | /** |
| 271 | * _scsih_set_debug_level - global setting of ioc->logging_level. | 280 | * _scsih_set_debug_level - global setting of ioc->logging_level. |
| 272 | * | 281 | * |
| @@ -282,8 +291,10 @@ _scsih_set_debug_level(const char *val, struct kernel_param *kp) | |||
| 282 | return ret; | 291 | return ret; |
| 283 | 292 | ||
| 284 | pr_info("setting logging_level(0x%08x)\n", logging_level); | 293 | pr_info("setting logging_level(0x%08x)\n", logging_level); |
| 294 | spin_lock(&gioc_lock); | ||
| 285 | list_for_each_entry(ioc, &mpt3sas_ioc_list, list) | 295 | list_for_each_entry(ioc, &mpt3sas_ioc_list, list) |
| 286 | ioc->logging_level = logging_level; | 296 | ioc->logging_level = logging_level; |
| 297 | spin_unlock(&gioc_lock); | ||
| 287 | return 0; | 298 | return 0; |
| 288 | } | 299 | } |
| 289 | module_param_call(logging_level, _scsih_set_debug_level, param_get_int, | 300 | module_param_call(logging_level, _scsih_set_debug_level, param_get_int, |
| @@ -518,8 +529,61 @@ _scsih_determine_boot_device(struct MPT3SAS_ADAPTER *ioc, | |||
| 518 | } | 529 | } |
| 519 | } | 530 | } |
| 520 | 531 | ||
| 532 | static struct _sas_device * | ||
| 533 | __mpt3sas_get_sdev_from_target(struct MPT3SAS_ADAPTER *ioc, | ||
| 534 | struct MPT3SAS_TARGET *tgt_priv) | ||
| 535 | { | ||
| 536 | struct _sas_device *ret; | ||
| 537 | |||
| 538 | assert_spin_locked(&ioc->sas_device_lock); | ||
| 539 | |||
| 540 | ret = tgt_priv->sdev; | ||
| 541 | if (ret) | ||
| 542 | sas_device_get(ret); | ||
| 543 | |||
| 544 | return ret; | ||
| 545 | } | ||
| 546 | |||
| 547 | static struct _sas_device * | ||
| 548 | mpt3sas_get_sdev_from_target(struct MPT3SAS_ADAPTER *ioc, | ||
| 549 | struct MPT3SAS_TARGET *tgt_priv) | ||
| 550 | { | ||
| 551 | struct _sas_device *ret; | ||
| 552 | unsigned long flags; | ||
| 553 | |||
| 554 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 555 | ret = __mpt3sas_get_sdev_from_target(ioc, tgt_priv); | ||
| 556 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 557 | |||
| 558 | return ret; | ||
| 559 | } | ||
| 560 | |||
| 561 | |||
| 562 | struct _sas_device * | ||
| 563 | __mpt3sas_get_sdev_by_addr(struct MPT3SAS_ADAPTER *ioc, | ||
| 564 | u64 sas_address) | ||
| 565 | { | ||
| 566 | struct _sas_device *sas_device; | ||
| 567 | |||
| 568 | assert_spin_locked(&ioc->sas_device_lock); | ||
| 569 | |||
| 570 | list_for_each_entry(sas_device, &ioc->sas_device_list, list) | ||
| 571 | if (sas_device->sas_address == sas_address) | ||
| 572 | goto found_device; | ||
| 573 | |||
| 574 | list_for_each_entry(sas_device, &ioc->sas_device_init_list, list) | ||
| 575 | if (sas_device->sas_address == sas_address) | ||
| 576 | goto found_device; | ||
| 577 | |||
| 578 | return NULL; | ||
| 579 | |||
| 580 | found_device: | ||
| 581 | sas_device_get(sas_device); | ||
| 582 | return sas_device; | ||
| 583 | } | ||
| 584 | |||
| 521 | /** | 585 | /** |
| 522 | * mpt3sas_scsih_sas_device_find_by_sas_address - sas device search | 586 | * mpt3sas_get_sdev_by_addr - sas device search |
| 523 | * @ioc: per adapter object | 587 | * @ioc: per adapter object |
| 524 | * @sas_address: sas address | 588 | * @sas_address: sas address |
| 525 | * Context: Calling function should acquire ioc->sas_device_lock | 589 | * Context: Calling function should acquire ioc->sas_device_lock |
| @@ -528,24 +592,44 @@ _scsih_determine_boot_device(struct MPT3SAS_ADAPTER *ioc, | |||
| 528 | * object. | 592 | * object. |
| 529 | */ | 593 | */ |
| 530 | struct _sas_device * | 594 | struct _sas_device * |
| 531 | mpt3sas_scsih_sas_device_find_by_sas_address(struct MPT3SAS_ADAPTER *ioc, | 595 | mpt3sas_get_sdev_by_addr(struct MPT3SAS_ADAPTER *ioc, |
| 532 | u64 sas_address) | 596 | u64 sas_address) |
| 533 | { | 597 | { |
| 534 | struct _sas_device *sas_device; | 598 | struct _sas_device *sas_device; |
| 599 | unsigned long flags; | ||
| 600 | |||
| 601 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 602 | sas_device = __mpt3sas_get_sdev_by_addr(ioc, | ||
| 603 | sas_address); | ||
| 604 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 605 | |||
| 606 | return sas_device; | ||
| 607 | } | ||
| 608 | |||
| 609 | static struct _sas_device * | ||
| 610 | __mpt3sas_get_sdev_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle) | ||
| 611 | { | ||
| 612 | struct _sas_device *sas_device; | ||
| 613 | |||
| 614 | assert_spin_locked(&ioc->sas_device_lock); | ||
| 535 | 615 | ||
| 536 | list_for_each_entry(sas_device, &ioc->sas_device_list, list) | 616 | list_for_each_entry(sas_device, &ioc->sas_device_list, list) |
| 537 | if (sas_device->sas_address == sas_address) | 617 | if (sas_device->handle == handle) |
| 538 | return sas_device; | 618 | goto found_device; |
| 539 | 619 | ||
| 540 | list_for_each_entry(sas_device, &ioc->sas_device_init_list, list) | 620 | list_for_each_entry(sas_device, &ioc->sas_device_init_list, list) |
| 541 | if (sas_device->sas_address == sas_address) | 621 | if (sas_device->handle == handle) |
| 542 | return sas_device; | 622 | goto found_device; |
| 543 | 623 | ||
| 544 | return NULL; | 624 | return NULL; |
| 625 | |||
| 626 | found_device: | ||
| 627 | sas_device_get(sas_device); | ||
| 628 | return sas_device; | ||
| 545 | } | 629 | } |
| 546 | 630 | ||
| 547 | /** | 631 | /** |
| 548 | * _scsih_sas_device_find_by_handle - sas device search | 632 | * mpt3sas_get_sdev_by_handle - sas device search |
| 549 | * @ioc: per adapter object | 633 | * @ioc: per adapter object |
| 550 | * @handle: sas device handle (assigned by firmware) | 634 | * @handle: sas device handle (assigned by firmware) |
| 551 | * Context: Calling function should acquire ioc->sas_device_lock | 635 | * Context: Calling function should acquire ioc->sas_device_lock |
| @@ -554,19 +638,16 @@ mpt3sas_scsih_sas_device_find_by_sas_address(struct MPT3SAS_ADAPTER *ioc, | |||
| 554 | * object. | 638 | * object. |
| 555 | */ | 639 | */ |
| 556 | static struct _sas_device * | 640 | static struct _sas_device * |
| 557 | _scsih_sas_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle) | 641 | mpt3sas_get_sdev_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle) |
| 558 | { | 642 | { |
| 559 | struct _sas_device *sas_device; | 643 | struct _sas_device *sas_device; |
| 644 | unsigned long flags; | ||
| 560 | 645 | ||
| 561 | list_for_each_entry(sas_device, &ioc->sas_device_list, list) | 646 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 562 | if (sas_device->handle == handle) | 647 | sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle); |
| 563 | return sas_device; | 648 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 564 | |||
| 565 | list_for_each_entry(sas_device, &ioc->sas_device_init_list, list) | ||
| 566 | if (sas_device->handle == handle) | ||
| 567 | return sas_device; | ||
| 568 | 649 | ||
| 569 | return NULL; | 650 | return sas_device; |
| 570 | } | 651 | } |
| 571 | 652 | ||
| 572 | /** | 653 | /** |
| @@ -575,7 +656,7 @@ _scsih_sas_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle) | |||
| 575 | * @sas_device: the sas_device object | 656 | * @sas_device: the sas_device object |
| 576 | * Context: This function will acquire ioc->sas_device_lock. | 657 | * Context: This function will acquire ioc->sas_device_lock. |
| 577 | * | 658 | * |
| 578 | * Removing object and freeing associated memory from the ioc->sas_device_list. | 659 | * If sas_device is on the list, remove it and decrement its reference count. |
| 579 | */ | 660 | */ |
| 580 | static void | 661 | static void |
| 581 | _scsih_sas_device_remove(struct MPT3SAS_ADAPTER *ioc, | 662 | _scsih_sas_device_remove(struct MPT3SAS_ADAPTER *ioc, |
| @@ -602,9 +683,15 @@ _scsih_sas_device_remove(struct MPT3SAS_ADAPTER *ioc, | |||
| 602 | ioc->name, sas_device->enclosure_level, | 683 | ioc->name, sas_device->enclosure_level, |
| 603 | sas_device->connector_name); | 684 | sas_device->connector_name); |
| 604 | 685 | ||
| 686 | /* | ||
| 687 | * The lock serializes access to the list, but we still need to verify | ||
| 688 | * that nobody removed the entry while we were waiting on the lock. | ||
| 689 | */ | ||
| 605 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 690 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 606 | list_del(&sas_device->list); | 691 | if (!list_empty(&sas_device->list)) { |
| 607 | kfree(sas_device); | 692 | list_del_init(&sas_device->list); |
| 693 | sas_device_put(sas_device); | ||
| 694 | } | ||
| 608 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 695 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 609 | } | 696 | } |
| 610 | 697 | ||
| @@ -625,12 +712,16 @@ _scsih_device_remove_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle) | |||
| 625 | return; | 712 | return; |
| 626 | 713 | ||
| 627 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 714 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 628 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | 715 | sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle); |
| 629 | if (sas_device) | 716 | if (sas_device) { |
| 630 | list_del(&sas_device->list); | 717 | list_del_init(&sas_device->list); |
| 718 | sas_device_put(sas_device); | ||
| 719 | } | ||
| 631 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 720 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 632 | if (sas_device) | 721 | if (sas_device) { |
| 633 | _scsih_remove_device(ioc, sas_device); | 722 | _scsih_remove_device(ioc, sas_device); |
| 723 | sas_device_put(sas_device); | ||
| 724 | } | ||
| 634 | } | 725 | } |
| 635 | 726 | ||
| 636 | /** | 727 | /** |
| @@ -651,13 +742,16 @@ mpt3sas_device_remove_by_sas_address(struct MPT3SAS_ADAPTER *ioc, | |||
| 651 | return; | 742 | return; |
| 652 | 743 | ||
| 653 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 744 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 654 | sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc, | 745 | sas_device = __mpt3sas_get_sdev_by_addr(ioc, sas_address); |
| 655 | sas_address); | 746 | if (sas_device) { |
| 656 | if (sas_device) | 747 | list_del_init(&sas_device->list); |
| 657 | list_del(&sas_device->list); | 748 | sas_device_put(sas_device); |
| 749 | } | ||
| 658 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 750 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 659 | if (sas_device) | 751 | if (sas_device) { |
| 660 | _scsih_remove_device(ioc, sas_device); | 752 | _scsih_remove_device(ioc, sas_device); |
| 753 | sas_device_put(sas_device); | ||
| 754 | } | ||
| 661 | } | 755 | } |
| 662 | 756 | ||
| 663 | /** | 757 | /** |
| @@ -692,6 +786,7 @@ _scsih_sas_device_add(struct MPT3SAS_ADAPTER *ioc, | |||
| 692 | sas_device->enclosure_level, sas_device->connector_name)); | 786 | sas_device->enclosure_level, sas_device->connector_name)); |
| 693 | 787 | ||
| 694 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 788 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 789 | sas_device_get(sas_device); | ||
| 695 | list_add_tail(&sas_device->list, &ioc->sas_device_list); | 790 | list_add_tail(&sas_device->list, &ioc->sas_device_list); |
| 696 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 791 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 697 | 792 | ||
| @@ -745,6 +840,7 @@ _scsih_sas_device_init_add(struct MPT3SAS_ADAPTER *ioc, | |||
| 745 | sas_device->connector_name)); | 840 | sas_device->connector_name)); |
| 746 | 841 | ||
| 747 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 842 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 843 | sas_device_get(sas_device); | ||
| 748 | list_add_tail(&sas_device->list, &ioc->sas_device_init_list); | 844 | list_add_tail(&sas_device->list, &ioc->sas_device_init_list); |
| 749 | _scsih_determine_boot_device(ioc, sas_device, 0); | 845 | _scsih_determine_boot_device(ioc, sas_device, 0); |
| 750 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 846 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| @@ -778,7 +874,7 @@ _scsih_raid_device_find_by_id(struct MPT3SAS_ADAPTER *ioc, int id, int channel) | |||
| 778 | } | 874 | } |
| 779 | 875 | ||
| 780 | /** | 876 | /** |
| 781 | * _scsih_raid_device_find_by_handle - raid device search | 877 | * mpt3sas_raid_device_find_by_handle - raid device search |
| 782 | * @ioc: per adapter object | 878 | * @ioc: per adapter object |
| 783 | * @handle: sas device handle (assigned by firmware) | 879 | * @handle: sas device handle (assigned by firmware) |
| 784 | * Context: Calling function should acquire ioc->raid_device_lock | 880 | * Context: Calling function should acquire ioc->raid_device_lock |
| @@ -786,8 +882,8 @@ _scsih_raid_device_find_by_id(struct MPT3SAS_ADAPTER *ioc, int id, int channel) | |||
| 786 | * This searches for raid_device based on handle, then return raid_device | 882 | * This searches for raid_device based on handle, then return raid_device |
| 787 | * object. | 883 | * object. |
| 788 | */ | 884 | */ |
| 789 | static struct _raid_device * | 885 | struct _raid_device * |
| 790 | _scsih_raid_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle) | 886 | mpt3sas_raid_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle) |
| 791 | { | 887 | { |
| 792 | struct _raid_device *raid_device, *r; | 888 | struct _raid_device *raid_device, *r; |
| 793 | 889 | ||
| @@ -1095,14 +1191,14 @@ _scsih_scsi_lookup_find_by_lun(struct MPT3SAS_ADAPTER *ioc, int id, | |||
| 1095 | } | 1191 | } |
| 1096 | 1192 | ||
| 1097 | /** | 1193 | /** |
| 1098 | * _scsih_change_queue_depth - setting device queue depth | 1194 | * scsih_change_queue_depth - setting device queue depth |
| 1099 | * @sdev: scsi device struct | 1195 | * @sdev: scsi device struct |
| 1100 | * @qdepth: requested queue depth | 1196 | * @qdepth: requested queue depth |
| 1101 | * | 1197 | * |
| 1102 | * Returns queue depth. | 1198 | * Returns queue depth. |
| 1103 | */ | 1199 | */ |
| 1104 | static int | 1200 | int |
| 1105 | _scsih_change_queue_depth(struct scsi_device *sdev, int qdepth) | 1201 | scsih_change_queue_depth(struct scsi_device *sdev, int qdepth) |
| 1106 | { | 1202 | { |
| 1107 | struct Scsi_Host *shost = sdev->host; | 1203 | struct Scsi_Host *shost = sdev->host; |
| 1108 | int max_depth; | 1204 | int max_depth; |
| @@ -1123,12 +1219,15 @@ _scsih_change_queue_depth(struct scsi_device *sdev, int qdepth) | |||
| 1123 | goto not_sata; | 1219 | goto not_sata; |
| 1124 | if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) | 1220 | if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) |
| 1125 | goto not_sata; | 1221 | goto not_sata; |
| 1222 | |||
| 1126 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 1223 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 1127 | sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc, | 1224 | sas_device = __mpt3sas_get_sdev_from_target(ioc, sas_target_priv_data); |
| 1128 | sas_device_priv_data->sas_target->sas_address); | 1225 | if (sas_device) { |
| 1129 | if (sas_device && sas_device->device_info & | 1226 | if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) |
| 1130 | MPI2_SAS_DEVICE_INFO_SATA_DEVICE) | 1227 | max_depth = MPT3SAS_SATA_QUEUE_DEPTH; |
| 1131 | max_depth = MPT3SAS_SATA_QUEUE_DEPTH; | 1228 | |
| 1229 | sas_device_put(sas_device); | ||
| 1230 | } | ||
| 1132 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 1231 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 1133 | 1232 | ||
| 1134 | not_sata: | 1233 | not_sata: |
| @@ -1141,14 +1240,14 @@ _scsih_change_queue_depth(struct scsi_device *sdev, int qdepth) | |||
| 1141 | } | 1240 | } |
| 1142 | 1241 | ||
| 1143 | /** | 1242 | /** |
| 1144 | * _scsih_target_alloc - target add routine | 1243 | * scsih_target_alloc - target add routine |
| 1145 | * @starget: scsi target struct | 1244 | * @starget: scsi target struct |
| 1146 | * | 1245 | * |
| 1147 | * Returns 0 if ok. Any other return is assumed to be an error and | 1246 | * Returns 0 if ok. Any other return is assumed to be an error and |
| 1148 | * the device is ignored. | 1247 | * the device is ignored. |
| 1149 | */ | 1248 | */ |
| 1150 | static int | 1249 | int |
| 1151 | _scsih_target_alloc(struct scsi_target *starget) | 1250 | scsih_target_alloc(struct scsi_target *starget) |
| 1152 | { | 1251 | { |
| 1153 | struct Scsi_Host *shost = dev_to_shost(&starget->dev); | 1252 | struct Scsi_Host *shost = dev_to_shost(&starget->dev); |
| 1154 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); | 1253 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); |
| @@ -1176,7 +1275,9 @@ _scsih_target_alloc(struct scsi_target *starget) | |||
| 1176 | sas_target_priv_data->handle = raid_device->handle; | 1275 | sas_target_priv_data->handle = raid_device->handle; |
| 1177 | sas_target_priv_data->sas_address = raid_device->wwid; | 1276 | sas_target_priv_data->sas_address = raid_device->wwid; |
| 1178 | sas_target_priv_data->flags |= MPT_TARGET_FLAGS_VOLUME; | 1277 | sas_target_priv_data->flags |= MPT_TARGET_FLAGS_VOLUME; |
| 1179 | raid_device->starget = starget; | 1278 | sas_target_priv_data->raid_device = raid_device; |
| 1279 | if (ioc->is_warpdrive) | ||
| 1280 | raid_device->starget = starget; | ||
| 1180 | } | 1281 | } |
| 1181 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); | 1282 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); |
| 1182 | return 0; | 1283 | return 0; |
| @@ -1185,12 +1286,13 @@ _scsih_target_alloc(struct scsi_target *starget) | |||
| 1185 | /* sas/sata devices */ | 1286 | /* sas/sata devices */ |
| 1186 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 1287 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 1187 | rphy = dev_to_rphy(starget->dev.parent); | 1288 | rphy = dev_to_rphy(starget->dev.parent); |
| 1188 | sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc, | 1289 | sas_device = __mpt3sas_get_sdev_by_addr(ioc, |
| 1189 | rphy->identify.sas_address); | 1290 | rphy->identify.sas_address); |
| 1190 | 1291 | ||
| 1191 | if (sas_device) { | 1292 | if (sas_device) { |
| 1192 | sas_target_priv_data->handle = sas_device->handle; | 1293 | sas_target_priv_data->handle = sas_device->handle; |
| 1193 | sas_target_priv_data->sas_address = sas_device->sas_address; | 1294 | sas_target_priv_data->sas_address = sas_device->sas_address; |
| 1295 | sas_target_priv_data->sdev = sas_device; | ||
| 1194 | sas_device->starget = starget; | 1296 | sas_device->starget = starget; |
| 1195 | sas_device->id = starget->id; | 1297 | sas_device->id = starget->id; |
| 1196 | sas_device->channel = starget->channel; | 1298 | sas_device->channel = starget->channel; |
| @@ -1206,13 +1308,13 @@ _scsih_target_alloc(struct scsi_target *starget) | |||
| 1206 | } | 1308 | } |
| 1207 | 1309 | ||
| 1208 | /** | 1310 | /** |
| 1209 | * _scsih_target_destroy - target destroy routine | 1311 | * scsih_target_destroy - target destroy routine |
| 1210 | * @starget: scsi target struct | 1312 | * @starget: scsi target struct |
| 1211 | * | 1313 | * |
| 1212 | * Returns nothing. | 1314 | * Returns nothing. |
| 1213 | */ | 1315 | */ |
| 1214 | static void | 1316 | void |
| 1215 | _scsih_target_destroy(struct scsi_target *starget) | 1317 | scsih_target_destroy(struct scsi_target *starget) |
| 1216 | { | 1318 | { |
| 1217 | struct Scsi_Host *shost = dev_to_shost(&starget->dev); | 1319 | struct Scsi_Host *shost = dev_to_shost(&starget->dev); |
| 1218 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); | 1320 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); |
| @@ -1240,13 +1342,21 @@ _scsih_target_destroy(struct scsi_target *starget) | |||
| 1240 | 1342 | ||
| 1241 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 1343 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 1242 | rphy = dev_to_rphy(starget->dev.parent); | 1344 | rphy = dev_to_rphy(starget->dev.parent); |
| 1243 | sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc, | 1345 | sas_device = __mpt3sas_get_sdev_from_target(ioc, sas_target_priv_data); |
| 1244 | rphy->identify.sas_address); | ||
| 1245 | if (sas_device && (sas_device->starget == starget) && | 1346 | if (sas_device && (sas_device->starget == starget) && |
| 1246 | (sas_device->id == starget->id) && | 1347 | (sas_device->id == starget->id) && |
| 1247 | (sas_device->channel == starget->channel)) | 1348 | (sas_device->channel == starget->channel)) |
| 1248 | sas_device->starget = NULL; | 1349 | sas_device->starget = NULL; |
| 1249 | 1350 | ||
| 1351 | if (sas_device) { | ||
| 1352 | /* | ||
| 1353 | * Corresponding get() is in _scsih_target_alloc() | ||
| 1354 | */ | ||
| 1355 | sas_target_priv_data->sdev = NULL; | ||
| 1356 | sas_device_put(sas_device); | ||
| 1357 | |||
| 1358 | sas_device_put(sas_device); | ||
| 1359 | } | ||
| 1250 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 1360 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 1251 | 1361 | ||
| 1252 | out: | 1362 | out: |
| @@ -1255,14 +1365,14 @@ _scsih_target_destroy(struct scsi_target *starget) | |||
| 1255 | } | 1365 | } |
| 1256 | 1366 | ||
| 1257 | /** | 1367 | /** |
| 1258 | * _scsih_slave_alloc - device add routine | 1368 | * scsih_slave_alloc - device add routine |
| 1259 | * @sdev: scsi device struct | 1369 | * @sdev: scsi device struct |
| 1260 | * | 1370 | * |
| 1261 | * Returns 0 if ok. Any other return is assumed to be an error and | 1371 | * Returns 0 if ok. Any other return is assumed to be an error and |
| 1262 | * the device is ignored. | 1372 | * the device is ignored. |
| 1263 | */ | 1373 | */ |
| 1264 | static int | 1374 | int |
| 1265 | _scsih_slave_alloc(struct scsi_device *sdev) | 1375 | scsih_slave_alloc(struct scsi_device *sdev) |
| 1266 | { | 1376 | { |
| 1267 | struct Scsi_Host *shost; | 1377 | struct Scsi_Host *shost; |
| 1268 | struct MPT3SAS_ADAPTER *ioc; | 1378 | struct MPT3SAS_ADAPTER *ioc; |
| @@ -1302,14 +1412,18 @@ _scsih_slave_alloc(struct scsi_device *sdev) | |||
| 1302 | 1412 | ||
| 1303 | if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) { | 1413 | if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) { |
| 1304 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 1414 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 1305 | sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc, | 1415 | sas_device = __mpt3sas_get_sdev_by_addr(ioc, |
| 1306 | sas_target_priv_data->sas_address); | 1416 | sas_target_priv_data->sas_address); |
| 1307 | if (sas_device && (sas_device->starget == NULL)) { | 1417 | if (sas_device && (sas_device->starget == NULL)) { |
| 1308 | sdev_printk(KERN_INFO, sdev, | 1418 | sdev_printk(KERN_INFO, sdev, |
| 1309 | "%s : sas_device->starget set to starget @ %d\n", | 1419 | "%s : sas_device->starget set to starget @ %d\n", |
| 1310 | __func__, __LINE__); | 1420 | __func__, __LINE__); |
| 1311 | sas_device->starget = starget; | 1421 | sas_device->starget = starget; |
| 1312 | } | 1422 | } |
| 1423 | |||
| 1424 | if (sas_device) | ||
| 1425 | sas_device_put(sas_device); | ||
| 1426 | |||
| 1313 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 1427 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 1314 | } | 1428 | } |
| 1315 | 1429 | ||
| @@ -1317,13 +1431,13 @@ _scsih_slave_alloc(struct scsi_device *sdev) | |||
| 1317 | } | 1431 | } |
| 1318 | 1432 | ||
| 1319 | /** | 1433 | /** |
| 1320 | * _scsih_slave_destroy - device destroy routine | 1434 | * scsih_slave_destroy - device destroy routine |
| 1321 | * @sdev: scsi device struct | 1435 | * @sdev: scsi device struct |
| 1322 | * | 1436 | * |
| 1323 | * Returns nothing. | 1437 | * Returns nothing. |
| 1324 | */ | 1438 | */ |
| 1325 | static void | 1439 | void |
| 1326 | _scsih_slave_destroy(struct scsi_device *sdev) | 1440 | scsih_slave_destroy(struct scsi_device *sdev) |
| 1327 | { | 1441 | { |
| 1328 | struct MPT3SAS_TARGET *sas_target_priv_data; | 1442 | struct MPT3SAS_TARGET *sas_target_priv_data; |
| 1329 | struct scsi_target *starget; | 1443 | struct scsi_target *starget; |
| @@ -1344,10 +1458,13 @@ _scsih_slave_destroy(struct scsi_device *sdev) | |||
| 1344 | 1458 | ||
| 1345 | if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) { | 1459 | if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) { |
| 1346 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 1460 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 1347 | sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc, | 1461 | sas_device = __mpt3sas_get_sdev_from_target(ioc, |
| 1348 | sas_target_priv_data->sas_address); | 1462 | sas_target_priv_data); |
| 1349 | if (sas_device && !sas_target_priv_data->num_luns) | 1463 | if (sas_device && !sas_target_priv_data->num_luns) |
| 1350 | sas_device->starget = NULL; | 1464 | sas_device->starget = NULL; |
| 1465 | |||
| 1466 | if (sas_device) | ||
| 1467 | sas_device_put(sas_device); | ||
| 1351 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 1468 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 1352 | } | 1469 | } |
| 1353 | 1470 | ||
| @@ -1409,23 +1526,26 @@ _scsih_display_sata_capabilities(struct MPT3SAS_ADAPTER *ioc, | |||
| 1409 | */ | 1526 | */ |
| 1410 | 1527 | ||
| 1411 | /** | 1528 | /** |
| 1412 | * _scsih_is_raid - return boolean indicating device is raid volume | 1529 | * scsih_is_raid - return boolean indicating device is raid volume |
| 1413 | * @dev the device struct object | 1530 | * @dev the device struct object |
| 1414 | */ | 1531 | */ |
| 1415 | static int | 1532 | int |
| 1416 | _scsih_is_raid(struct device *dev) | 1533 | scsih_is_raid(struct device *dev) |
| 1417 | { | 1534 | { |
| 1418 | struct scsi_device *sdev = to_scsi_device(dev); | 1535 | struct scsi_device *sdev = to_scsi_device(dev); |
| 1536 | struct MPT3SAS_ADAPTER *ioc = shost_priv(sdev->host); | ||
| 1419 | 1537 | ||
| 1538 | if (ioc->is_warpdrive) | ||
| 1539 | return 0; | ||
| 1420 | return (sdev->channel == RAID_CHANNEL) ? 1 : 0; | 1540 | return (sdev->channel == RAID_CHANNEL) ? 1 : 0; |
| 1421 | } | 1541 | } |
| 1422 | 1542 | ||
| 1423 | /** | 1543 | /** |
| 1424 | * _scsih_get_resync - get raid volume resync percent complete | 1544 | * scsih_get_resync - get raid volume resync percent complete |
| 1425 | * @dev the device struct object | 1545 | * @dev the device struct object |
| 1426 | */ | 1546 | */ |
| 1427 | static void | 1547 | void |
| 1428 | _scsih_get_resync(struct device *dev) | 1548 | scsih_get_resync(struct device *dev) |
| 1429 | { | 1549 | { |
| 1430 | struct scsi_device *sdev = to_scsi_device(dev); | 1550 | struct scsi_device *sdev = to_scsi_device(dev); |
| 1431 | struct MPT3SAS_ADAPTER *ioc = shost_priv(sdev->host); | 1551 | struct MPT3SAS_ADAPTER *ioc = shost_priv(sdev->host); |
| @@ -1439,6 +1559,9 @@ _scsih_get_resync(struct device *dev) | |||
| 1439 | 1559 | ||
| 1440 | percent_complete = 0; | 1560 | percent_complete = 0; |
| 1441 | handle = 0; | 1561 | handle = 0; |
| 1562 | if (ioc->is_warpdrive) | ||
| 1563 | goto out; | ||
| 1564 | |||
| 1442 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | 1565 | spin_lock_irqsave(&ioc->raid_device_lock, flags); |
| 1443 | raid_device = _scsih_raid_device_find_by_id(ioc, sdev->id, | 1566 | raid_device = _scsih_raid_device_find_by_id(ioc, sdev->id, |
| 1444 | sdev->channel); | 1567 | sdev->channel); |
| @@ -1466,15 +1589,18 @@ _scsih_get_resync(struct device *dev) | |||
| 1466 | percent_complete = 0; | 1589 | percent_complete = 0; |
| 1467 | 1590 | ||
| 1468 | out: | 1591 | out: |
| 1469 | raid_set_resync(mpt3sas_raid_template, dev, percent_complete); | 1592 | if (ioc->hba_mpi_version_belonged == MPI2_VERSION) |
| 1593 | raid_set_resync(mpt2sas_raid_template, dev, percent_complete); | ||
| 1594 | if (ioc->hba_mpi_version_belonged == MPI25_VERSION) | ||
| 1595 | raid_set_resync(mpt3sas_raid_template, dev, percent_complete); | ||
| 1470 | } | 1596 | } |
| 1471 | 1597 | ||
| 1472 | /** | 1598 | /** |
| 1473 | * _scsih_get_state - get raid volume level | 1599 | * scsih_get_state - get raid volume level |
| 1474 | * @dev the device struct object | 1600 | * @dev the device struct object |
| 1475 | */ | 1601 | */ |
| 1476 | static void | 1602 | void |
| 1477 | _scsih_get_state(struct device *dev) | 1603 | scsih_get_state(struct device *dev) |
| 1478 | { | 1604 | { |
| 1479 | struct scsi_device *sdev = to_scsi_device(dev); | 1605 | struct scsi_device *sdev = to_scsi_device(dev); |
| 1480 | struct MPT3SAS_ADAPTER *ioc = shost_priv(sdev->host); | 1606 | struct MPT3SAS_ADAPTER *ioc = shost_priv(sdev->host); |
| @@ -1524,7 +1650,10 @@ _scsih_get_state(struct device *dev) | |||
| 1524 | break; | 1650 | break; |
| 1525 | } | 1651 | } |
| 1526 | out: | 1652 | out: |
| 1527 | raid_set_state(mpt3sas_raid_template, dev, state); | 1653 | if (ioc->hba_mpi_version_belonged == MPI2_VERSION) |
| 1654 | raid_set_state(mpt2sas_raid_template, dev, state); | ||
| 1655 | if (ioc->hba_mpi_version_belonged == MPI25_VERSION) | ||
| 1656 | raid_set_state(mpt3sas_raid_template, dev, state); | ||
| 1528 | } | 1657 | } |
| 1529 | 1658 | ||
| 1530 | /** | 1659 | /** |
| @@ -1533,7 +1662,8 @@ _scsih_get_state(struct device *dev) | |||
| 1533 | * @volume_type: volume type | 1662 | * @volume_type: volume type |
| 1534 | */ | 1663 | */ |
| 1535 | static void | 1664 | static void |
| 1536 | _scsih_set_level(struct scsi_device *sdev, u8 volume_type) | 1665 | _scsih_set_level(struct MPT3SAS_ADAPTER *ioc, |
| 1666 | struct scsi_device *sdev, u8 volume_type) | ||
| 1537 | { | 1667 | { |
| 1538 | enum raid_level level = RAID_LEVEL_UNKNOWN; | 1668 | enum raid_level level = RAID_LEVEL_UNKNOWN; |
| 1539 | 1669 | ||
| @@ -1552,7 +1682,12 @@ _scsih_set_level(struct scsi_device *sdev, u8 volume_type) | |||
| 1552 | break; | 1682 | break; |
| 1553 | } | 1683 | } |
| 1554 | 1684 | ||
| 1555 | raid_set_level(mpt3sas_raid_template, &sdev->sdev_gendev, level); | 1685 | if (ioc->hba_mpi_version_belonged == MPI2_VERSION) |
| 1686 | raid_set_level(mpt2sas_raid_template, | ||
| 1687 | &sdev->sdev_gendev, level); | ||
| 1688 | if (ioc->hba_mpi_version_belonged == MPI25_VERSION) | ||
| 1689 | raid_set_level(mpt3sas_raid_template, | ||
| 1690 | &sdev->sdev_gendev, level); | ||
| 1556 | } | 1691 | } |
| 1557 | 1692 | ||
| 1558 | 1693 | ||
| @@ -1622,8 +1757,6 @@ _scsih_get_volume_capabilities(struct MPT3SAS_ADAPTER *ioc, | |||
| 1622 | return 0; | 1757 | return 0; |
| 1623 | } | 1758 | } |
| 1624 | 1759 | ||
| 1625 | |||
| 1626 | |||
| 1627 | /** | 1760 | /** |
| 1628 | * _scsih_enable_tlr - setting TLR flags | 1761 | * _scsih_enable_tlr - setting TLR flags |
| 1629 | * @ioc: per adapter object | 1762 | * @ioc: per adapter object |
| @@ -1652,14 +1785,14 @@ _scsih_enable_tlr(struct MPT3SAS_ADAPTER *ioc, struct scsi_device *sdev) | |||
| 1652 | } | 1785 | } |
| 1653 | 1786 | ||
| 1654 | /** | 1787 | /** |
| 1655 | * _scsih_slave_configure - device configure routine. | 1788 | * scsih_slave_configure - device configure routine. |
| 1656 | * @sdev: scsi device struct | 1789 | * @sdev: scsi device struct |
| 1657 | * | 1790 | * |
| 1658 | * Returns 0 if ok. Any other return is assumed to be an error and | 1791 | * Returns 0 if ok. Any other return is assumed to be an error and |
| 1659 | * the device is ignored. | 1792 | * the device is ignored. |
| 1660 | */ | 1793 | */ |
| 1661 | static int | 1794 | int |
| 1662 | _scsih_slave_configure(struct scsi_device *sdev) | 1795 | scsih_slave_configure(struct scsi_device *sdev) |
| 1663 | { | 1796 | { |
| 1664 | struct Scsi_Host *shost = sdev->host; | 1797 | struct Scsi_Host *shost = sdev->host; |
| 1665 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); | 1798 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); |
| @@ -1686,7 +1819,7 @@ _scsih_slave_configure(struct scsi_device *sdev) | |||
| 1686 | if (sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME) { | 1819 | if (sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME) { |
| 1687 | 1820 | ||
| 1688 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | 1821 | spin_lock_irqsave(&ioc->raid_device_lock, flags); |
| 1689 | raid_device = _scsih_raid_device_find_by_handle(ioc, handle); | 1822 | raid_device = mpt3sas_raid_device_find_by_handle(ioc, handle); |
| 1690 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); | 1823 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); |
| 1691 | if (!raid_device) { | 1824 | if (!raid_device) { |
| 1692 | dfailprintk(ioc, pr_warn(MPT3SAS_FMT | 1825 | dfailprintk(ioc, pr_warn(MPT3SAS_FMT |
| @@ -1702,6 +1835,10 @@ _scsih_slave_configure(struct scsi_device *sdev) | |||
| 1702 | return 1; | 1835 | return 1; |
| 1703 | } | 1836 | } |
| 1704 | 1837 | ||
| 1838 | /* | ||
| 1839 | * WARPDRIVE: Initialize the required data for Direct IO | ||
| 1840 | */ | ||
| 1841 | mpt3sas_init_warpdrive_properties(ioc, raid_device); | ||
| 1705 | 1842 | ||
| 1706 | /* RAID Queue Depth Support | 1843 | /* RAID Queue Depth Support |
| 1707 | * IS volume = underlying qdepth of drive type, either | 1844 | * IS volume = underlying qdepth of drive type, either |
| @@ -1750,17 +1887,19 @@ _scsih_slave_configure(struct scsi_device *sdev) | |||
| 1750 | break; | 1887 | break; |
| 1751 | } | 1888 | } |
| 1752 | 1889 | ||
| 1753 | sdev_printk(KERN_INFO, sdev, | 1890 | if (!ioc->hide_ir_msg) |
| 1754 | "%s: handle(0x%04x), wwid(0x%016llx), pd_count(%d), type(%s)\n", | 1891 | sdev_printk(KERN_INFO, sdev, |
| 1755 | r_level, raid_device->handle, | 1892 | "%s: handle(0x%04x), wwid(0x%016llx)," |
| 1756 | (unsigned long long)raid_device->wwid, | 1893 | " pd_count(%d), type(%s)\n", |
| 1757 | raid_device->num_pds, ds); | 1894 | r_level, raid_device->handle, |
| 1758 | 1895 | (unsigned long long)raid_device->wwid, | |
| 1896 | raid_device->num_pds, ds); | ||
| 1759 | 1897 | ||
| 1760 | _scsih_change_queue_depth(sdev, qdepth); | 1898 | scsih_change_queue_depth(sdev, qdepth); |
| 1761 | 1899 | ||
| 1762 | /* raid transport support */ | 1900 | /* raid transport support */ |
| 1763 | _scsih_set_level(sdev, raid_device->volume_type); | 1901 | if (!ioc->is_warpdrive) |
| 1902 | _scsih_set_level(ioc, sdev, raid_device->volume_type); | ||
| 1764 | return 0; | 1903 | return 0; |
| 1765 | } | 1904 | } |
| 1766 | 1905 | ||
| @@ -1783,7 +1922,7 @@ _scsih_slave_configure(struct scsi_device *sdev) | |||
| 1783 | } | 1922 | } |
| 1784 | 1923 | ||
| 1785 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 1924 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 1786 | sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc, | 1925 | sas_device = __mpt3sas_get_sdev_by_addr(ioc, |
| 1787 | sas_device_priv_data->sas_target->sas_address); | 1926 | sas_device_priv_data->sas_target->sas_address); |
| 1788 | if (!sas_device) { | 1927 | if (!sas_device) { |
| 1789 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 1928 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| @@ -1823,13 +1962,14 @@ _scsih_slave_configure(struct scsi_device *sdev) | |||
| 1823 | ds, sas_device->enclosure_level, | 1962 | ds, sas_device->enclosure_level, |
| 1824 | sas_device->connector_name); | 1963 | sas_device->connector_name); |
| 1825 | 1964 | ||
| 1965 | sas_device_put(sas_device); | ||
| 1826 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 1966 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 1827 | 1967 | ||
| 1828 | if (!ssp_target) | 1968 | if (!ssp_target) |
| 1829 | _scsih_display_sata_capabilities(ioc, handle, sdev); | 1969 | _scsih_display_sata_capabilities(ioc, handle, sdev); |
| 1830 | 1970 | ||
| 1831 | 1971 | ||
| 1832 | _scsih_change_queue_depth(sdev, qdepth); | 1972 | scsih_change_queue_depth(sdev, qdepth); |
| 1833 | 1973 | ||
| 1834 | if (ssp_target) { | 1974 | if (ssp_target) { |
| 1835 | sas_read_port_mode_page(sdev); | 1975 | sas_read_port_mode_page(sdev); |
| @@ -1840,7 +1980,7 @@ _scsih_slave_configure(struct scsi_device *sdev) | |||
| 1840 | } | 1980 | } |
| 1841 | 1981 | ||
| 1842 | /** | 1982 | /** |
| 1843 | * _scsih_bios_param - fetch head, sector, cylinder info for a disk | 1983 | * scsih_bios_param - fetch head, sector, cylinder info for a disk |
| 1844 | * @sdev: scsi device struct | 1984 | * @sdev: scsi device struct |
| 1845 | * @bdev: pointer to block device context | 1985 | * @bdev: pointer to block device context |
| 1846 | * @capacity: device size (in 512 byte sectors) | 1986 | * @capacity: device size (in 512 byte sectors) |
| @@ -1851,8 +1991,8 @@ _scsih_slave_configure(struct scsi_device *sdev) | |||
| 1851 | * | 1991 | * |
| 1852 | * Return nothing. | 1992 | * Return nothing. |
| 1853 | */ | 1993 | */ |
| 1854 | static int | 1994 | int |
| 1855 | _scsih_bios_param(struct scsi_device *sdev, struct block_device *bdev, | 1995 | scsih_bios_param(struct scsi_device *sdev, struct block_device *bdev, |
| 1856 | sector_t capacity, int params[]) | 1996 | sector_t capacity, int params[]) |
| 1857 | { | 1997 | { |
| 1858 | int heads; | 1998 | int heads; |
| @@ -2209,7 +2349,10 @@ _scsih_tm_display_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd) | |||
| 2209 | 2349 | ||
| 2210 | if (!priv_target) | 2350 | if (!priv_target) |
| 2211 | return; | 2351 | return; |
| 2212 | device_str = "volume"; | 2352 | if (ioc->hide_ir_msg) |
| 2353 | device_str = "WarpDrive"; | ||
| 2354 | else | ||
| 2355 | device_str = "volume"; | ||
| 2213 | 2356 | ||
| 2214 | scsi_print_command(scmd); | 2357 | scsi_print_command(scmd); |
| 2215 | if (priv_target->flags & MPT_TARGET_FLAGS_VOLUME) { | 2358 | if (priv_target->flags & MPT_TARGET_FLAGS_VOLUME) { |
| @@ -2219,8 +2362,7 @@ _scsih_tm_display_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd) | |||
| 2219 | device_str, (unsigned long long)priv_target->sas_address); | 2362 | device_str, (unsigned long long)priv_target->sas_address); |
| 2220 | } else { | 2363 | } else { |
| 2221 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 2364 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 2222 | sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc, | 2365 | sas_device = __mpt3sas_get_sdev_from_target(ioc, priv_target); |
| 2223 | priv_target->sas_address); | ||
| 2224 | if (sas_device) { | 2366 | if (sas_device) { |
| 2225 | if (priv_target->flags & | 2367 | if (priv_target->flags & |
| 2226 | MPT_TARGET_FLAGS_RAID_COMPONENT) { | 2368 | MPT_TARGET_FLAGS_RAID_COMPONENT) { |
| @@ -2246,19 +2388,21 @@ _scsih_tm_display_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd) | |||
| 2246 | "enclosure level(0x%04x),connector name(%s)\n", | 2388 | "enclosure level(0x%04x),connector name(%s)\n", |
| 2247 | sas_device->enclosure_level, | 2389 | sas_device->enclosure_level, |
| 2248 | sas_device->connector_name); | 2390 | sas_device->connector_name); |
| 2391 | |||
| 2392 | sas_device_put(sas_device); | ||
| 2249 | } | 2393 | } |
| 2250 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 2394 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 2251 | } | 2395 | } |
| 2252 | } | 2396 | } |
| 2253 | 2397 | ||
| 2254 | /** | 2398 | /** |
| 2255 | * _scsih_abort - eh threads main abort routine | 2399 | * scsih_abort - eh threads main abort routine |
| 2256 | * @scmd: pointer to scsi command object | 2400 | * @scmd: pointer to scsi command object |
| 2257 | * | 2401 | * |
| 2258 | * Returns SUCCESS if command aborted else FAILED | 2402 | * Returns SUCCESS if command aborted else FAILED |
| 2259 | */ | 2403 | */ |
| 2260 | static int | 2404 | int |
| 2261 | _scsih_abort(struct scsi_cmnd *scmd) | 2405 | scsih_abort(struct scsi_cmnd *scmd) |
| 2262 | { | 2406 | { |
| 2263 | struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host); | 2407 | struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host); |
| 2264 | struct MPT3SAS_DEVICE *sas_device_priv_data; | 2408 | struct MPT3SAS_DEVICE *sas_device_priv_data; |
| @@ -2311,21 +2455,23 @@ _scsih_abort(struct scsi_cmnd *scmd) | |||
| 2311 | } | 2455 | } |
| 2312 | 2456 | ||
| 2313 | /** | 2457 | /** |
| 2314 | * _scsih_dev_reset - eh threads main device reset routine | 2458 | * scsih_dev_reset - eh threads main device reset routine |
| 2315 | * @scmd: pointer to scsi command object | 2459 | * @scmd: pointer to scsi command object |
| 2316 | * | 2460 | * |
| 2317 | * Returns SUCCESS if command aborted else FAILED | 2461 | * Returns SUCCESS if command aborted else FAILED |
| 2318 | */ | 2462 | */ |
| 2319 | static int | 2463 | int |
| 2320 | _scsih_dev_reset(struct scsi_cmnd *scmd) | 2464 | scsih_dev_reset(struct scsi_cmnd *scmd) |
| 2321 | { | 2465 | { |
| 2322 | struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host); | 2466 | struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host); |
| 2323 | struct MPT3SAS_DEVICE *sas_device_priv_data; | 2467 | struct MPT3SAS_DEVICE *sas_device_priv_data; |
| 2324 | struct _sas_device *sas_device; | 2468 | struct _sas_device *sas_device = NULL; |
| 2325 | unsigned long flags; | ||
| 2326 | u16 handle; | 2469 | u16 handle; |
| 2327 | int r; | 2470 | int r; |
| 2328 | 2471 | ||
| 2472 | struct scsi_target *starget = scmd->device->sdev_target; | ||
| 2473 | struct MPT3SAS_TARGET *target_priv_data = starget->hostdata; | ||
| 2474 | |||
| 2329 | sdev_printk(KERN_INFO, scmd->device, | 2475 | sdev_printk(KERN_INFO, scmd->device, |
| 2330 | "attempting device reset! scmd(%p)\n", scmd); | 2476 | "attempting device reset! scmd(%p)\n", scmd); |
| 2331 | _scsih_tm_display_info(ioc, scmd); | 2477 | _scsih_tm_display_info(ioc, scmd); |
| @@ -2344,12 +2490,10 @@ _scsih_dev_reset(struct scsi_cmnd *scmd) | |||
| 2344 | handle = 0; | 2490 | handle = 0; |
| 2345 | if (sas_device_priv_data->sas_target->flags & | 2491 | if (sas_device_priv_data->sas_target->flags & |
| 2346 | MPT_TARGET_FLAGS_RAID_COMPONENT) { | 2492 | MPT_TARGET_FLAGS_RAID_COMPONENT) { |
| 2347 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 2493 | sas_device = mpt3sas_get_sdev_from_target(ioc, |
| 2348 | sas_device = _scsih_sas_device_find_by_handle(ioc, | 2494 | target_priv_data); |
| 2349 | sas_device_priv_data->sas_target->handle); | ||
| 2350 | if (sas_device) | 2495 | if (sas_device) |
| 2351 | handle = sas_device->volume_handle; | 2496 | handle = sas_device->volume_handle; |
| 2352 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 2353 | } else | 2497 | } else |
| 2354 | handle = sas_device_priv_data->sas_target->handle; | 2498 | handle = sas_device_priv_data->sas_target->handle; |
| 2355 | 2499 | ||
| @@ -2366,25 +2510,29 @@ _scsih_dev_reset(struct scsi_cmnd *scmd) | |||
| 2366 | out: | 2510 | out: |
| 2367 | sdev_printk(KERN_INFO, scmd->device, "device reset: %s scmd(%p)\n", | 2511 | sdev_printk(KERN_INFO, scmd->device, "device reset: %s scmd(%p)\n", |
| 2368 | ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); | 2512 | ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); |
| 2513 | |||
| 2514 | if (sas_device) | ||
| 2515 | sas_device_put(sas_device); | ||
| 2516 | |||
| 2369 | return r; | 2517 | return r; |
| 2370 | } | 2518 | } |
| 2371 | 2519 | ||
| 2372 | /** | 2520 | /** |
| 2373 | * _scsih_target_reset - eh threads main target reset routine | 2521 | * scsih_target_reset - eh threads main target reset routine |
| 2374 | * @scmd: pointer to scsi command object | 2522 | * @scmd: pointer to scsi command object |
| 2375 | * | 2523 | * |
| 2376 | * Returns SUCCESS if command aborted else FAILED | 2524 | * Returns SUCCESS if command aborted else FAILED |
| 2377 | */ | 2525 | */ |
| 2378 | static int | 2526 | int |
| 2379 | _scsih_target_reset(struct scsi_cmnd *scmd) | 2527 | scsih_target_reset(struct scsi_cmnd *scmd) |
| 2380 | { | 2528 | { |
| 2381 | struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host); | 2529 | struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host); |
| 2382 | struct MPT3SAS_DEVICE *sas_device_priv_data; | 2530 | struct MPT3SAS_DEVICE *sas_device_priv_data; |
| 2383 | struct _sas_device *sas_device; | 2531 | struct _sas_device *sas_device = NULL; |
| 2384 | unsigned long flags; | ||
| 2385 | u16 handle; | 2532 | u16 handle; |
| 2386 | int r; | 2533 | int r; |
| 2387 | struct scsi_target *starget = scmd->device->sdev_target; | 2534 | struct scsi_target *starget = scmd->device->sdev_target; |
| 2535 | struct MPT3SAS_TARGET *target_priv_data = starget->hostdata; | ||
| 2388 | 2536 | ||
| 2389 | starget_printk(KERN_INFO, starget, "attempting target reset! scmd(%p)\n", | 2537 | starget_printk(KERN_INFO, starget, "attempting target reset! scmd(%p)\n", |
| 2390 | scmd); | 2538 | scmd); |
| @@ -2404,12 +2552,10 @@ _scsih_target_reset(struct scsi_cmnd *scmd) | |||
| 2404 | handle = 0; | 2552 | handle = 0; |
| 2405 | if (sas_device_priv_data->sas_target->flags & | 2553 | if (sas_device_priv_data->sas_target->flags & |
| 2406 | MPT_TARGET_FLAGS_RAID_COMPONENT) { | 2554 | MPT_TARGET_FLAGS_RAID_COMPONENT) { |
| 2407 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 2555 | sas_device = mpt3sas_get_sdev_from_target(ioc, |
| 2408 | sas_device = _scsih_sas_device_find_by_handle(ioc, | 2556 | target_priv_data); |
| 2409 | sas_device_priv_data->sas_target->handle); | ||
| 2410 | if (sas_device) | 2557 | if (sas_device) |
| 2411 | handle = sas_device->volume_handle; | 2558 | handle = sas_device->volume_handle; |
| 2412 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 2413 | } else | 2559 | } else |
| 2414 | handle = sas_device_priv_data->sas_target->handle; | 2560 | handle = sas_device_priv_data->sas_target->handle; |
| 2415 | 2561 | ||
| @@ -2426,18 +2572,22 @@ _scsih_target_reset(struct scsi_cmnd *scmd) | |||
| 2426 | out: | 2572 | out: |
| 2427 | starget_printk(KERN_INFO, starget, "target reset: %s scmd(%p)\n", | 2573 | starget_printk(KERN_INFO, starget, "target reset: %s scmd(%p)\n", |
| 2428 | ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); | 2574 | ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); |
| 2575 | |||
| 2576 | if (sas_device) | ||
| 2577 | sas_device_put(sas_device); | ||
| 2578 | |||
| 2429 | return r; | 2579 | return r; |
| 2430 | } | 2580 | } |
| 2431 | 2581 | ||
| 2432 | 2582 | ||
| 2433 | /** | 2583 | /** |
| 2434 | * _scsih_host_reset - eh threads main host reset routine | 2584 | * scsih_host_reset - eh threads main host reset routine |
| 2435 | * @scmd: pointer to scsi command object | 2585 | * @scmd: pointer to scsi command object |
| 2436 | * | 2586 | * |
| 2437 | * Returns SUCCESS if command aborted else FAILED | 2587 | * Returns SUCCESS if command aborted else FAILED |
| 2438 | */ | 2588 | */ |
| 2439 | static int | 2589 | int |
| 2440 | _scsih_host_reset(struct scsi_cmnd *scmd) | 2590 | scsih_host_reset(struct scsi_cmnd *scmd) |
| 2441 | { | 2591 | { |
| 2442 | struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host); | 2592 | struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host); |
| 2443 | int r, retval; | 2593 | int r, retval; |
| @@ -2483,32 +2633,36 @@ _scsih_fw_event_add(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event) | |||
| 2483 | return; | 2633 | return; |
| 2484 | 2634 | ||
| 2485 | spin_lock_irqsave(&ioc->fw_event_lock, flags); | 2635 | spin_lock_irqsave(&ioc->fw_event_lock, flags); |
| 2636 | fw_event_work_get(fw_event); | ||
| 2486 | INIT_LIST_HEAD(&fw_event->list); | 2637 | INIT_LIST_HEAD(&fw_event->list); |
| 2487 | list_add_tail(&fw_event->list, &ioc->fw_event_list); | 2638 | list_add_tail(&fw_event->list, &ioc->fw_event_list); |
| 2488 | INIT_WORK(&fw_event->work, _firmware_event_work); | 2639 | INIT_WORK(&fw_event->work, _firmware_event_work); |
| 2640 | fw_event_work_get(fw_event); | ||
| 2489 | queue_work(ioc->firmware_event_thread, &fw_event->work); | 2641 | queue_work(ioc->firmware_event_thread, &fw_event->work); |
| 2490 | spin_unlock_irqrestore(&ioc->fw_event_lock, flags); | 2642 | spin_unlock_irqrestore(&ioc->fw_event_lock, flags); |
| 2491 | } | 2643 | } |
| 2492 | 2644 | ||
| 2493 | /** | 2645 | /** |
| 2494 | * _scsih_fw_event_free - delete fw_event | 2646 | * _scsih_fw_event_del_from_list - delete fw_event from the list |
| 2495 | * @ioc: per adapter object | 2647 | * @ioc: per adapter object |
| 2496 | * @fw_event: object describing the event | 2648 | * @fw_event: object describing the event |
| 2497 | * Context: This function will acquire ioc->fw_event_lock. | 2649 | * Context: This function will acquire ioc->fw_event_lock. |
| 2498 | * | 2650 | * |
| 2499 | * This removes firmware event object from link list, frees associated memory. | 2651 | * If the fw_event is on the fw_event_list, remove it and do a put. |
| 2500 | * | 2652 | * |
| 2501 | * Return nothing. | 2653 | * Return nothing. |
| 2502 | */ | 2654 | */ |
| 2503 | static void | 2655 | static void |
| 2504 | _scsih_fw_event_free(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work | 2656 | _scsih_fw_event_del_from_list(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work |
| 2505 | *fw_event) | 2657 | *fw_event) |
| 2506 | { | 2658 | { |
| 2507 | unsigned long flags; | 2659 | unsigned long flags; |
| 2508 | 2660 | ||
| 2509 | spin_lock_irqsave(&ioc->fw_event_lock, flags); | 2661 | spin_lock_irqsave(&ioc->fw_event_lock, flags); |
| 2510 | list_del(&fw_event->list); | 2662 | if (!list_empty(&fw_event->list)) { |
| 2511 | kfree(fw_event); | 2663 | list_del_init(&fw_event->list); |
| 2664 | fw_event_work_put(fw_event); | ||
| 2665 | } | ||
| 2512 | spin_unlock_irqrestore(&ioc->fw_event_lock, flags); | 2666 | spin_unlock_irqrestore(&ioc->fw_event_lock, flags); |
| 2513 | } | 2667 | } |
| 2514 | 2668 | ||
| @@ -2525,17 +2679,19 @@ mpt3sas_send_trigger_data_event(struct MPT3SAS_ADAPTER *ioc, | |||
| 2525 | struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data) | 2679 | struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data) |
| 2526 | { | 2680 | { |
| 2527 | struct fw_event_work *fw_event; | 2681 | struct fw_event_work *fw_event; |
| 2682 | u16 sz; | ||
| 2528 | 2683 | ||
| 2529 | if (ioc->is_driver_loading) | 2684 | if (ioc->is_driver_loading) |
| 2530 | return; | 2685 | return; |
| 2531 | fw_event = kzalloc(sizeof(*fw_event) + sizeof(*event_data), | 2686 | sz = sizeof(*event_data); |
| 2532 | GFP_ATOMIC); | 2687 | fw_event = alloc_fw_event_work(sz); |
| 2533 | if (!fw_event) | 2688 | if (!fw_event) |
| 2534 | return; | 2689 | return; |
| 2535 | fw_event->event = MPT3SAS_PROCESS_TRIGGER_DIAG; | 2690 | fw_event->event = MPT3SAS_PROCESS_TRIGGER_DIAG; |
| 2536 | fw_event->ioc = ioc; | 2691 | fw_event->ioc = ioc; |
| 2537 | memcpy(fw_event->event_data, event_data, sizeof(*event_data)); | 2692 | memcpy(fw_event->event_data, event_data, sizeof(*event_data)); |
| 2538 | _scsih_fw_event_add(ioc, fw_event); | 2693 | _scsih_fw_event_add(ioc, fw_event); |
| 2694 | fw_event_work_put(fw_event); | ||
| 2539 | } | 2695 | } |
| 2540 | 2696 | ||
| 2541 | /** | 2697 | /** |
| @@ -2551,12 +2707,13 @@ _scsih_error_recovery_delete_devices(struct MPT3SAS_ADAPTER *ioc) | |||
| 2551 | 2707 | ||
| 2552 | if (ioc->is_driver_loading) | 2708 | if (ioc->is_driver_loading) |
| 2553 | return; | 2709 | return; |
| 2554 | fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC); | 2710 | fw_event = alloc_fw_event_work(0); |
| 2555 | if (!fw_event) | 2711 | if (!fw_event) |
| 2556 | return; | 2712 | return; |
| 2557 | fw_event->event = MPT3SAS_REMOVE_UNRESPONDING_DEVICES; | 2713 | fw_event->event = MPT3SAS_REMOVE_UNRESPONDING_DEVICES; |
| 2558 | fw_event->ioc = ioc; | 2714 | fw_event->ioc = ioc; |
| 2559 | _scsih_fw_event_add(ioc, fw_event); | 2715 | _scsih_fw_event_add(ioc, fw_event); |
| 2716 | fw_event_work_put(fw_event); | ||
| 2560 | } | 2717 | } |
| 2561 | 2718 | ||
| 2562 | /** | 2719 | /** |
| @@ -2570,12 +2727,29 @@ mpt3sas_port_enable_complete(struct MPT3SAS_ADAPTER *ioc) | |||
| 2570 | { | 2727 | { |
| 2571 | struct fw_event_work *fw_event; | 2728 | struct fw_event_work *fw_event; |
| 2572 | 2729 | ||
| 2573 | fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC); | 2730 | fw_event = alloc_fw_event_work(0); |
| 2574 | if (!fw_event) | 2731 | if (!fw_event) |
| 2575 | return; | 2732 | return; |
| 2576 | fw_event->event = MPT3SAS_PORT_ENABLE_COMPLETE; | 2733 | fw_event->event = MPT3SAS_PORT_ENABLE_COMPLETE; |
| 2577 | fw_event->ioc = ioc; | 2734 | fw_event->ioc = ioc; |
| 2578 | _scsih_fw_event_add(ioc, fw_event); | 2735 | _scsih_fw_event_add(ioc, fw_event); |
| 2736 | fw_event_work_put(fw_event); | ||
| 2737 | } | ||
| 2738 | |||
| 2739 | static struct fw_event_work *dequeue_next_fw_event(struct MPT3SAS_ADAPTER *ioc) | ||
| 2740 | { | ||
| 2741 | unsigned long flags; | ||
| 2742 | struct fw_event_work *fw_event = NULL; | ||
| 2743 | |||
| 2744 | spin_lock_irqsave(&ioc->fw_event_lock, flags); | ||
| 2745 | if (!list_empty(&ioc->fw_event_list)) { | ||
| 2746 | fw_event = list_first_entry(&ioc->fw_event_list, | ||
| 2747 | struct fw_event_work, list); | ||
| 2748 | list_del_init(&fw_event->list); | ||
| 2749 | } | ||
| 2750 | spin_unlock_irqrestore(&ioc->fw_event_lock, flags); | ||
| 2751 | |||
| 2752 | return fw_event; | ||
| 2579 | } | 2753 | } |
| 2580 | 2754 | ||
| 2581 | /** | 2755 | /** |
| @@ -2590,17 +2764,25 @@ mpt3sas_port_enable_complete(struct MPT3SAS_ADAPTER *ioc) | |||
| 2590 | static void | 2764 | static void |
| 2591 | _scsih_fw_event_cleanup_queue(struct MPT3SAS_ADAPTER *ioc) | 2765 | _scsih_fw_event_cleanup_queue(struct MPT3SAS_ADAPTER *ioc) |
| 2592 | { | 2766 | { |
| 2593 | struct fw_event_work *fw_event, *next; | 2767 | struct fw_event_work *fw_event; |
| 2594 | 2768 | ||
| 2595 | if (list_empty(&ioc->fw_event_list) || | 2769 | if (list_empty(&ioc->fw_event_list) || |
| 2596 | !ioc->firmware_event_thread || in_interrupt()) | 2770 | !ioc->firmware_event_thread || in_interrupt()) |
| 2597 | return; | 2771 | return; |
| 2598 | 2772 | ||
| 2599 | list_for_each_entry_safe(fw_event, next, &ioc->fw_event_list, list) { | 2773 | while ((fw_event = dequeue_next_fw_event(ioc))) { |
| 2600 | if (cancel_delayed_work_sync(&fw_event->delayed_work)) { | 2774 | /* |
| 2601 | _scsih_fw_event_free(ioc, fw_event); | 2775 | * Wait on the fw_event to complete. If this returns 1, then |
| 2602 | continue; | 2776 | * the event was never executed, and we need a put for the |
| 2603 | } | 2777 | * reference the delayed_work had on the fw_event. |
| 2778 | * | ||
| 2779 | * If it did execute, we wait for it to finish, and the put will | ||
| 2780 | * happen from _firmware_event_work() | ||
| 2781 | */ | ||
| 2782 | if (cancel_delayed_work_sync(&fw_event->delayed_work)) | ||
| 2783 | fw_event_work_put(fw_event); | ||
| 2784 | |||
| 2785 | fw_event_work_put(fw_event); | ||
| 2604 | } | 2786 | } |
| 2605 | } | 2787 | } |
| 2606 | 2788 | ||
| @@ -2763,7 +2945,7 @@ _scsih_block_io_device(struct MPT3SAS_ADAPTER *ioc, u16 handle) | |||
| 2763 | struct scsi_device *sdev; | 2945 | struct scsi_device *sdev; |
| 2764 | struct _sas_device *sas_device; | 2946 | struct _sas_device *sas_device; |
| 2765 | 2947 | ||
| 2766 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | 2948 | sas_device = mpt3sas_get_sdev_by_handle(ioc, handle); |
| 2767 | if (!sas_device) | 2949 | if (!sas_device) |
| 2768 | return; | 2950 | return; |
| 2769 | 2951 | ||
| @@ -2779,6 +2961,8 @@ _scsih_block_io_device(struct MPT3SAS_ADAPTER *ioc, u16 handle) | |||
| 2779 | continue; | 2961 | continue; |
| 2780 | _scsih_internal_device_block(sdev, sas_device_priv_data); | 2962 | _scsih_internal_device_block(sdev, sas_device_priv_data); |
| 2781 | } | 2963 | } |
| 2964 | |||
| 2965 | sas_device_put(sas_device); | ||
| 2782 | } | 2966 | } |
| 2783 | 2967 | ||
| 2784 | /** | 2968 | /** |
| @@ -2807,12 +2991,13 @@ _scsih_block_io_to_children_attached_to_ex(struct MPT3SAS_ADAPTER *ioc, | |||
| 2807 | if (mpt3sas_port->remote_identify.device_type == | 2991 | if (mpt3sas_port->remote_identify.device_type == |
| 2808 | SAS_END_DEVICE) { | 2992 | SAS_END_DEVICE) { |
| 2809 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 2993 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 2810 | sas_device = | 2994 | sas_device = __mpt3sas_get_sdev_by_addr(ioc, |
| 2811 | mpt3sas_scsih_sas_device_find_by_sas_address(ioc, | 2995 | mpt3sas_port->remote_identify.sas_address); |
| 2812 | mpt3sas_port->remote_identify.sas_address); | 2996 | if (sas_device) { |
| 2813 | if (sas_device) | ||
| 2814 | set_bit(sas_device->handle, | 2997 | set_bit(sas_device->handle, |
| 2815 | ioc->blocking_handles); | 2998 | ioc->blocking_handles); |
| 2999 | sas_device_put(sas_device); | ||
| 3000 | } | ||
| 2816 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 3001 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 2817 | } | 3002 | } |
| 2818 | } | 3003 | } |
| @@ -2880,7 +3065,7 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle) | |||
| 2880 | { | 3065 | { |
| 2881 | Mpi2SCSITaskManagementRequest_t *mpi_request; | 3066 | Mpi2SCSITaskManagementRequest_t *mpi_request; |
| 2882 | u16 smid; | 3067 | u16 smid; |
| 2883 | struct _sas_device *sas_device; | 3068 | struct _sas_device *sas_device = NULL; |
| 2884 | struct MPT3SAS_TARGET *sas_target_priv_data = NULL; | 3069 | struct MPT3SAS_TARGET *sas_target_priv_data = NULL; |
| 2885 | u64 sas_address = 0; | 3070 | u64 sas_address = 0; |
| 2886 | unsigned long flags; | 3071 | unsigned long flags; |
| @@ -2913,7 +3098,7 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle) | |||
| 2913 | return; | 3098 | return; |
| 2914 | 3099 | ||
| 2915 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 3100 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 2916 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | 3101 | sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle); |
| 2917 | if (sas_device && sas_device->starget && | 3102 | if (sas_device && sas_device->starget && |
| 2918 | sas_device->starget->hostdata) { | 3103 | sas_device->starget->hostdata) { |
| 2919 | sas_target_priv_data = sas_device->starget->hostdata; | 3104 | sas_target_priv_data = sas_device->starget->hostdata; |
| @@ -2947,14 +3132,14 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle) | |||
| 2947 | if (!smid) { | 3132 | if (!smid) { |
| 2948 | delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC); | 3133 | delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC); |
| 2949 | if (!delayed_tr) | 3134 | if (!delayed_tr) |
| 2950 | return; | 3135 | goto out; |
| 2951 | INIT_LIST_HEAD(&delayed_tr->list); | 3136 | INIT_LIST_HEAD(&delayed_tr->list); |
| 2952 | delayed_tr->handle = handle; | 3137 | delayed_tr->handle = handle; |
| 2953 | list_add_tail(&delayed_tr->list, &ioc->delayed_tr_list); | 3138 | list_add_tail(&delayed_tr->list, &ioc->delayed_tr_list); |
| 2954 | dewtprintk(ioc, pr_info(MPT3SAS_FMT | 3139 | dewtprintk(ioc, pr_info(MPT3SAS_FMT |
| 2955 | "DELAYED:tr:handle(0x%04x), (open)\n", | 3140 | "DELAYED:tr:handle(0x%04x), (open)\n", |
| 2956 | ioc->name, handle)); | 3141 | ioc->name, handle)); |
| 2957 | return; | 3142 | goto out; |
| 2958 | } | 3143 | } |
| 2959 | 3144 | ||
| 2960 | dewtprintk(ioc, pr_info(MPT3SAS_FMT | 3145 | dewtprintk(ioc, pr_info(MPT3SAS_FMT |
| @@ -2968,6 +3153,10 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle) | |||
| 2968 | mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; | 3153 | mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; |
| 2969 | mpt3sas_base_put_smid_hi_priority(ioc, smid); | 3154 | mpt3sas_base_put_smid_hi_priority(ioc, smid); |
| 2970 | mpt3sas_trigger_master(ioc, MASTER_TRIGGER_DEVICE_REMOVAL); | 3155 | mpt3sas_trigger_master(ioc, MASTER_TRIGGER_DEVICE_REMOVAL); |
| 3156 | |||
| 3157 | out: | ||
| 3158 | if (sas_device) | ||
| 3159 | sas_device_put(sas_device); | ||
| 2971 | } | 3160 | } |
| 2972 | 3161 | ||
| 2973 | /** | 3162 | /** |
| @@ -3337,7 +3526,7 @@ _scsih_set_volume_delete_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle) | |||
| 3337 | unsigned long flags; | 3526 | unsigned long flags; |
| 3338 | 3527 | ||
| 3339 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | 3528 | spin_lock_irqsave(&ioc->raid_device_lock, flags); |
| 3340 | raid_device = _scsih_raid_device_find_by_handle(ioc, handle); | 3529 | raid_device = mpt3sas_raid_device_find_by_handle(ioc, handle); |
| 3341 | if (raid_device && raid_device->starget && | 3530 | if (raid_device && raid_device->starget && |
| 3342 | raid_device->starget->hostdata) { | 3531 | raid_device->starget->hostdata) { |
| 3343 | sas_target_priv_data = | 3532 | sas_target_priv_data = |
| @@ -3398,6 +3587,9 @@ _scsih_check_ir_config_unhide_events(struct MPT3SAS_ADAPTER *ioc, | |||
| 3398 | a = 0; | 3587 | a = 0; |
| 3399 | b = 0; | 3588 | b = 0; |
| 3400 | 3589 | ||
| 3590 | if (ioc->is_warpdrive) | ||
| 3591 | return; | ||
| 3592 | |||
| 3401 | /* Volume Resets for Deleted or Removed */ | 3593 | /* Volume Resets for Deleted or Removed */ |
| 3402 | element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; | 3594 | element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; |
| 3403 | for (i = 0; i < event_data->NumElements; i++, element++) { | 3595 | for (i = 0; i < event_data->NumElements; i++, element++) { |
| @@ -3634,8 +3826,9 @@ _scsih_eedp_error_handling(struct scsi_cmnd *scmd, u16 ioc_status) | |||
| 3634 | } | 3826 | } |
| 3635 | 3827 | ||
| 3636 | 3828 | ||
| 3829 | |||
| 3637 | /** | 3830 | /** |
| 3638 | * _scsih_qcmd - main scsi request entry point | 3831 | * scsih_qcmd - main scsi request entry point |
| 3639 | * @scmd: pointer to scsi command object | 3832 | * @scmd: pointer to scsi command object |
| 3640 | * @done: function pointer to be invoked on completion | 3833 | * @done: function pointer to be invoked on completion |
| 3641 | * | 3834 | * |
| @@ -3645,21 +3838,20 @@ _scsih_eedp_error_handling(struct scsi_cmnd *scmd, u16 ioc_status) | |||
| 3645 | * SCSI_MLQUEUE_DEVICE_BUSY if the device queue is full, or | 3838 | * SCSI_MLQUEUE_DEVICE_BUSY if the device queue is full, or |
| 3646 | * SCSI_MLQUEUE_HOST_BUSY if the entire host queue is full | 3839 | * SCSI_MLQUEUE_HOST_BUSY if the entire host queue is full |
| 3647 | */ | 3840 | */ |
| 3648 | static int | 3841 | int |
| 3649 | _scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd) | 3842 | scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd) |
| 3650 | { | 3843 | { |
| 3651 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); | 3844 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); |
| 3652 | struct MPT3SAS_DEVICE *sas_device_priv_data; | 3845 | struct MPT3SAS_DEVICE *sas_device_priv_data; |
| 3653 | struct MPT3SAS_TARGET *sas_target_priv_data; | 3846 | struct MPT3SAS_TARGET *sas_target_priv_data; |
| 3847 | struct _raid_device *raid_device; | ||
| 3654 | Mpi2SCSIIORequest_t *mpi_request; | 3848 | Mpi2SCSIIORequest_t *mpi_request; |
| 3655 | u32 mpi_control; | 3849 | u32 mpi_control; |
| 3656 | u16 smid; | 3850 | u16 smid; |
| 3657 | u16 handle; | 3851 | u16 handle; |
| 3658 | 3852 | ||
| 3659 | #ifdef CONFIG_SCSI_MPT3SAS_LOGGING | ||
| 3660 | if (ioc->logging_level & MPT_DEBUG_SCSI) | 3853 | if (ioc->logging_level & MPT_DEBUG_SCSI) |
| 3661 | scsi_print_command(scmd); | 3854 | scsi_print_command(scmd); |
| 3662 | #endif | ||
| 3663 | 3855 | ||
| 3664 | sas_device_priv_data = scmd->device->hostdata; | 3856 | sas_device_priv_data = scmd->device->hostdata; |
| 3665 | if (!sas_device_priv_data || !sas_device_priv_data->sas_target) { | 3857 | if (!sas_device_priv_data || !sas_device_priv_data->sas_target) { |
| @@ -3709,7 +3901,11 @@ _scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd) | |||
| 3709 | /* set tags */ | 3901 | /* set tags */ |
| 3710 | mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ; | 3902 | mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ; |
| 3711 | 3903 | ||
| 3712 | if ((sas_device_priv_data->flags & MPT_DEVICE_TLR_ON) && | 3904 | /* Make sure Device is not raid volume. |
| 3905 | * We do not expose raid functionality to upper layer for warpdrive. | ||
| 3906 | */ | ||
| 3907 | if (!ioc->is_warpdrive && !scsih_is_raid(&scmd->device->sdev_gendev) | ||
| 3908 | && (sas_device_priv_data->flags & MPT_DEVICE_TLR_ON) && | ||
| 3713 | scmd->cmd_len != 32) | 3909 | scmd->cmd_len != 32) |
| 3714 | mpi_control |= MPI2_SCSIIO_CONTROL_TLR_ON; | 3910 | mpi_control |= MPI2_SCSIIO_CONTROL_TLR_ON; |
| 3715 | 3911 | ||
| @@ -3752,13 +3948,19 @@ _scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd) | |||
| 3752 | } else | 3948 | } else |
| 3753 | ioc->build_zero_len_sge(ioc, &mpi_request->SGL); | 3949 | ioc->build_zero_len_sge(ioc, &mpi_request->SGL); |
| 3754 | 3950 | ||
| 3951 | raid_device = sas_target_priv_data->raid_device; | ||
| 3952 | if (raid_device && raid_device->direct_io_enabled) | ||
| 3953 | mpt3sas_setup_direct_io(ioc, scmd, raid_device, mpi_request, | ||
| 3954 | smid); | ||
| 3955 | |||
| 3755 | if (likely(mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST)) { | 3956 | if (likely(mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST)) { |
| 3756 | if (sas_target_priv_data->flags & MPT_TARGET_FASTPATH_IO) { | 3957 | if (sas_target_priv_data->flags & MPT_TARGET_FASTPATH_IO) { |
| 3757 | mpi_request->IoFlags = cpu_to_le16(scmd->cmd_len | | 3958 | mpi_request->IoFlags = cpu_to_le16(scmd->cmd_len | |
| 3758 | MPI25_SCSIIO_IOFLAGS_FAST_PATH); | 3959 | MPI25_SCSIIO_IOFLAGS_FAST_PATH); |
| 3759 | mpt3sas_base_put_smid_fast_path(ioc, smid, handle); | 3960 | mpt3sas_base_put_smid_fast_path(ioc, smid, handle); |
| 3760 | } else | 3961 | } else |
| 3761 | mpt3sas_base_put_smid_scsi_io(ioc, smid, handle); | 3962 | mpt3sas_base_put_smid_scsi_io(ioc, smid, |
| 3963 | le16_to_cpu(mpi_request->DevHandle)); | ||
| 3762 | } else | 3964 | } else |
| 3763 | mpt3sas_base_put_smid_default(ioc, smid); | 3965 | mpt3sas_base_put_smid_default(ioc, smid); |
| 3764 | return 0; | 3966 | return 0; |
| @@ -3790,7 +3992,6 @@ _scsih_normalize_sense(char *sense_buffer, struct sense_info *data) | |||
| 3790 | } | 3992 | } |
| 3791 | } | 3993 | } |
| 3792 | 3994 | ||
| 3793 | #ifdef CONFIG_SCSI_MPT3SAS_LOGGING | ||
| 3794 | /** | 3995 | /** |
| 3795 | * _scsih_scsi_ioc_info - translated non-succesfull SCSI_IO request | 3996 | * _scsih_scsi_ioc_info - translated non-succesfull SCSI_IO request |
| 3796 | * @ioc: per adapter object | 3997 | * @ioc: per adapter object |
| @@ -3818,14 +4019,16 @@ _scsih_scsi_ioc_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, | |||
| 3818 | char *desc_scsi_state = ioc->tmp_string; | 4019 | char *desc_scsi_state = ioc->tmp_string; |
| 3819 | u32 log_info = le32_to_cpu(mpi_reply->IOCLogInfo); | 4020 | u32 log_info = le32_to_cpu(mpi_reply->IOCLogInfo); |
| 3820 | struct _sas_device *sas_device = NULL; | 4021 | struct _sas_device *sas_device = NULL; |
| 3821 | unsigned long flags; | ||
| 3822 | struct scsi_target *starget = scmd->device->sdev_target; | 4022 | struct scsi_target *starget = scmd->device->sdev_target; |
| 3823 | struct MPT3SAS_TARGET *priv_target = starget->hostdata; | 4023 | struct MPT3SAS_TARGET *priv_target = starget->hostdata; |
| 3824 | char *device_str = NULL; | 4024 | char *device_str = NULL; |
| 3825 | 4025 | ||
| 3826 | if (!priv_target) | 4026 | if (!priv_target) |
| 3827 | return; | 4027 | return; |
| 3828 | device_str = "volume"; | 4028 | if (ioc->hide_ir_msg) |
| 4029 | device_str = "WarpDrive"; | ||
| 4030 | else | ||
| 4031 | device_str = "volume"; | ||
| 3829 | 4032 | ||
| 3830 | if (log_info == 0x31170000) | 4033 | if (log_info == 0x31170000) |
| 3831 | return; | 4034 | return; |
| @@ -3946,9 +4149,7 @@ _scsih_scsi_ioc_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, | |||
| 3946 | pr_warn(MPT3SAS_FMT "\t%s wwid(0x%016llx)\n", ioc->name, | 4149 | pr_warn(MPT3SAS_FMT "\t%s wwid(0x%016llx)\n", ioc->name, |
| 3947 | device_str, (unsigned long long)priv_target->sas_address); | 4150 | device_str, (unsigned long long)priv_target->sas_address); |
| 3948 | } else { | 4151 | } else { |
| 3949 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 4152 | sas_device = mpt3sas_get_sdev_from_target(ioc, priv_target); |
| 3950 | sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc, | ||
| 3951 | priv_target->sas_address); | ||
| 3952 | if (sas_device) { | 4153 | if (sas_device) { |
| 3953 | pr_warn(MPT3SAS_FMT | 4154 | pr_warn(MPT3SAS_FMT |
| 3954 | "\tsas_address(0x%016llx), phy(%d)\n", | 4155 | "\tsas_address(0x%016llx), phy(%d)\n", |
| @@ -3967,8 +4168,9 @@ _scsih_scsi_ioc_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, | |||
| 3967 | " connector name( %s)\n", ioc->name, | 4168 | " connector name( %s)\n", ioc->name, |
| 3968 | sas_device->enclosure_level, | 4169 | sas_device->enclosure_level, |
| 3969 | sas_device->connector_name); | 4170 | sas_device->connector_name); |
| 4171 | |||
| 4172 | sas_device_put(sas_device); | ||
| 3970 | } | 4173 | } |
| 3971 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 3972 | } | 4174 | } |
| 3973 | 4175 | ||
| 3974 | pr_warn(MPT3SAS_FMT | 4176 | pr_warn(MPT3SAS_FMT |
| @@ -4003,7 +4205,6 @@ _scsih_scsi_ioc_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, | |||
| 4003 | _scsih_response_code(ioc, response_bytes[0]); | 4205 | _scsih_response_code(ioc, response_bytes[0]); |
| 4004 | } | 4206 | } |
| 4005 | } | 4207 | } |
| 4006 | #endif | ||
| 4007 | 4208 | ||
| 4008 | /** | 4209 | /** |
| 4009 | * _scsih_turn_on_pfa_led - illuminate PFA LED | 4210 | * _scsih_turn_on_pfa_led - illuminate PFA LED |
| @@ -4020,7 +4221,7 @@ _scsih_turn_on_pfa_led(struct MPT3SAS_ADAPTER *ioc, u16 handle) | |||
| 4020 | Mpi2SepRequest_t mpi_request; | 4221 | Mpi2SepRequest_t mpi_request; |
| 4021 | struct _sas_device *sas_device; | 4222 | struct _sas_device *sas_device; |
| 4022 | 4223 | ||
| 4023 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | 4224 | sas_device = mpt3sas_get_sdev_by_handle(ioc, handle); |
| 4024 | if (!sas_device) | 4225 | if (!sas_device) |
| 4025 | return; | 4226 | return; |
| 4026 | 4227 | ||
| @@ -4035,7 +4236,7 @@ _scsih_turn_on_pfa_led(struct MPT3SAS_ADAPTER *ioc, u16 handle) | |||
| 4035 | &mpi_request)) != 0) { | 4236 | &mpi_request)) != 0) { |
| 4036 | pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", ioc->name, | 4237 | pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", ioc->name, |
| 4037 | __FILE__, __LINE__, __func__); | 4238 | __FILE__, __LINE__, __func__); |
| 4038 | return; | 4239 | goto out; |
| 4039 | } | 4240 | } |
| 4040 | sas_device->pfa_led_on = 1; | 4241 | sas_device->pfa_led_on = 1; |
| 4041 | 4242 | ||
| @@ -4044,9 +4245,12 @@ _scsih_turn_on_pfa_led(struct MPT3SAS_ADAPTER *ioc, u16 handle) | |||
| 4044 | "enclosure_processor: ioc_status (0x%04x), loginfo(0x%08x)\n", | 4245 | "enclosure_processor: ioc_status (0x%04x), loginfo(0x%08x)\n", |
| 4045 | ioc->name, le16_to_cpu(mpi_reply.IOCStatus), | 4246 | ioc->name, le16_to_cpu(mpi_reply.IOCStatus), |
| 4046 | le32_to_cpu(mpi_reply.IOCLogInfo))); | 4247 | le32_to_cpu(mpi_reply.IOCLogInfo))); |
| 4047 | return; | 4248 | goto out; |
| 4048 | } | 4249 | } |
| 4250 | out: | ||
| 4251 | sas_device_put(sas_device); | ||
| 4049 | } | 4252 | } |
| 4253 | |||
| 4050 | /** | 4254 | /** |
| 4051 | * _scsih_turn_off_pfa_led - turn off Fault LED | 4255 | * _scsih_turn_off_pfa_led - turn off Fault LED |
| 4052 | * @ioc: per adapter object | 4256 | * @ioc: per adapter object |
| @@ -4085,6 +4289,7 @@ _scsih_turn_off_pfa_led(struct MPT3SAS_ADAPTER *ioc, | |||
| 4085 | return; | 4289 | return; |
| 4086 | } | 4290 | } |
| 4087 | } | 4291 | } |
| 4292 | |||
| 4088 | /** | 4293 | /** |
| 4089 | * _scsih_send_event_to_turn_on_pfa_led - fire delayed event | 4294 | * _scsih_send_event_to_turn_on_pfa_led - fire delayed event |
| 4090 | * @ioc: per adapter object | 4295 | * @ioc: per adapter object |
| @@ -4098,13 +4303,14 @@ _scsih_send_event_to_turn_on_pfa_led(struct MPT3SAS_ADAPTER *ioc, u16 handle) | |||
| 4098 | { | 4303 | { |
| 4099 | struct fw_event_work *fw_event; | 4304 | struct fw_event_work *fw_event; |
| 4100 | 4305 | ||
| 4101 | fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC); | 4306 | fw_event = alloc_fw_event_work(0); |
| 4102 | if (!fw_event) | 4307 | if (!fw_event) |
| 4103 | return; | 4308 | return; |
| 4104 | fw_event->event = MPT3SAS_TURN_ON_PFA_LED; | 4309 | fw_event->event = MPT3SAS_TURN_ON_PFA_LED; |
| 4105 | fw_event->device_handle = handle; | 4310 | fw_event->device_handle = handle; |
| 4106 | fw_event->ioc = ioc; | 4311 | fw_event->ioc = ioc; |
| 4107 | _scsih_fw_event_add(ioc, fw_event); | 4312 | _scsih_fw_event_add(ioc, fw_event); |
| 4313 | fw_event_work_put(fw_event); | ||
| 4108 | } | 4314 | } |
| 4109 | 4315 | ||
| 4110 | /** | 4316 | /** |
| @@ -4128,19 +4334,17 @@ _scsih_smart_predicted_fault(struct MPT3SAS_ADAPTER *ioc, u16 handle) | |||
| 4128 | 4334 | ||
| 4129 | /* only handle non-raid devices */ | 4335 | /* only handle non-raid devices */ |
| 4130 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 4336 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 4131 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | 4337 | sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle); |
| 4132 | if (!sas_device) { | 4338 | if (!sas_device) |
| 4133 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 4339 | goto out_unlock; |
| 4134 | return; | 4340 | |
| 4135 | } | ||
| 4136 | starget = sas_device->starget; | 4341 | starget = sas_device->starget; |
| 4137 | sas_target_priv_data = starget->hostdata; | 4342 | sas_target_priv_data = starget->hostdata; |
| 4138 | 4343 | ||
| 4139 | if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT) || | 4344 | if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT) || |
| 4140 | ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME))) { | 4345 | ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME))) |
| 4141 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 4346 | goto out_unlock; |
| 4142 | return; | 4347 | |
| 4143 | } | ||
| 4144 | if (sas_device->enclosure_handle != 0) | 4348 | if (sas_device->enclosure_handle != 0) |
| 4145 | starget_printk(KERN_INFO, starget, "predicted fault, " | 4349 | starget_printk(KERN_INFO, starget, "predicted fault, " |
| 4146 | "enclosure logical id(0x%016llx), slot(%d)\n", | 4350 | "enclosure logical id(0x%016llx), slot(%d)\n", |
| @@ -4163,7 +4367,7 @@ _scsih_smart_predicted_fault(struct MPT3SAS_ADAPTER *ioc, u16 handle) | |||
| 4163 | if (!event_reply) { | 4367 | if (!event_reply) { |
| 4164 | pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", | 4368 | pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", |
| 4165 | ioc->name, __FILE__, __LINE__, __func__); | 4369 | ioc->name, __FILE__, __LINE__, __func__); |
| 4166 | return; | 4370 | goto out; |
| 4167 | } | 4371 | } |
| 4168 | 4372 | ||
| 4169 | event_reply->Function = MPI2_FUNCTION_EVENT_NOTIFICATION; | 4373 | event_reply->Function = MPI2_FUNCTION_EVENT_NOTIFICATION; |
| @@ -4180,6 +4384,14 @@ _scsih_smart_predicted_fault(struct MPT3SAS_ADAPTER *ioc, u16 handle) | |||
| 4180 | event_data->SASAddress = cpu_to_le64(sas_target_priv_data->sas_address); | 4384 | event_data->SASAddress = cpu_to_le64(sas_target_priv_data->sas_address); |
| 4181 | mpt3sas_ctl_add_to_event_log(ioc, event_reply); | 4385 | mpt3sas_ctl_add_to_event_log(ioc, event_reply); |
| 4182 | kfree(event_reply); | 4386 | kfree(event_reply); |
| 4387 | out: | ||
| 4388 | if (sas_device) | ||
| 4389 | sas_device_put(sas_device); | ||
| 4390 | return; | ||
| 4391 | |||
| 4392 | out_unlock: | ||
| 4393 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 4394 | goto out; | ||
| 4183 | } | 4395 | } |
| 4184 | 4396 | ||
| 4185 | /** | 4397 | /** |
| @@ -4207,6 +4419,7 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) | |||
| 4207 | u32 log_info; | 4419 | u32 log_info; |
| 4208 | struct MPT3SAS_DEVICE *sas_device_priv_data; | 4420 | struct MPT3SAS_DEVICE *sas_device_priv_data; |
| 4209 | u32 response_code = 0; | 4421 | u32 response_code = 0; |
| 4422 | unsigned long flags; | ||
| 4210 | 4423 | ||
| 4211 | mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply); | 4424 | mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply); |
| 4212 | scmd = _scsih_scsi_lookup_get_clear(ioc, smid); | 4425 | scmd = _scsih_scsi_lookup_get_clear(ioc, smid); |
| @@ -4228,6 +4441,24 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) | |||
| 4228 | } | 4441 | } |
| 4229 | ioc_status = le16_to_cpu(mpi_reply->IOCStatus); | 4442 | ioc_status = le16_to_cpu(mpi_reply->IOCStatus); |
| 4230 | 4443 | ||
| 4444 | /* | ||
| 4445 | * WARPDRIVE: If direct_io is set then it is directIO, | ||
| 4446 | * the failed direct I/O should be redirected to volume | ||
| 4447 | */ | ||
| 4448 | if (mpt3sas_scsi_direct_io_get(ioc, smid) && | ||
| 4449 | ((ioc_status & MPI2_IOCSTATUS_MASK) | ||
| 4450 | != MPI2_IOCSTATUS_SCSI_TASK_TERMINATED)) { | ||
| 4451 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | ||
| 4452 | ioc->scsi_lookup[smid - 1].scmd = scmd; | ||
| 4453 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | ||
| 4454 | mpt3sas_scsi_direct_io_set(ioc, smid, 0); | ||
| 4455 | memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len); | ||
| 4456 | mpi_request->DevHandle = | ||
| 4457 | cpu_to_le16(sas_device_priv_data->sas_target->handle); | ||
| 4458 | mpt3sas_base_put_smid_scsi_io(ioc, smid, | ||
| 4459 | sas_device_priv_data->sas_target->handle); | ||
| 4460 | return 0; | ||
| 4461 | } | ||
| 4231 | /* turning off TLR */ | 4462 | /* turning off TLR */ |
| 4232 | scsi_state = mpi_reply->SCSIState; | 4463 | scsi_state = mpi_reply->SCSIState; |
| 4233 | if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) | 4464 | if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) |
| @@ -4235,10 +4466,13 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) | |||
| 4235 | le32_to_cpu(mpi_reply->ResponseInfo) & 0xFF; | 4466 | le32_to_cpu(mpi_reply->ResponseInfo) & 0xFF; |
| 4236 | if (!sas_device_priv_data->tlr_snoop_check) { | 4467 | if (!sas_device_priv_data->tlr_snoop_check) { |
| 4237 | sas_device_priv_data->tlr_snoop_check++; | 4468 | sas_device_priv_data->tlr_snoop_check++; |
| 4238 | if ((sas_device_priv_data->flags & MPT_DEVICE_TLR_ON) && | 4469 | if (!ioc->is_warpdrive && |
| 4239 | response_code == MPI2_SCSITASKMGMT_RSP_INVALID_FRAME) | 4470 | !scsih_is_raid(&scmd->device->sdev_gendev) && |
| 4240 | sas_device_priv_data->flags &= | 4471 | sas_is_tlr_enabled(scmd->device) && |
| 4241 | ~MPT_DEVICE_TLR_ON; | 4472 | response_code == MPI2_SCSITASKMGMT_RSP_INVALID_FRAME) { |
| 4473 | sas_disable_tlr(scmd->device); | ||
| 4474 | sdev_printk(KERN_INFO, scmd->device, "TLR disabled\n"); | ||
| 4475 | } | ||
| 4242 | } | 4476 | } |
| 4243 | 4477 | ||
| 4244 | xfer_cnt = le32_to_cpu(mpi_reply->TransferCount); | 4478 | xfer_cnt = le32_to_cpu(mpi_reply->TransferCount); |
| @@ -4271,13 +4505,11 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) | |||
| 4271 | le16_to_cpu(mpi_reply->DevHandle)); | 4505 | le16_to_cpu(mpi_reply->DevHandle)); |
| 4272 | mpt3sas_trigger_scsi(ioc, data.skey, data.asc, data.ascq); | 4506 | mpt3sas_trigger_scsi(ioc, data.skey, data.asc, data.ascq); |
| 4273 | 4507 | ||
| 4274 | #ifdef CONFIG_SCSI_MPT3SAS_LOGGING | ||
| 4275 | if (!(ioc->logging_level & MPT_DEBUG_REPLY) && | 4508 | if (!(ioc->logging_level & MPT_DEBUG_REPLY) && |
| 4276 | ((scmd->sense_buffer[2] == UNIT_ATTENTION) || | 4509 | ((scmd->sense_buffer[2] == UNIT_ATTENTION) || |
| 4277 | (scmd->sense_buffer[2] == MEDIUM_ERROR) || | 4510 | (scmd->sense_buffer[2] == MEDIUM_ERROR) || |
| 4278 | (scmd->sense_buffer[2] == HARDWARE_ERROR))) | 4511 | (scmd->sense_buffer[2] == HARDWARE_ERROR))) |
| 4279 | _scsih_scsi_ioc_info(ioc, scmd, mpi_reply, smid); | 4512 | _scsih_scsi_ioc_info(ioc, scmd, mpi_reply, smid); |
| 4280 | #endif | ||
| 4281 | } | 4513 | } |
| 4282 | switch (ioc_status) { | 4514 | switch (ioc_status) { |
| 4283 | case MPI2_IOCSTATUS_BUSY: | 4515 | case MPI2_IOCSTATUS_BUSY: |
| @@ -4384,10 +4616,8 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) | |||
| 4384 | 4616 | ||
| 4385 | } | 4617 | } |
| 4386 | 4618 | ||
| 4387 | #ifdef CONFIG_SCSI_MPT3SAS_LOGGING | ||
| 4388 | if (scmd->result && (ioc->logging_level & MPT_DEBUG_REPLY)) | 4619 | if (scmd->result && (ioc->logging_level & MPT_DEBUG_REPLY)) |
| 4389 | _scsih_scsi_ioc_info(ioc , scmd, mpi_reply, smid); | 4620 | _scsih_scsi_ioc_info(ioc , scmd, mpi_reply, smid); |
| 4390 | #endif | ||
| 4391 | 4621 | ||
| 4392 | out: | 4622 | out: |
| 4393 | 4623 | ||
| @@ -4933,13 +5163,11 @@ _scsih_check_device(struct MPT3SAS_ADAPTER *ioc, | |||
| 4933 | 5163 | ||
| 4934 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 5164 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 4935 | sas_address = le64_to_cpu(sas_device_pg0.SASAddress); | 5165 | sas_address = le64_to_cpu(sas_device_pg0.SASAddress); |
| 4936 | sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc, | 5166 | sas_device = __mpt3sas_get_sdev_by_addr(ioc, |
| 4937 | sas_address); | 5167 | sas_address); |
| 4938 | 5168 | ||
| 4939 | if (!sas_device) { | 5169 | if (!sas_device) |
| 4940 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 5170 | goto out_unlock; |
| 4941 | return; | ||
| 4942 | } | ||
| 4943 | 5171 | ||
| 4944 | if (unlikely(sas_device->handle != handle)) { | 5172 | if (unlikely(sas_device->handle != handle)) { |
| 4945 | starget = sas_device->starget; | 5173 | starget = sas_device->starget; |
| @@ -4967,20 +5195,25 @@ _scsih_check_device(struct MPT3SAS_ADAPTER *ioc, | |||
| 4967 | pr_err(MPT3SAS_FMT | 5195 | pr_err(MPT3SAS_FMT |
| 4968 | "device is not present handle(0x%04x), flags!!!\n", | 5196 | "device is not present handle(0x%04x), flags!!!\n", |
| 4969 | ioc->name, handle); | 5197 | ioc->name, handle); |
| 4970 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 5198 | goto out_unlock; |
| 4971 | return; | ||
| 4972 | } | 5199 | } |
| 4973 | 5200 | ||
| 4974 | /* check if there were any issues with discovery */ | 5201 | /* check if there were any issues with discovery */ |
| 4975 | if (_scsih_check_access_status(ioc, sas_address, handle, | 5202 | if (_scsih_check_access_status(ioc, sas_address, handle, |
| 4976 | sas_device_pg0.AccessStatus)) { | 5203 | sas_device_pg0.AccessStatus)) |
| 4977 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 5204 | goto out_unlock; |
| 4978 | return; | ||
| 4979 | } | ||
| 4980 | 5205 | ||
| 4981 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 5206 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 4982 | _scsih_ublock_io_device(ioc, sas_address); | 5207 | _scsih_ublock_io_device(ioc, sas_address); |
| 4983 | 5208 | ||
| 5209 | if (sas_device) | ||
| 5210 | sas_device_put(sas_device); | ||
| 5211 | return; | ||
| 5212 | |||
| 5213 | out_unlock: | ||
| 5214 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 5215 | if (sas_device) | ||
| 5216 | sas_device_put(sas_device); | ||
| 4984 | } | 5217 | } |
| 4985 | 5218 | ||
| 4986 | /** | 5219 | /** |
| @@ -5005,7 +5238,6 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num, | |||
| 5005 | u32 ioc_status; | 5238 | u32 ioc_status; |
| 5006 | u64 sas_address; | 5239 | u64 sas_address; |
| 5007 | u32 device_info; | 5240 | u32 device_info; |
| 5008 | unsigned long flags; | ||
| 5009 | 5241 | ||
| 5010 | if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, | 5242 | if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, |
| 5011 | MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { | 5243 | MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { |
| @@ -5041,13 +5273,12 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num, | |||
| 5041 | sas_device_pg0.AccessStatus)) | 5273 | sas_device_pg0.AccessStatus)) |
| 5042 | return -1; | 5274 | return -1; |
| 5043 | 5275 | ||
| 5044 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 5276 | sas_device = mpt3sas_get_sdev_by_addr(ioc, |
| 5045 | sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc, | 5277 | sas_address); |
| 5046 | sas_address); | 5278 | if (sas_device) { |
| 5047 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 5279 | sas_device_put(sas_device); |
| 5048 | |||
| 5049 | if (sas_device) | ||
| 5050 | return -1; | 5280 | return -1; |
| 5281 | } | ||
| 5051 | 5282 | ||
| 5052 | sas_device = kzalloc(sizeof(struct _sas_device), | 5283 | sas_device = kzalloc(sizeof(struct _sas_device), |
| 5053 | GFP_KERNEL); | 5284 | GFP_KERNEL); |
| @@ -5057,6 +5288,7 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num, | |||
| 5057 | return 0; | 5288 | return 0; |
| 5058 | } | 5289 | } |
| 5059 | 5290 | ||
| 5291 | kref_init(&sas_device->refcount); | ||
| 5060 | sas_device->handle = handle; | 5292 | sas_device->handle = handle; |
| 5061 | if (_scsih_get_sas_address(ioc, | 5293 | if (_scsih_get_sas_address(ioc, |
| 5062 | le16_to_cpu(sas_device_pg0.ParentDevHandle), | 5294 | le16_to_cpu(sas_device_pg0.ParentDevHandle), |
| @@ -5098,6 +5330,7 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num, | |||
| 5098 | else | 5330 | else |
| 5099 | _scsih_sas_device_add(ioc, sas_device); | 5331 | _scsih_sas_device_add(ioc, sas_device); |
| 5100 | 5332 | ||
| 5333 | sas_device_put(sas_device); | ||
| 5101 | return 0; | 5334 | return 0; |
| 5102 | } | 5335 | } |
| 5103 | 5336 | ||
| @@ -5144,7 +5377,9 @@ _scsih_remove_device(struct MPT3SAS_ADAPTER *ioc, | |||
| 5144 | sas_target_priv_data->handle = | 5377 | sas_target_priv_data->handle = |
| 5145 | MPT3SAS_INVALID_DEVICE_HANDLE; | 5378 | MPT3SAS_INVALID_DEVICE_HANDLE; |
| 5146 | } | 5379 | } |
| 5147 | mpt3sas_transport_port_remove(ioc, | 5380 | |
| 5381 | if (!ioc->hide_drives) | ||
| 5382 | mpt3sas_transport_port_remove(ioc, | ||
| 5148 | sas_device->sas_address, | 5383 | sas_device->sas_address, |
| 5149 | sas_device->sas_address_parent); | 5384 | sas_device->sas_address_parent); |
| 5150 | 5385 | ||
| @@ -5180,11 +5415,8 @@ _scsih_remove_device(struct MPT3SAS_ADAPTER *ioc, | |||
| 5180 | "%s: exit: enclosure level(0x%04x), connector name(%s)\n", | 5415 | "%s: exit: enclosure level(0x%04x), connector name(%s)\n", |
| 5181 | ioc->name, __func__, sas_device->enclosure_level, | 5416 | ioc->name, __func__, sas_device->enclosure_level, |
| 5182 | sas_device->connector_name)); | 5417 | sas_device->connector_name)); |
| 5183 | |||
| 5184 | kfree(sas_device); | ||
| 5185 | } | 5418 | } |
| 5186 | 5419 | ||
| 5187 | #ifdef CONFIG_SCSI_MPT3SAS_LOGGING | ||
| 5188 | /** | 5420 | /** |
| 5189 | * _scsih_sas_topology_change_event_debug - debug for topology event | 5421 | * _scsih_sas_topology_change_event_debug - debug for topology event |
| 5190 | * @ioc: per adapter object | 5422 | * @ioc: per adapter object |
| @@ -5262,7 +5494,6 @@ _scsih_sas_topology_change_event_debug(struct MPT3SAS_ADAPTER *ioc, | |||
| 5262 | 5494 | ||
| 5263 | } | 5495 | } |
| 5264 | } | 5496 | } |
| 5265 | #endif | ||
| 5266 | 5497 | ||
| 5267 | /** | 5498 | /** |
| 5268 | * _scsih_sas_topology_change_event - handle topology changes | 5499 | * _scsih_sas_topology_change_event - handle topology changes |
| @@ -5287,10 +5518,8 @@ _scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc, | |||
| 5287 | (Mpi2EventDataSasTopologyChangeList_t *) | 5518 | (Mpi2EventDataSasTopologyChangeList_t *) |
| 5288 | fw_event->event_data; | 5519 | fw_event->event_data; |
| 5289 | 5520 | ||
| 5290 | #ifdef CONFIG_SCSI_MPT3SAS_LOGGING | ||
| 5291 | if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) | 5521 | if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) |
| 5292 | _scsih_sas_topology_change_event_debug(ioc, event_data); | 5522 | _scsih_sas_topology_change_event_debug(ioc, event_data); |
| 5293 | #endif | ||
| 5294 | 5523 | ||
| 5295 | if (ioc->shost_recovery || ioc->remove_host || ioc->pci_error_recovery) | 5524 | if (ioc->shost_recovery || ioc->remove_host || ioc->pci_error_recovery) |
| 5296 | return 0; | 5525 | return 0; |
| @@ -5396,7 +5625,6 @@ _scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc, | |||
| 5396 | return 0; | 5625 | return 0; |
| 5397 | } | 5626 | } |
| 5398 | 5627 | ||
| 5399 | #ifdef CONFIG_SCSI_MPT3SAS_LOGGING | ||
| 5400 | /** | 5628 | /** |
| 5401 | * _scsih_sas_device_status_change_event_debug - debug for device event | 5629 | * _scsih_sas_device_status_change_event_debug - debug for device event |
| 5402 | * @event_data: event data payload | 5630 | * @event_data: event data payload |
| @@ -5464,7 +5692,6 @@ _scsih_sas_device_status_change_event_debug(struct MPT3SAS_ADAPTER *ioc, | |||
| 5464 | event_data->ASC, event_data->ASCQ); | 5692 | event_data->ASC, event_data->ASCQ); |
| 5465 | pr_info("\n"); | 5693 | pr_info("\n"); |
| 5466 | } | 5694 | } |
| 5467 | #endif | ||
| 5468 | 5695 | ||
| 5469 | /** | 5696 | /** |
| 5470 | * _scsih_sas_device_status_change_event - handle device status change | 5697 | * _scsih_sas_device_status_change_event - handle device status change |
| @@ -5486,11 +5713,9 @@ _scsih_sas_device_status_change_event(struct MPT3SAS_ADAPTER *ioc, | |||
| 5486 | (Mpi2EventDataSasDeviceStatusChange_t *) | 5713 | (Mpi2EventDataSasDeviceStatusChange_t *) |
| 5487 | fw_event->event_data; | 5714 | fw_event->event_data; |
| 5488 | 5715 | ||
| 5489 | #ifdef CONFIG_SCSI_MPT3SAS_LOGGING | ||
| 5490 | if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) | 5716 | if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) |
| 5491 | _scsih_sas_device_status_change_event_debug(ioc, | 5717 | _scsih_sas_device_status_change_event_debug(ioc, |
| 5492 | event_data); | 5718 | event_data); |
| 5493 | #endif | ||
| 5494 | 5719 | ||
| 5495 | /* In MPI Revision K (0xC), the internal device reset complete was | 5720 | /* In MPI Revision K (0xC), the internal device reset complete was |
| 5496 | * implemented, so avoid setting tm_busy flag for older firmware. | 5721 | * implemented, so avoid setting tm_busy flag for older firmware. |
| @@ -5506,29 +5731,30 @@ _scsih_sas_device_status_change_event(struct MPT3SAS_ADAPTER *ioc, | |||
| 5506 | 5731 | ||
| 5507 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 5732 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 5508 | sas_address = le64_to_cpu(event_data->SASAddress); | 5733 | sas_address = le64_to_cpu(event_data->SASAddress); |
| 5509 | sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc, | 5734 | sas_device = __mpt3sas_get_sdev_by_addr(ioc, |
| 5510 | sas_address); | 5735 | sas_address); |
| 5511 | 5736 | ||
| 5512 | if (!sas_device || !sas_device->starget) { | 5737 | if (!sas_device || !sas_device->starget) |
| 5513 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 5738 | goto out; |
| 5514 | return; | ||
| 5515 | } | ||
| 5516 | 5739 | ||
| 5517 | target_priv_data = sas_device->starget->hostdata; | 5740 | target_priv_data = sas_device->starget->hostdata; |
| 5518 | if (!target_priv_data) { | 5741 | if (!target_priv_data) |
| 5519 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 5742 | goto out; |
| 5520 | return; | ||
| 5521 | } | ||
| 5522 | 5743 | ||
| 5523 | if (event_data->ReasonCode == | 5744 | if (event_data->ReasonCode == |
| 5524 | MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET) | 5745 | MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET) |
| 5525 | target_priv_data->tm_busy = 1; | 5746 | target_priv_data->tm_busy = 1; |
| 5526 | else | 5747 | else |
| 5527 | target_priv_data->tm_busy = 0; | 5748 | target_priv_data->tm_busy = 0; |
| 5749 | |||
| 5750 | out: | ||
| 5751 | if (sas_device) | ||
| 5752 | sas_device_put(sas_device); | ||
| 5753 | |||
| 5528 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 5754 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 5755 | |||
| 5529 | } | 5756 | } |
| 5530 | 5757 | ||
| 5531 | #ifdef CONFIG_SCSI_MPT3SAS_LOGGING | ||
| 5532 | /** | 5758 | /** |
| 5533 | * _scsih_sas_enclosure_dev_status_change_event_debug - debug for enclosure | 5759 | * _scsih_sas_enclosure_dev_status_change_event_debug - debug for enclosure |
| 5534 | * event | 5760 | * event |
| @@ -5563,7 +5789,6 @@ _scsih_sas_enclosure_dev_status_change_event_debug(struct MPT3SAS_ADAPTER *ioc, | |||
| 5563 | (unsigned long long)le64_to_cpu(event_data->EnclosureLogicalID), | 5789 | (unsigned long long)le64_to_cpu(event_data->EnclosureLogicalID), |
| 5564 | le16_to_cpu(event_data->StartSlot)); | 5790 | le16_to_cpu(event_data->StartSlot)); |
| 5565 | } | 5791 | } |
| 5566 | #endif | ||
| 5567 | 5792 | ||
| 5568 | /** | 5793 | /** |
| 5569 | * _scsih_sas_enclosure_dev_status_change_event - handle enclosure events | 5794 | * _scsih_sas_enclosure_dev_status_change_event - handle enclosure events |
| @@ -5577,12 +5802,10 @@ static void | |||
| 5577 | _scsih_sas_enclosure_dev_status_change_event(struct MPT3SAS_ADAPTER *ioc, | 5802 | _scsih_sas_enclosure_dev_status_change_event(struct MPT3SAS_ADAPTER *ioc, |
| 5578 | struct fw_event_work *fw_event) | 5803 | struct fw_event_work *fw_event) |
| 5579 | { | 5804 | { |
| 5580 | #ifdef CONFIG_SCSI_MPT3SAS_LOGGING | ||
| 5581 | if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) | 5805 | if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) |
| 5582 | _scsih_sas_enclosure_dev_status_change_event_debug(ioc, | 5806 | _scsih_sas_enclosure_dev_status_change_event_debug(ioc, |
| 5583 | (Mpi2EventDataSasEnclDevStatusChange_t *) | 5807 | (Mpi2EventDataSasEnclDevStatusChange_t *) |
| 5584 | fw_event->event_data); | 5808 | fw_event->event_data); |
| 5585 | #endif | ||
| 5586 | } | 5809 | } |
| 5587 | 5810 | ||
| 5588 | /** | 5811 | /** |
| @@ -5762,17 +5985,15 @@ _scsih_sas_discovery_event(struct MPT3SAS_ADAPTER *ioc, | |||
| 5762 | Mpi2EventDataSasDiscovery_t *event_data = | 5985 | Mpi2EventDataSasDiscovery_t *event_data = |
| 5763 | (Mpi2EventDataSasDiscovery_t *) fw_event->event_data; | 5986 | (Mpi2EventDataSasDiscovery_t *) fw_event->event_data; |
| 5764 | 5987 | ||
| 5765 | #ifdef CONFIG_SCSI_MPT3SAS_LOGGING | ||
| 5766 | if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) { | 5988 | if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) { |
| 5767 | pr_info(MPT3SAS_FMT "discovery event: (%s)", ioc->name, | 5989 | pr_info(MPT3SAS_FMT "discovery event: (%s)", ioc->name, |
| 5768 | (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED) ? | 5990 | (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED) ? |
| 5769 | "start" : "stop"); | 5991 | "start" : "stop"); |
| 5770 | if (event_data->DiscoveryStatus) | 5992 | if (event_data->DiscoveryStatus) |
| 5771 | pr_info("discovery_status(0x%08x)", | 5993 | pr_info("discovery_status(0x%08x)", |
| 5772 | le32_to_cpu(event_data->DiscoveryStatus)); | 5994 | le32_to_cpu(event_data->DiscoveryStatus)); |
| 5773 | pr_info("\n"); | 5995 | pr_info("\n"); |
| 5774 | } | 5996 | } |
| 5775 | #endif | ||
| 5776 | 5997 | ||
| 5777 | if (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED && | 5998 | if (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED && |
| 5778 | !ioc->sas_hba.num_phys) { | 5999 | !ioc->sas_hba.num_phys) { |
| @@ -5804,6 +6025,8 @@ _scsih_ir_fastpath(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phys_disk_num) | |||
| 5804 | u16 ioc_status; | 6025 | u16 ioc_status; |
| 5805 | u32 log_info; | 6026 | u32 log_info; |
| 5806 | 6027 | ||
| 6028 | if (ioc->hba_mpi_version_belonged == MPI2_VERSION) | ||
| 6029 | return rc; | ||
| 5807 | 6030 | ||
| 5808 | mutex_lock(&ioc->scsih_cmds.mutex); | 6031 | mutex_lock(&ioc->scsih_cmds.mutex); |
| 5809 | 6032 | ||
| @@ -5971,7 +6194,7 @@ _scsih_sas_volume_delete(struct MPT3SAS_ADAPTER *ioc, u16 handle) | |||
| 5971 | struct scsi_target *starget = NULL; | 6194 | struct scsi_target *starget = NULL; |
| 5972 | 6195 | ||
| 5973 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | 6196 | spin_lock_irqsave(&ioc->raid_device_lock, flags); |
| 5974 | raid_device = _scsih_raid_device_find_by_handle(ioc, handle); | 6197 | raid_device = mpt3sas_raid_device_find_by_handle(ioc, handle); |
| 5975 | if (raid_device) { | 6198 | if (raid_device) { |
| 5976 | if (raid_device->starget) { | 6199 | if (raid_device->starget) { |
| 5977 | starget = raid_device->starget; | 6200 | starget = raid_device->starget; |
| @@ -6008,7 +6231,7 @@ _scsih_sas_pd_expose(struct MPT3SAS_ADAPTER *ioc, | |||
| 6008 | u16 handle = le16_to_cpu(element->PhysDiskDevHandle); | 6231 | u16 handle = le16_to_cpu(element->PhysDiskDevHandle); |
| 6009 | 6232 | ||
| 6010 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 6233 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 6011 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | 6234 | sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle); |
| 6012 | if (sas_device) { | 6235 | if (sas_device) { |
| 6013 | sas_device->volume_handle = 0; | 6236 | sas_device->volume_handle = 0; |
| 6014 | sas_device->volume_wwid = 0; | 6237 | sas_device->volume_wwid = 0; |
| @@ -6027,6 +6250,8 @@ _scsih_sas_pd_expose(struct MPT3SAS_ADAPTER *ioc, | |||
| 6027 | /* exposing raid component */ | 6250 | /* exposing raid component */ |
| 6028 | if (starget) | 6251 | if (starget) |
| 6029 | starget_for_each_device(starget, NULL, _scsih_reprobe_lun); | 6252 | starget_for_each_device(starget, NULL, _scsih_reprobe_lun); |
| 6253 | |||
| 6254 | sas_device_put(sas_device); | ||
| 6030 | } | 6255 | } |
| 6031 | 6256 | ||
| 6032 | /** | 6257 | /** |
| @@ -6055,7 +6280,7 @@ _scsih_sas_pd_hide(struct MPT3SAS_ADAPTER *ioc, | |||
| 6055 | &volume_wwid); | 6280 | &volume_wwid); |
| 6056 | 6281 | ||
| 6057 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 6282 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 6058 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | 6283 | sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle); |
| 6059 | if (sas_device) { | 6284 | if (sas_device) { |
| 6060 | set_bit(handle, ioc->pd_handles); | 6285 | set_bit(handle, ioc->pd_handles); |
| 6061 | if (sas_device->starget && sas_device->starget->hostdata) { | 6286 | if (sas_device->starget && sas_device->starget->hostdata) { |
| @@ -6073,8 +6298,11 @@ _scsih_sas_pd_hide(struct MPT3SAS_ADAPTER *ioc, | |||
| 6073 | 6298 | ||
| 6074 | /* hiding raid component */ | 6299 | /* hiding raid component */ |
| 6075 | _scsih_ir_fastpath(ioc, handle, element->PhysDiskNum); | 6300 | _scsih_ir_fastpath(ioc, handle, element->PhysDiskNum); |
| 6301 | |||
| 6076 | if (starget) | 6302 | if (starget) |
| 6077 | starget_for_each_device(starget, (void *)1, _scsih_reprobe_lun); | 6303 | starget_for_each_device(starget, (void *)1, _scsih_reprobe_lun); |
| 6304 | |||
| 6305 | sas_device_put(sas_device); | ||
| 6078 | } | 6306 | } |
| 6079 | 6307 | ||
| 6080 | /** | 6308 | /** |
| @@ -6107,7 +6335,6 @@ _scsih_sas_pd_add(struct MPT3SAS_ADAPTER *ioc, | |||
| 6107 | Mpi2EventIrConfigElement_t *element) | 6335 | Mpi2EventIrConfigElement_t *element) |
| 6108 | { | 6336 | { |
| 6109 | struct _sas_device *sas_device; | 6337 | struct _sas_device *sas_device; |
| 6110 | unsigned long flags; | ||
| 6111 | u16 handle = le16_to_cpu(element->PhysDiskDevHandle); | 6338 | u16 handle = le16_to_cpu(element->PhysDiskDevHandle); |
| 6112 | Mpi2ConfigReply_t mpi_reply; | 6339 | Mpi2ConfigReply_t mpi_reply; |
| 6113 | Mpi2SasDevicePage0_t sas_device_pg0; | 6340 | Mpi2SasDevicePage0_t sas_device_pg0; |
| @@ -6117,11 +6344,10 @@ _scsih_sas_pd_add(struct MPT3SAS_ADAPTER *ioc, | |||
| 6117 | 6344 | ||
| 6118 | set_bit(handle, ioc->pd_handles); | 6345 | set_bit(handle, ioc->pd_handles); |
| 6119 | 6346 | ||
| 6120 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 6347 | sas_device = mpt3sas_get_sdev_by_handle(ioc, handle); |
| 6121 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | ||
| 6122 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 6123 | if (sas_device) { | 6348 | if (sas_device) { |
| 6124 | _scsih_ir_fastpath(ioc, handle, element->PhysDiskNum); | 6349 | _scsih_ir_fastpath(ioc, handle, element->PhysDiskNum); |
| 6350 | sas_device_put(sas_device); | ||
| 6125 | return; | 6351 | return; |
| 6126 | } | 6352 | } |
| 6127 | 6353 | ||
| @@ -6149,7 +6375,6 @@ _scsih_sas_pd_add(struct MPT3SAS_ADAPTER *ioc, | |||
| 6149 | _scsih_add_device(ioc, handle, 0, 1); | 6375 | _scsih_add_device(ioc, handle, 0, 1); |
| 6150 | } | 6376 | } |
| 6151 | 6377 | ||
| 6152 | #ifdef CONFIG_SCSI_MPT3SAS_LOGGING | ||
| 6153 | /** | 6378 | /** |
| 6154 | * _scsih_sas_ir_config_change_event_debug - debug for IR Config Change events | 6379 | * _scsih_sas_ir_config_change_event_debug - debug for IR Config Change events |
| 6155 | * @ioc: per adapter object | 6380 | * @ioc: per adapter object |
| @@ -6229,7 +6454,6 @@ _scsih_sas_ir_config_change_event_debug(struct MPT3SAS_ADAPTER *ioc, | |||
| 6229 | element->PhysDiskNum); | 6454 | element->PhysDiskNum); |
| 6230 | } | 6455 | } |
| 6231 | } | 6456 | } |
| 6232 | #endif | ||
| 6233 | 6457 | ||
| 6234 | /** | 6458 | /** |
| 6235 | * _scsih_sas_ir_config_change_event - handle ir configuration change events | 6459 | * _scsih_sas_ir_config_change_event - handle ir configuration change events |
| @@ -6250,18 +6474,16 @@ _scsih_sas_ir_config_change_event(struct MPT3SAS_ADAPTER *ioc, | |||
| 6250 | (Mpi2EventDataIrConfigChangeList_t *) | 6474 | (Mpi2EventDataIrConfigChangeList_t *) |
| 6251 | fw_event->event_data; | 6475 | fw_event->event_data; |
| 6252 | 6476 | ||
| 6253 | #ifdef CONFIG_SCSI_MPT3SAS_LOGGING | 6477 | if ((ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) && |
| 6254 | if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) | 6478 | (!ioc->hide_ir_msg)) |
| 6255 | _scsih_sas_ir_config_change_event_debug(ioc, event_data); | 6479 | _scsih_sas_ir_config_change_event_debug(ioc, event_data); |
| 6256 | 6480 | ||
| 6257 | #endif | ||
| 6258 | |||
| 6259 | foreign_config = (le32_to_cpu(event_data->Flags) & | 6481 | foreign_config = (le32_to_cpu(event_data->Flags) & |
| 6260 | MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0; | 6482 | MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0; |
| 6261 | 6483 | ||
| 6262 | element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; | 6484 | element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; |
| 6263 | if (ioc->shost_recovery) { | 6485 | if (ioc->shost_recovery && |
| 6264 | 6486 | ioc->hba_mpi_version_belonged != MPI2_VERSION) { | |
| 6265 | for (i = 0; i < event_data->NumElements; i++, element++) { | 6487 | for (i = 0; i < event_data->NumElements; i++, element++) { |
| 6266 | if (element->ReasonCode == MPI2_EVENT_IR_CHANGE_RC_HIDE) | 6488 | if (element->ReasonCode == MPI2_EVENT_IR_CHANGE_RC_HIDE) |
| 6267 | _scsih_ir_fastpath(ioc, | 6489 | _scsih_ir_fastpath(ioc, |
| @@ -6270,6 +6492,7 @@ _scsih_sas_ir_config_change_event(struct MPT3SAS_ADAPTER *ioc, | |||
| 6270 | } | 6492 | } |
| 6271 | return; | 6493 | return; |
| 6272 | } | 6494 | } |
| 6495 | |||
| 6273 | for (i = 0; i < event_data->NumElements; i++, element++) { | 6496 | for (i = 0; i < event_data->NumElements; i++, element++) { |
| 6274 | 6497 | ||
| 6275 | switch (element->ReasonCode) { | 6498 | switch (element->ReasonCode) { |
| @@ -6285,16 +6508,20 @@ _scsih_sas_ir_config_change_event(struct MPT3SAS_ADAPTER *ioc, | |||
| 6285 | le16_to_cpu(element->VolDevHandle)); | 6508 | le16_to_cpu(element->VolDevHandle)); |
| 6286 | break; | 6509 | break; |
| 6287 | case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED: | 6510 | case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED: |
| 6288 | _scsih_sas_pd_hide(ioc, element); | 6511 | if (!ioc->is_warpdrive) |
| 6512 | _scsih_sas_pd_hide(ioc, element); | ||
| 6289 | break; | 6513 | break; |
| 6290 | case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED: | 6514 | case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED: |
| 6291 | _scsih_sas_pd_expose(ioc, element); | 6515 | if (!ioc->is_warpdrive) |
| 6516 | _scsih_sas_pd_expose(ioc, element); | ||
| 6292 | break; | 6517 | break; |
| 6293 | case MPI2_EVENT_IR_CHANGE_RC_HIDE: | 6518 | case MPI2_EVENT_IR_CHANGE_RC_HIDE: |
| 6294 | _scsih_sas_pd_add(ioc, element); | 6519 | if (!ioc->is_warpdrive) |
| 6520 | _scsih_sas_pd_add(ioc, element); | ||
| 6295 | break; | 6521 | break; |
| 6296 | case MPI2_EVENT_IR_CHANGE_RC_UNHIDE: | 6522 | case MPI2_EVENT_IR_CHANGE_RC_UNHIDE: |
| 6297 | _scsih_sas_pd_delete(ioc, element); | 6523 | if (!ioc->is_warpdrive) |
| 6524 | _scsih_sas_pd_delete(ioc, element); | ||
| 6298 | break; | 6525 | break; |
| 6299 | } | 6526 | } |
| 6300 | } | 6527 | } |
| @@ -6329,10 +6556,11 @@ _scsih_sas_ir_volume_event(struct MPT3SAS_ADAPTER *ioc, | |||
| 6329 | 6556 | ||
| 6330 | handle = le16_to_cpu(event_data->VolDevHandle); | 6557 | handle = le16_to_cpu(event_data->VolDevHandle); |
| 6331 | state = le32_to_cpu(event_data->NewValue); | 6558 | state = le32_to_cpu(event_data->NewValue); |
| 6332 | dewtprintk(ioc, pr_info(MPT3SAS_FMT | 6559 | if (!ioc->hide_ir_msg) |
| 6333 | "%s: handle(0x%04x), old(0x%08x), new(0x%08x)\n", | 6560 | dewtprintk(ioc, pr_info(MPT3SAS_FMT |
| 6334 | ioc->name, __func__, handle, | 6561 | "%s: handle(0x%04x), old(0x%08x), new(0x%08x)\n", |
| 6335 | le32_to_cpu(event_data->PreviousValue), state)); | 6562 | ioc->name, __func__, handle, |
| 6563 | le32_to_cpu(event_data->PreviousValue), state)); | ||
| 6336 | switch (state) { | 6564 | switch (state) { |
| 6337 | case MPI2_RAID_VOL_STATE_MISSING: | 6565 | case MPI2_RAID_VOL_STATE_MISSING: |
| 6338 | case MPI2_RAID_VOL_STATE_FAILED: | 6566 | case MPI2_RAID_VOL_STATE_FAILED: |
| @@ -6344,7 +6572,7 @@ _scsih_sas_ir_volume_event(struct MPT3SAS_ADAPTER *ioc, | |||
| 6344 | case MPI2_RAID_VOL_STATE_OPTIMAL: | 6572 | case MPI2_RAID_VOL_STATE_OPTIMAL: |
| 6345 | 6573 | ||
| 6346 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | 6574 | spin_lock_irqsave(&ioc->raid_device_lock, flags); |
| 6347 | raid_device = _scsih_raid_device_find_by_handle(ioc, handle); | 6575 | raid_device = mpt3sas_raid_device_find_by_handle(ioc, handle); |
| 6348 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); | 6576 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); |
| 6349 | 6577 | ||
| 6350 | if (raid_device) | 6578 | if (raid_device) |
| @@ -6398,7 +6626,6 @@ _scsih_sas_ir_physical_disk_event(struct MPT3SAS_ADAPTER *ioc, | |||
| 6398 | u16 handle, parent_handle; | 6626 | u16 handle, parent_handle; |
| 6399 | u32 state; | 6627 | u32 state; |
| 6400 | struct _sas_device *sas_device; | 6628 | struct _sas_device *sas_device; |
| 6401 | unsigned long flags; | ||
| 6402 | Mpi2ConfigReply_t mpi_reply; | 6629 | Mpi2ConfigReply_t mpi_reply; |
| 6403 | Mpi2SasDevicePage0_t sas_device_pg0; | 6630 | Mpi2SasDevicePage0_t sas_device_pg0; |
| 6404 | u32 ioc_status; | 6631 | u32 ioc_status; |
| @@ -6415,10 +6642,12 @@ _scsih_sas_ir_physical_disk_event(struct MPT3SAS_ADAPTER *ioc, | |||
| 6415 | handle = le16_to_cpu(event_data->PhysDiskDevHandle); | 6642 | handle = le16_to_cpu(event_data->PhysDiskDevHandle); |
| 6416 | state = le32_to_cpu(event_data->NewValue); | 6643 | state = le32_to_cpu(event_data->NewValue); |
| 6417 | 6644 | ||
| 6418 | dewtprintk(ioc, pr_info(MPT3SAS_FMT | 6645 | if (!ioc->hide_ir_msg) |
| 6419 | "%s: handle(0x%04x), old(0x%08x), new(0x%08x)\n", | 6646 | dewtprintk(ioc, pr_info(MPT3SAS_FMT |
| 6420 | ioc->name, __func__, handle, | 6647 | "%s: handle(0x%04x), old(0x%08x), new(0x%08x)\n", |
| 6648 | ioc->name, __func__, handle, | ||
| 6421 | le32_to_cpu(event_data->PreviousValue), state)); | 6649 | le32_to_cpu(event_data->PreviousValue), state)); |
| 6650 | |||
| 6422 | switch (state) { | 6651 | switch (state) { |
| 6423 | case MPI2_RAID_PD_STATE_ONLINE: | 6652 | case MPI2_RAID_PD_STATE_ONLINE: |
| 6424 | case MPI2_RAID_PD_STATE_DEGRADED: | 6653 | case MPI2_RAID_PD_STATE_DEGRADED: |
| @@ -6426,13 +6655,14 @@ _scsih_sas_ir_physical_disk_event(struct MPT3SAS_ADAPTER *ioc, | |||
| 6426 | case MPI2_RAID_PD_STATE_OPTIMAL: | 6655 | case MPI2_RAID_PD_STATE_OPTIMAL: |
| 6427 | case MPI2_RAID_PD_STATE_HOT_SPARE: | 6656 | case MPI2_RAID_PD_STATE_HOT_SPARE: |
| 6428 | 6657 | ||
| 6429 | set_bit(handle, ioc->pd_handles); | 6658 | if (!ioc->is_warpdrive) |
| 6430 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 6659 | set_bit(handle, ioc->pd_handles); |
| 6431 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | ||
| 6432 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 6433 | 6660 | ||
| 6434 | if (sas_device) | 6661 | sas_device = mpt3sas_get_sdev_by_handle(ioc, handle); |
| 6662 | if (sas_device) { | ||
| 6663 | sas_device_put(sas_device); | ||
| 6435 | return; | 6664 | return; |
| 6665 | } | ||
| 6436 | 6666 | ||
| 6437 | if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, | 6667 | if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, |
| 6438 | &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, | 6668 | &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, |
| @@ -6467,7 +6697,6 @@ _scsih_sas_ir_physical_disk_event(struct MPT3SAS_ADAPTER *ioc, | |||
| 6467 | } | 6697 | } |
| 6468 | } | 6698 | } |
| 6469 | 6699 | ||
| 6470 | #ifdef CONFIG_SCSI_MPT3SAS_LOGGING | ||
| 6471 | /** | 6700 | /** |
| 6472 | * _scsih_sas_ir_operation_status_event_debug - debug for IR op event | 6701 | * _scsih_sas_ir_operation_status_event_debug - debug for IR op event |
| 6473 | * @ioc: per adapter object | 6702 | * @ioc: per adapter object |
| @@ -6509,7 +6738,6 @@ _scsih_sas_ir_operation_status_event_debug(struct MPT3SAS_ADAPTER *ioc, | |||
| 6509 | le16_to_cpu(event_data->VolDevHandle), | 6738 | le16_to_cpu(event_data->VolDevHandle), |
| 6510 | event_data->PercentComplete); | 6739 | event_data->PercentComplete); |
| 6511 | } | 6740 | } |
| 6512 | #endif | ||
| 6513 | 6741 | ||
| 6514 | /** | 6742 | /** |
| 6515 | * _scsih_sas_ir_operation_status_event - handle RAID operation events | 6743 | * _scsih_sas_ir_operation_status_event - handle RAID operation events |
| @@ -6530,18 +6758,17 @@ _scsih_sas_ir_operation_status_event(struct MPT3SAS_ADAPTER *ioc, | |||
| 6530 | unsigned long flags; | 6758 | unsigned long flags; |
| 6531 | u16 handle; | 6759 | u16 handle; |
| 6532 | 6760 | ||
| 6533 | #ifdef CONFIG_SCSI_MPT3SAS_LOGGING | 6761 | if ((ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) && |
| 6534 | if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) | 6762 | (!ioc->hide_ir_msg)) |
| 6535 | _scsih_sas_ir_operation_status_event_debug(ioc, | 6763 | _scsih_sas_ir_operation_status_event_debug(ioc, |
| 6536 | event_data); | 6764 | event_data); |
| 6537 | #endif | ||
| 6538 | 6765 | ||
| 6539 | /* code added for raid transport support */ | 6766 | /* code added for raid transport support */ |
| 6540 | if (event_data->RAIDOperation == MPI2_EVENT_IR_RAIDOP_RESYNC) { | 6767 | if (event_data->RAIDOperation == MPI2_EVENT_IR_RAIDOP_RESYNC) { |
| 6541 | 6768 | ||
| 6542 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | 6769 | spin_lock_irqsave(&ioc->raid_device_lock, flags); |
| 6543 | handle = le16_to_cpu(event_data->VolDevHandle); | 6770 | handle = le16_to_cpu(event_data->VolDevHandle); |
| 6544 | raid_device = _scsih_raid_device_find_by_handle(ioc, handle); | 6771 | raid_device = mpt3sas_raid_device_find_by_handle(ioc, handle); |
| 6545 | if (raid_device) | 6772 | if (raid_device) |
| 6546 | raid_device->percent_complete = | 6773 | raid_device->percent_complete = |
| 6547 | event_data->PercentComplete; | 6774 | event_data->PercentComplete; |
| @@ -6703,7 +6930,7 @@ static void | |||
| 6703 | _scsih_mark_responding_raid_device(struct MPT3SAS_ADAPTER *ioc, u64 wwid, | 6930 | _scsih_mark_responding_raid_device(struct MPT3SAS_ADAPTER *ioc, u64 wwid, |
| 6704 | u16 handle) | 6931 | u16 handle) |
| 6705 | { | 6932 | { |
| 6706 | struct MPT3SAS_TARGET *sas_target_priv_data; | 6933 | struct MPT3SAS_TARGET *sas_target_priv_data = NULL; |
| 6707 | struct scsi_target *starget; | 6934 | struct scsi_target *starget; |
| 6708 | struct _raid_device *raid_device; | 6935 | struct _raid_device *raid_device; |
| 6709 | unsigned long flags; | 6936 | unsigned long flags; |
| @@ -6722,6 +6949,13 @@ _scsih_mark_responding_raid_device(struct MPT3SAS_ADAPTER *ioc, u64 wwid, | |||
| 6722 | starget_printk(KERN_INFO, raid_device->starget, | 6949 | starget_printk(KERN_INFO, raid_device->starget, |
| 6723 | "handle(0x%04x), wwid(0x%016llx)\n", handle, | 6950 | "handle(0x%04x), wwid(0x%016llx)\n", handle, |
| 6724 | (unsigned long long)raid_device->wwid); | 6951 | (unsigned long long)raid_device->wwid); |
| 6952 | |||
| 6953 | /* | ||
| 6954 | * WARPDRIVE: The handles of the PDs might have changed | ||
| 6955 | * across the host reset so re-initialize the | ||
| 6956 | * required data for Direct IO | ||
| 6957 | */ | ||
| 6958 | mpt3sas_init_warpdrive_properties(ioc, raid_device); | ||
| 6725 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | 6959 | spin_lock_irqsave(&ioc->raid_device_lock, flags); |
| 6726 | if (raid_device->handle == handle) { | 6960 | if (raid_device->handle == handle) { |
| 6727 | spin_unlock_irqrestore(&ioc->raid_device_lock, | 6961 | spin_unlock_irqrestore(&ioc->raid_device_lock, |
| @@ -6791,6 +7025,7 @@ _scsih_search_responding_raid_devices(struct MPT3SAS_ADAPTER *ioc) | |||
| 6791 | } | 7025 | } |
| 6792 | 7026 | ||
| 6793 | /* refresh the pd_handles */ | 7027 | /* refresh the pd_handles */ |
| 7028 | if (!ioc->is_warpdrive) { | ||
| 6794 | phys_disk_num = 0xFF; | 7029 | phys_disk_num = 0xFF; |
| 6795 | memset(ioc->pd_handles, 0, ioc->pd_handles_sz); | 7030 | memset(ioc->pd_handles, 0, ioc->pd_handles_sz); |
| 6796 | while (!(mpt3sas_config_get_phys_disk_pg0(ioc, &mpi_reply, | 7031 | while (!(mpt3sas_config_get_phys_disk_pg0(ioc, &mpi_reply, |
| @@ -6804,6 +7039,7 @@ _scsih_search_responding_raid_devices(struct MPT3SAS_ADAPTER *ioc) | |||
| 6804 | handle = le16_to_cpu(pd_pg0.DevHandle); | 7039 | handle = le16_to_cpu(pd_pg0.DevHandle); |
| 6805 | set_bit(handle, ioc->pd_handles); | 7040 | set_bit(handle, ioc->pd_handles); |
| 6806 | } | 7041 | } |
| 7042 | } | ||
| 6807 | out: | 7043 | out: |
| 6808 | pr_info(MPT3SAS_FMT "search for responding raid volumes: complete\n", | 7044 | pr_info(MPT3SAS_FMT "search for responding raid volumes: complete\n", |
| 6809 | ioc->name); | 7045 | ioc->name); |
| @@ -6906,6 +7142,7 @@ _scsih_remove_unresponding_sas_devices(struct MPT3SAS_ADAPTER *ioc) | |||
| 6906 | struct _raid_device *raid_device, *raid_device_next; | 7142 | struct _raid_device *raid_device, *raid_device_next; |
| 6907 | struct list_head tmp_list; | 7143 | struct list_head tmp_list; |
| 6908 | unsigned long flags; | 7144 | unsigned long flags; |
| 7145 | LIST_HEAD(head); | ||
| 6909 | 7146 | ||
| 6910 | pr_info(MPT3SAS_FMT "removing unresponding devices: start\n", | 7147 | pr_info(MPT3SAS_FMT "removing unresponding devices: start\n", |
| 6911 | ioc->name); | 7148 | ioc->name); |
| @@ -6913,14 +7150,28 @@ _scsih_remove_unresponding_sas_devices(struct MPT3SAS_ADAPTER *ioc) | |||
| 6913 | /* removing unresponding end devices */ | 7150 | /* removing unresponding end devices */ |
| 6914 | pr_info(MPT3SAS_FMT "removing unresponding devices: end-devices\n", | 7151 | pr_info(MPT3SAS_FMT "removing unresponding devices: end-devices\n", |
| 6915 | ioc->name); | 7152 | ioc->name); |
| 7153 | /* | ||
| 7154 | * Iterate, pulling off devices marked as non-responding. We become the | ||
| 7155 | * owner for the reference the list had on any object we prune. | ||
| 7156 | */ | ||
| 7157 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 6916 | list_for_each_entry_safe(sas_device, sas_device_next, | 7158 | list_for_each_entry_safe(sas_device, sas_device_next, |
| 6917 | &ioc->sas_device_list, list) { | 7159 | &ioc->sas_device_list, list) { |
| 6918 | if (!sas_device->responding) | 7160 | if (!sas_device->responding) |
| 6919 | mpt3sas_device_remove_by_sas_address(ioc, | 7161 | list_move_tail(&sas_device->list, &head); |
| 6920 | sas_device->sas_address); | ||
| 6921 | else | 7162 | else |
| 6922 | sas_device->responding = 0; | 7163 | sas_device->responding = 0; |
| 6923 | } | 7164 | } |
| 7165 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 7166 | |||
| 7167 | /* | ||
| 7168 | * Now, uninitialize and remove the unresponding devices we pruned. | ||
| 7169 | */ | ||
| 7170 | list_for_each_entry_safe(sas_device, sas_device_next, &head, list) { | ||
| 7171 | _scsih_remove_device(ioc, sas_device); | ||
| 7172 | list_del_init(&sas_device->list); | ||
| 7173 | sas_device_put(sas_device); | ||
| 7174 | } | ||
| 6924 | 7175 | ||
| 6925 | /* removing unresponding volumes */ | 7176 | /* removing unresponding volumes */ |
| 6926 | if (ioc->ir_firmware) { | 7177 | if (ioc->ir_firmware) { |
| @@ -7074,11 +7325,11 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc) | |||
| 7074 | } | 7325 | } |
| 7075 | phys_disk_num = pd_pg0.PhysDiskNum; | 7326 | phys_disk_num = pd_pg0.PhysDiskNum; |
| 7076 | handle = le16_to_cpu(pd_pg0.DevHandle); | 7327 | handle = le16_to_cpu(pd_pg0.DevHandle); |
| 7077 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 7328 | sas_device = mpt3sas_get_sdev_by_handle(ioc, handle); |
| 7078 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | 7329 | if (sas_device) { |
| 7079 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 7330 | sas_device_put(sas_device); |
| 7080 | if (sas_device) | ||
| 7081 | continue; | 7331 | continue; |
| 7332 | } | ||
| 7082 | if (mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, | 7333 | if (mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, |
| 7083 | &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, | 7334 | &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, |
| 7084 | handle) != 0) | 7335 | handle) != 0) |
| @@ -7199,12 +7450,12 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc) | |||
| 7199 | if (!(_scsih_is_end_device( | 7450 | if (!(_scsih_is_end_device( |
| 7200 | le32_to_cpu(sas_device_pg0.DeviceInfo)))) | 7451 | le32_to_cpu(sas_device_pg0.DeviceInfo)))) |
| 7201 | continue; | 7452 | continue; |
| 7202 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 7453 | sas_device = mpt3sas_get_sdev_by_addr(ioc, |
| 7203 | sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc, | ||
| 7204 | le64_to_cpu(sas_device_pg0.SASAddress)); | 7454 | le64_to_cpu(sas_device_pg0.SASAddress)); |
| 7205 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 7455 | if (sas_device) { |
| 7206 | if (sas_device) | 7456 | sas_device_put(sas_device); |
| 7207 | continue; | 7457 | continue; |
| 7458 | } | ||
| 7208 | parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle); | 7459 | parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle); |
| 7209 | if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) { | 7460 | if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) { |
| 7210 | pr_info(MPT3SAS_FMT "\tBEFORE adding end device: " \ | 7461 | pr_info(MPT3SAS_FMT "\tBEFORE adding end device: " \ |
| @@ -7296,10 +7547,11 @@ mpt3sas_scsih_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase) | |||
| 7296 | static void | 7547 | static void |
| 7297 | _mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event) | 7548 | _mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event) |
| 7298 | { | 7549 | { |
| 7550 | _scsih_fw_event_del_from_list(ioc, fw_event); | ||
| 7551 | |||
| 7299 | /* the queue is being flushed so ignore this event */ | 7552 | /* the queue is being flushed so ignore this event */ |
| 7300 | if (ioc->remove_host || | 7553 | if (ioc->remove_host || ioc->pci_error_recovery) { |
| 7301 | ioc->pci_error_recovery) { | 7554 | fw_event_work_put(fw_event); |
| 7302 | _scsih_fw_event_free(ioc, fw_event); | ||
| 7303 | return; | 7555 | return; |
| 7304 | } | 7556 | } |
| 7305 | 7557 | ||
| @@ -7310,8 +7562,16 @@ _mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event) | |||
| 7310 | fw_event->event_data); | 7562 | fw_event->event_data); |
| 7311 | break; | 7563 | break; |
| 7312 | case MPT3SAS_REMOVE_UNRESPONDING_DEVICES: | 7564 | case MPT3SAS_REMOVE_UNRESPONDING_DEVICES: |
| 7313 | while (scsi_host_in_recovery(ioc->shost) || ioc->shost_recovery) | 7565 | while (scsi_host_in_recovery(ioc->shost) || |
| 7566 | ioc->shost_recovery) { | ||
| 7567 | /* | ||
| 7568 | * If we're unloading, bail. Otherwise, this can become | ||
| 7569 | * an infinite loop. | ||
| 7570 | */ | ||
| 7571 | if (ioc->remove_host) | ||
| 7572 | goto out; | ||
| 7314 | ssleep(1); | 7573 | ssleep(1); |
| 7574 | } | ||
| 7315 | _scsih_remove_unresponding_sas_devices(ioc); | 7575 | _scsih_remove_unresponding_sas_devices(ioc); |
| 7316 | _scsih_scan_for_devices_after_reset(ioc); | 7576 | _scsih_scan_for_devices_after_reset(ioc); |
| 7317 | break; | 7577 | break; |
| @@ -7356,7 +7616,8 @@ _mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event) | |||
| 7356 | _scsih_sas_ir_operation_status_event(ioc, fw_event); | 7616 | _scsih_sas_ir_operation_status_event(ioc, fw_event); |
| 7357 | break; | 7617 | break; |
| 7358 | } | 7618 | } |
| 7359 | _scsih_fw_event_free(ioc, fw_event); | 7619 | out: |
| 7620 | fw_event_work_put(fw_event); | ||
| 7360 | } | 7621 | } |
| 7361 | 7622 | ||
| 7362 | /** | 7623 | /** |
| @@ -7453,7 +7714,53 @@ mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index, | |||
| 7453 | (Mpi2EventDataIrVolume_t *) | 7714 | (Mpi2EventDataIrVolume_t *) |
| 7454 | mpi_reply->EventData); | 7715 | mpi_reply->EventData); |
| 7455 | break; | 7716 | break; |
| 7717 | case MPI2_EVENT_LOG_ENTRY_ADDED: | ||
| 7718 | { | ||
| 7719 | Mpi2EventDataLogEntryAdded_t *log_entry; | ||
| 7720 | u32 *log_code; | ||
| 7721 | |||
| 7722 | if (!ioc->is_warpdrive) | ||
| 7723 | break; | ||
| 7724 | |||
| 7725 | log_entry = (Mpi2EventDataLogEntryAdded_t *) | ||
| 7726 | mpi_reply->EventData; | ||
| 7727 | log_code = (u32 *)log_entry->LogData; | ||
| 7456 | 7728 | ||
| 7729 | if (le16_to_cpu(log_entry->LogEntryQualifier) | ||
| 7730 | != MPT2_WARPDRIVE_LOGENTRY) | ||
| 7731 | break; | ||
| 7732 | |||
| 7733 | switch (le32_to_cpu(*log_code)) { | ||
| 7734 | case MPT2_WARPDRIVE_LC_SSDT: | ||
| 7735 | pr_warn(MPT3SAS_FMT "WarpDrive Warning: " | ||
| 7736 | "IO Throttling has occurred in the WarpDrive " | ||
| 7737 | "subsystem. Check WarpDrive documentation for " | ||
| 7738 | "additional details.\n", ioc->name); | ||
| 7739 | break; | ||
| 7740 | case MPT2_WARPDRIVE_LC_SSDLW: | ||
| 7741 | pr_warn(MPT3SAS_FMT "WarpDrive Warning: " | ||
| 7742 | "Program/Erase Cycles for the WarpDrive subsystem " | ||
| 7743 | "in degraded range. Check WarpDrive documentation " | ||
| 7744 | "for additional details.\n", ioc->name); | ||
| 7745 | break; | ||
| 7746 | case MPT2_WARPDRIVE_LC_SSDLF: | ||
| 7747 | pr_err(MPT3SAS_FMT "WarpDrive Fatal Error: " | ||
| 7748 | "There are no Program/Erase Cycles for the " | ||
| 7749 | "WarpDrive subsystem. The storage device will be " | ||
| 7750 | "in read-only mode. Check WarpDrive documentation " | ||
| 7751 | "for additional details.\n", ioc->name); | ||
| 7752 | break; | ||
| 7753 | case MPT2_WARPDRIVE_LC_BRMF: | ||
| 7754 | pr_err(MPT3SAS_FMT "WarpDrive Fatal Error: " | ||
| 7755 | "The Backup Rail Monitor has failed on the " | ||
| 7756 | "WarpDrive subsystem. Check WarpDrive " | ||
| 7757 | "documentation for additional details.\n", | ||
| 7758 | ioc->name); | ||
| 7759 | break; | ||
| 7760 | } | ||
| 7761 | |||
| 7762 | break; | ||
| 7763 | } | ||
| 7457 | case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE: | 7764 | case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE: |
| 7458 | case MPI2_EVENT_IR_OPERATION_STATUS: | 7765 | case MPI2_EVENT_IR_OPERATION_STATUS: |
| 7459 | case MPI2_EVENT_SAS_DISCOVERY: | 7766 | case MPI2_EVENT_SAS_DISCOVERY: |
| @@ -7472,7 +7779,7 @@ mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index, | |||
| 7472 | } | 7779 | } |
| 7473 | 7780 | ||
| 7474 | sz = le16_to_cpu(mpi_reply->EventDataLength) * 4; | 7781 | sz = le16_to_cpu(mpi_reply->EventDataLength) * 4; |
| 7475 | fw_event = kzalloc(sizeof(*fw_event) + sz, GFP_ATOMIC); | 7782 | fw_event = alloc_fw_event_work(sz); |
| 7476 | if (!fw_event) { | 7783 | if (!fw_event) { |
| 7477 | pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", | 7784 | pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", |
| 7478 | ioc->name, __FILE__, __LINE__, __func__); | 7785 | ioc->name, __FILE__, __LINE__, __func__); |
| @@ -7485,39 +7792,10 @@ mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index, | |||
| 7485 | fw_event->VP_ID = mpi_reply->VP_ID; | 7792 | fw_event->VP_ID = mpi_reply->VP_ID; |
| 7486 | fw_event->event = event; | 7793 | fw_event->event = event; |
| 7487 | _scsih_fw_event_add(ioc, fw_event); | 7794 | _scsih_fw_event_add(ioc, fw_event); |
| 7795 | fw_event_work_put(fw_event); | ||
| 7488 | return 1; | 7796 | return 1; |
| 7489 | } | 7797 | } |
| 7490 | 7798 | ||
| 7491 | /* shost template */ | ||
| 7492 | static struct scsi_host_template scsih_driver_template = { | ||
| 7493 | .module = THIS_MODULE, | ||
| 7494 | .name = "Fusion MPT SAS Host", | ||
| 7495 | .proc_name = MPT3SAS_DRIVER_NAME, | ||
| 7496 | .queuecommand = _scsih_qcmd, | ||
| 7497 | .target_alloc = _scsih_target_alloc, | ||
| 7498 | .slave_alloc = _scsih_slave_alloc, | ||
| 7499 | .slave_configure = _scsih_slave_configure, | ||
| 7500 | .target_destroy = _scsih_target_destroy, | ||
| 7501 | .slave_destroy = _scsih_slave_destroy, | ||
| 7502 | .scan_finished = _scsih_scan_finished, | ||
| 7503 | .scan_start = _scsih_scan_start, | ||
| 7504 | .change_queue_depth = _scsih_change_queue_depth, | ||
| 7505 | .eh_abort_handler = _scsih_abort, | ||
| 7506 | .eh_device_reset_handler = _scsih_dev_reset, | ||
| 7507 | .eh_target_reset_handler = _scsih_target_reset, | ||
| 7508 | .eh_host_reset_handler = _scsih_host_reset, | ||
| 7509 | .bios_param = _scsih_bios_param, | ||
| 7510 | .can_queue = 1, | ||
| 7511 | .this_id = -1, | ||
| 7512 | .sg_tablesize = MPT3SAS_SG_DEPTH, | ||
| 7513 | .max_sectors = 32767, | ||
| 7514 | .cmd_per_lun = 7, | ||
| 7515 | .use_clustering = ENABLE_CLUSTERING, | ||
| 7516 | .shost_attrs = mpt3sas_host_attrs, | ||
| 7517 | .sdev_attrs = mpt3sas_dev_attrs, | ||
| 7518 | .track_queue_depth = 1, | ||
| 7519 | }; | ||
| 7520 | |||
| 7521 | /** | 7799 | /** |
| 7522 | * _scsih_expander_node_remove - removing expander device from list. | 7800 | * _scsih_expander_node_remove - removing expander device from list. |
| 7523 | * @ioc: per adapter object | 7801 | * @ioc: per adapter object |
| @@ -7613,7 +7891,8 @@ _scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc) | |||
| 7613 | mpi_request->Function = MPI2_FUNCTION_RAID_ACTION; | 7891 | mpi_request->Function = MPI2_FUNCTION_RAID_ACTION; |
| 7614 | mpi_request->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED; | 7892 | mpi_request->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED; |
| 7615 | 7893 | ||
| 7616 | pr_info(MPT3SAS_FMT "IR shutdown (sending)\n", ioc->name); | 7894 | if (!ioc->hide_ir_msg) |
| 7895 | pr_info(MPT3SAS_FMT "IR shutdown (sending)\n", ioc->name); | ||
| 7617 | init_completion(&ioc->scsih_cmds.done); | 7896 | init_completion(&ioc->scsih_cmds.done); |
| 7618 | mpt3sas_base_put_smid_default(ioc, smid); | 7897 | mpt3sas_base_put_smid_default(ioc, smid); |
| 7619 | wait_for_completion_timeout(&ioc->scsih_cmds.done, 10*HZ); | 7898 | wait_for_completion_timeout(&ioc->scsih_cmds.done, 10*HZ); |
| @@ -7626,10 +7905,11 @@ _scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc) | |||
| 7626 | 7905 | ||
| 7627 | if (ioc->scsih_cmds.status & MPT3_CMD_REPLY_VALID) { | 7906 | if (ioc->scsih_cmds.status & MPT3_CMD_REPLY_VALID) { |
| 7628 | mpi_reply = ioc->scsih_cmds.reply; | 7907 | mpi_reply = ioc->scsih_cmds.reply; |
| 7629 | pr_info(MPT3SAS_FMT | 7908 | if (!ioc->hide_ir_msg) |
| 7630 | "IR shutdown (complete): ioc_status(0x%04x), loginfo(0x%08x)\n", | 7909 | pr_info(MPT3SAS_FMT "IR shutdown " |
| 7631 | ioc->name, le16_to_cpu(mpi_reply->IOCStatus), | 7910 | "(complete): ioc_status(0x%04x), loginfo(0x%08x)\n", |
| 7632 | le32_to_cpu(mpi_reply->IOCLogInfo)); | 7911 | ioc->name, le16_to_cpu(mpi_reply->IOCStatus), |
| 7912 | le32_to_cpu(mpi_reply->IOCLogInfo)); | ||
| 7633 | } | 7913 | } |
| 7634 | 7914 | ||
| 7635 | out: | 7915 | out: |
| @@ -7638,13 +7918,13 @@ _scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc) | |||
| 7638 | } | 7918 | } |
| 7639 | 7919 | ||
| 7640 | /** | 7920 | /** |
| 7641 | * _scsih_remove - detach and remove add host | 7921 | * scsih_remove - detach and remove add host |
| 7642 | * @pdev: PCI device struct | 7922 | * @pdev: PCI device struct |
| 7643 | * | 7923 | * |
| 7644 | * Routine called when unloading the driver. | 7924 | * Routine called when unloading the driver. |
| 7645 | * Return nothing. | 7925 | * Return nothing. |
| 7646 | */ | 7926 | */ |
| 7647 | static void _scsih_remove(struct pci_dev *pdev) | 7927 | void scsih_remove(struct pci_dev *pdev) |
| 7648 | { | 7928 | { |
| 7649 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | 7929 | struct Scsi_Host *shost = pci_get_drvdata(pdev); |
| 7650 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); | 7930 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); |
| @@ -7705,18 +7985,20 @@ static void _scsih_remove(struct pci_dev *pdev) | |||
| 7705 | sas_remove_host(shost); | 7985 | sas_remove_host(shost); |
| 7706 | scsi_remove_host(shost); | 7986 | scsi_remove_host(shost); |
| 7707 | mpt3sas_base_detach(ioc); | 7987 | mpt3sas_base_detach(ioc); |
| 7988 | spin_lock(&gioc_lock); | ||
| 7708 | list_del(&ioc->list); | 7989 | list_del(&ioc->list); |
| 7990 | spin_unlock(&gioc_lock); | ||
| 7709 | scsi_host_put(shost); | 7991 | scsi_host_put(shost); |
| 7710 | } | 7992 | } |
| 7711 | 7993 | ||
| 7712 | /** | 7994 | /** |
| 7713 | * _scsih_shutdown - routine call during system shutdown | 7995 | * scsih_shutdown - routine call during system shutdown |
| 7714 | * @pdev: PCI device struct | 7996 | * @pdev: PCI device struct |
| 7715 | * | 7997 | * |
| 7716 | * Return nothing. | 7998 | * Return nothing. |
| 7717 | */ | 7999 | */ |
| 7718 | static void | 8000 | void |
| 7719 | _scsih_shutdown(struct pci_dev *pdev) | 8001 | scsih_shutdown(struct pci_dev *pdev) |
| 7720 | { | 8002 | { |
| 7721 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | 8003 | struct Scsi_Host *shost = pci_get_drvdata(pdev); |
| 7722 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); | 8004 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); |
| @@ -7794,6 +8076,8 @@ _scsih_probe_boot_devices(struct MPT3SAS_ADAPTER *ioc) | |||
| 7794 | list_move_tail(&sas_device->list, &ioc->sas_device_list); | 8076 | list_move_tail(&sas_device->list, &ioc->sas_device_list); |
| 7795 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 8077 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 7796 | 8078 | ||
| 8079 | if (ioc->hide_drives) | ||
| 8080 | return; | ||
| 7797 | if (!mpt3sas_transport_port_add(ioc, handle, | 8081 | if (!mpt3sas_transport_port_add(ioc, handle, |
| 7798 | sas_address_parent)) { | 8082 | sas_address_parent)) { |
| 7799 | _scsih_sas_device_remove(ioc, sas_device); | 8083 | _scsih_sas_device_remove(ioc, sas_device); |
| @@ -7831,6 +8115,48 @@ _scsih_probe_raid(struct MPT3SAS_ADAPTER *ioc) | |||
| 7831 | } | 8115 | } |
| 7832 | } | 8116 | } |
| 7833 | 8117 | ||
| 8118 | static struct _sas_device *get_next_sas_device(struct MPT3SAS_ADAPTER *ioc) | ||
| 8119 | { | ||
| 8120 | struct _sas_device *sas_device = NULL; | ||
| 8121 | unsigned long flags; | ||
| 8122 | |||
| 8123 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 8124 | if (!list_empty(&ioc->sas_device_init_list)) { | ||
| 8125 | sas_device = list_first_entry(&ioc->sas_device_init_list, | ||
| 8126 | struct _sas_device, list); | ||
| 8127 | sas_device_get(sas_device); | ||
| 8128 | } | ||
| 8129 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 8130 | |||
| 8131 | return sas_device; | ||
| 8132 | } | ||
| 8133 | |||
| 8134 | static void sas_device_make_active(struct MPT3SAS_ADAPTER *ioc, | ||
| 8135 | struct _sas_device *sas_device) | ||
| 8136 | { | ||
| 8137 | unsigned long flags; | ||
| 8138 | |||
| 8139 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 8140 | |||
| 8141 | /* | ||
| 8142 | * Since we dropped the lock during the call to port_add(), we need to | ||
| 8143 | * be careful here that somebody else didn't move or delete this item | ||
| 8144 | * while we were busy with other things. | ||
| 8145 | * | ||
| 8146 | * If it was on the list, we need a put() for the reference the list | ||
| 8147 | * had. Either way, we need a get() for the destination list. | ||
| 8148 | */ | ||
| 8149 | if (!list_empty(&sas_device->list)) { | ||
| 8150 | list_del_init(&sas_device->list); | ||
| 8151 | sas_device_put(sas_device); | ||
| 8152 | } | ||
| 8153 | |||
| 8154 | sas_device_get(sas_device); | ||
| 8155 | list_add_tail(&sas_device->list, &ioc->sas_device_list); | ||
| 8156 | |||
| 8157 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 8158 | } | ||
| 8159 | |||
| 7834 | /** | 8160 | /** |
| 7835 | * _scsih_probe_sas - reporting sas devices to sas transport | 8161 | * _scsih_probe_sas - reporting sas devices to sas transport |
| 7836 | * @ioc: per adapter object | 8162 | * @ioc: per adapter object |
| @@ -7840,17 +8166,16 @@ _scsih_probe_raid(struct MPT3SAS_ADAPTER *ioc) | |||
| 7840 | static void | 8166 | static void |
| 7841 | _scsih_probe_sas(struct MPT3SAS_ADAPTER *ioc) | 8167 | _scsih_probe_sas(struct MPT3SAS_ADAPTER *ioc) |
| 7842 | { | 8168 | { |
| 7843 | struct _sas_device *sas_device, *next; | 8169 | struct _sas_device *sas_device; |
| 7844 | unsigned long flags; | ||
| 7845 | 8170 | ||
| 7846 | /* SAS Device List */ | 8171 | if (ioc->hide_drives) |
| 7847 | list_for_each_entry_safe(sas_device, next, &ioc->sas_device_init_list, | 8172 | return; |
| 7848 | list) { | ||
| 7849 | 8173 | ||
| 8174 | while ((sas_device = get_next_sas_device(ioc))) { | ||
| 7850 | if (!mpt3sas_transport_port_add(ioc, sas_device->handle, | 8175 | if (!mpt3sas_transport_port_add(ioc, sas_device->handle, |
| 7851 | sas_device->sas_address_parent)) { | 8176 | sas_device->sas_address_parent)) { |
| 7852 | list_del(&sas_device->list); | 8177 | _scsih_sas_device_remove(ioc, sas_device); |
| 7853 | kfree(sas_device); | 8178 | sas_device_put(sas_device); |
| 7854 | continue; | 8179 | continue; |
| 7855 | } else if (!sas_device->starget) { | 8180 | } else if (!sas_device->starget) { |
| 7856 | /* | 8181 | /* |
| @@ -7863,15 +8188,13 @@ _scsih_probe_sas(struct MPT3SAS_ADAPTER *ioc) | |||
| 7863 | mpt3sas_transport_port_remove(ioc, | 8188 | mpt3sas_transport_port_remove(ioc, |
| 7864 | sas_device->sas_address, | 8189 | sas_device->sas_address, |
| 7865 | sas_device->sas_address_parent); | 8190 | sas_device->sas_address_parent); |
| 7866 | list_del(&sas_device->list); | 8191 | _scsih_sas_device_remove(ioc, sas_device); |
| 7867 | kfree(sas_device); | 8192 | sas_device_put(sas_device); |
| 7868 | continue; | 8193 | continue; |
| 7869 | } | 8194 | } |
| 7870 | } | 8195 | } |
| 7871 | 8196 | sas_device_make_active(ioc, sas_device); | |
| 7872 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 8197 | sas_device_put(sas_device); |
| 7873 | list_move_tail(&sas_device->list, &ioc->sas_device_list); | ||
| 7874 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 7875 | } | 8198 | } |
| 7876 | } | 8199 | } |
| 7877 | 8200 | ||
| @@ -7908,15 +8231,15 @@ _scsih_probe_devices(struct MPT3SAS_ADAPTER *ioc) | |||
| 7908 | } | 8231 | } |
| 7909 | 8232 | ||
| 7910 | /** | 8233 | /** |
| 7911 | * _scsih_scan_start - scsi lld callback for .scan_start | 8234 | * scsih_scan_start - scsi lld callback for .scan_start |
| 7912 | * @shost: SCSI host pointer | 8235 | * @shost: SCSI host pointer |
| 7913 | * | 8236 | * |
| 7914 | * The shost has the ability to discover targets on its own instead | 8237 | * The shost has the ability to discover targets on its own instead |
| 7915 | * of scanning the entire bus. In our implemention, we will kick off | 8238 | * of scanning the entire bus. In our implemention, we will kick off |
| 7916 | * firmware discovery. | 8239 | * firmware discovery. |
| 7917 | */ | 8240 | */ |
| 7918 | static void | 8241 | void |
| 7919 | _scsih_scan_start(struct Scsi_Host *shost) | 8242 | scsih_scan_start(struct Scsi_Host *shost) |
| 7920 | { | 8243 | { |
| 7921 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); | 8244 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); |
| 7922 | int rc; | 8245 | int rc; |
| @@ -7934,7 +8257,7 @@ _scsih_scan_start(struct Scsi_Host *shost) | |||
| 7934 | } | 8257 | } |
| 7935 | 8258 | ||
| 7936 | /** | 8259 | /** |
| 7937 | * _scsih_scan_finished - scsi lld callback for .scan_finished | 8260 | * scsih_scan_finished - scsi lld callback for .scan_finished |
| 7938 | * @shost: SCSI host pointer | 8261 | * @shost: SCSI host pointer |
| 7939 | * @time: elapsed time of the scan in jiffies | 8262 | * @time: elapsed time of the scan in jiffies |
| 7940 | * | 8263 | * |
| @@ -7942,8 +8265,8 @@ _scsih_scan_start(struct Scsi_Host *shost) | |||
| 7942 | * scsi_host and the elapsed time of the scan in jiffies. In our implemention, | 8265 | * scsi_host and the elapsed time of the scan in jiffies. In our implemention, |
| 7943 | * we wait for firmware discovery to complete, then return 1. | 8266 | * we wait for firmware discovery to complete, then return 1. |
| 7944 | */ | 8267 | */ |
| 7945 | static int | 8268 | int |
| 7946 | _scsih_scan_finished(struct Scsi_Host *shost, unsigned long time) | 8269 | scsih_scan_finished(struct Scsi_Host *shost, unsigned long time) |
| 7947 | { | 8270 | { |
| 7948 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); | 8271 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); |
| 7949 | 8272 | ||
| @@ -7987,6 +8310,124 @@ _scsih_scan_finished(struct Scsi_Host *shost, unsigned long time) | |||
| 7987 | return 1; | 8310 | return 1; |
| 7988 | } | 8311 | } |
| 7989 | 8312 | ||
| 8313 | /* shost template for SAS 2.0 HBA devices */ | ||
| 8314 | static struct scsi_host_template mpt2sas_driver_template = { | ||
| 8315 | .module = THIS_MODULE, | ||
| 8316 | .name = "Fusion MPT SAS Host", | ||
| 8317 | .proc_name = MPT2SAS_DRIVER_NAME, | ||
| 8318 | .queuecommand = scsih_qcmd, | ||
| 8319 | .target_alloc = scsih_target_alloc, | ||
| 8320 | .slave_alloc = scsih_slave_alloc, | ||
| 8321 | .slave_configure = scsih_slave_configure, | ||
| 8322 | .target_destroy = scsih_target_destroy, | ||
| 8323 | .slave_destroy = scsih_slave_destroy, | ||
| 8324 | .scan_finished = scsih_scan_finished, | ||
| 8325 | .scan_start = scsih_scan_start, | ||
| 8326 | .change_queue_depth = scsih_change_queue_depth, | ||
| 8327 | .eh_abort_handler = scsih_abort, | ||
| 8328 | .eh_device_reset_handler = scsih_dev_reset, | ||
| 8329 | .eh_target_reset_handler = scsih_target_reset, | ||
| 8330 | .eh_host_reset_handler = scsih_host_reset, | ||
| 8331 | .bios_param = scsih_bios_param, | ||
| 8332 | .can_queue = 1, | ||
| 8333 | .this_id = -1, | ||
| 8334 | .sg_tablesize = MPT2SAS_SG_DEPTH, | ||
| 8335 | .max_sectors = 32767, | ||
| 8336 | .cmd_per_lun = 7, | ||
| 8337 | .use_clustering = ENABLE_CLUSTERING, | ||
| 8338 | .shost_attrs = mpt3sas_host_attrs, | ||
| 8339 | .sdev_attrs = mpt3sas_dev_attrs, | ||
| 8340 | .track_queue_depth = 1, | ||
| 8341 | }; | ||
| 8342 | |||
| 8343 | /* raid transport support for SAS 2.0 HBA devices */ | ||
| 8344 | static struct raid_function_template mpt2sas_raid_functions = { | ||
| 8345 | .cookie = &mpt2sas_driver_template, | ||
| 8346 | .is_raid = scsih_is_raid, | ||
| 8347 | .get_resync = scsih_get_resync, | ||
| 8348 | .get_state = scsih_get_state, | ||
| 8349 | }; | ||
| 8350 | |||
| 8351 | /* shost template for SAS 3.0 HBA devices */ | ||
| 8352 | static struct scsi_host_template mpt3sas_driver_template = { | ||
| 8353 | .module = THIS_MODULE, | ||
| 8354 | .name = "Fusion MPT SAS Host", | ||
| 8355 | .proc_name = MPT3SAS_DRIVER_NAME, | ||
| 8356 | .queuecommand = scsih_qcmd, | ||
| 8357 | .target_alloc = scsih_target_alloc, | ||
| 8358 | .slave_alloc = scsih_slave_alloc, | ||
| 8359 | .slave_configure = scsih_slave_configure, | ||
| 8360 | .target_destroy = scsih_target_destroy, | ||
| 8361 | .slave_destroy = scsih_slave_destroy, | ||
| 8362 | .scan_finished = scsih_scan_finished, | ||
| 8363 | .scan_start = scsih_scan_start, | ||
| 8364 | .change_queue_depth = scsih_change_queue_depth, | ||
| 8365 | .eh_abort_handler = scsih_abort, | ||
| 8366 | .eh_device_reset_handler = scsih_dev_reset, | ||
| 8367 | .eh_target_reset_handler = scsih_target_reset, | ||
| 8368 | .eh_host_reset_handler = scsih_host_reset, | ||
| 8369 | .bios_param = scsih_bios_param, | ||
| 8370 | .can_queue = 1, | ||
| 8371 | .this_id = -1, | ||
| 8372 | .sg_tablesize = MPT3SAS_SG_DEPTH, | ||
| 8373 | .max_sectors = 32767, | ||
| 8374 | .cmd_per_lun = 7, | ||
| 8375 | .use_clustering = ENABLE_CLUSTERING, | ||
| 8376 | .shost_attrs = mpt3sas_host_attrs, | ||
| 8377 | .sdev_attrs = mpt3sas_dev_attrs, | ||
| 8378 | .track_queue_depth = 1, | ||
| 8379 | }; | ||
| 8380 | |||
| 8381 | /* raid transport support for SAS 3.0 HBA devices */ | ||
| 8382 | static struct raid_function_template mpt3sas_raid_functions = { | ||
| 8383 | .cookie = &mpt3sas_driver_template, | ||
| 8384 | .is_raid = scsih_is_raid, | ||
| 8385 | .get_resync = scsih_get_resync, | ||
| 8386 | .get_state = scsih_get_state, | ||
| 8387 | }; | ||
| 8388 | |||
| 8389 | /** | ||
| 8390 | * _scsih_determine_hba_mpi_version - determine in which MPI version class | ||
| 8391 | * this device belongs to. | ||
| 8392 | * @pdev: PCI device struct | ||
| 8393 | * | ||
| 8394 | * return MPI2_VERSION for SAS 2.0 HBA devices, | ||
| 8395 | * MPI25_VERSION for SAS 3.0 HBA devices. | ||
| 8396 | */ | ||
| 8397 | u16 | ||
| 8398 | _scsih_determine_hba_mpi_version(struct pci_dev *pdev) | ||
| 8399 | { | ||
| 8400 | |||
| 8401 | switch (pdev->device) { | ||
| 8402 | case MPI2_MFGPAGE_DEVID_SSS6200: | ||
| 8403 | case MPI2_MFGPAGE_DEVID_SAS2004: | ||
| 8404 | case MPI2_MFGPAGE_DEVID_SAS2008: | ||
| 8405 | case MPI2_MFGPAGE_DEVID_SAS2108_1: | ||
| 8406 | case MPI2_MFGPAGE_DEVID_SAS2108_2: | ||
| 8407 | case MPI2_MFGPAGE_DEVID_SAS2108_3: | ||
| 8408 | case MPI2_MFGPAGE_DEVID_SAS2116_1: | ||
| 8409 | case MPI2_MFGPAGE_DEVID_SAS2116_2: | ||
| 8410 | case MPI2_MFGPAGE_DEVID_SAS2208_1: | ||
| 8411 | case MPI2_MFGPAGE_DEVID_SAS2208_2: | ||
| 8412 | case MPI2_MFGPAGE_DEVID_SAS2208_3: | ||
| 8413 | case MPI2_MFGPAGE_DEVID_SAS2208_4: | ||
| 8414 | case MPI2_MFGPAGE_DEVID_SAS2208_5: | ||
| 8415 | case MPI2_MFGPAGE_DEVID_SAS2208_6: | ||
| 8416 | case MPI2_MFGPAGE_DEVID_SAS2308_1: | ||
| 8417 | case MPI2_MFGPAGE_DEVID_SAS2308_2: | ||
| 8418 | case MPI2_MFGPAGE_DEVID_SAS2308_3: | ||
| 8419 | return MPI2_VERSION; | ||
| 8420 | case MPI25_MFGPAGE_DEVID_SAS3004: | ||
| 8421 | case MPI25_MFGPAGE_DEVID_SAS3008: | ||
| 8422 | case MPI25_MFGPAGE_DEVID_SAS3108_1: | ||
| 8423 | case MPI25_MFGPAGE_DEVID_SAS3108_2: | ||
| 8424 | case MPI25_MFGPAGE_DEVID_SAS3108_5: | ||
| 8425 | case MPI25_MFGPAGE_DEVID_SAS3108_6: | ||
| 8426 | return MPI25_VERSION; | ||
| 8427 | } | ||
| 8428 | return 0; | ||
| 8429 | } | ||
| 8430 | |||
| 7990 | /** | 8431 | /** |
| 7991 | * _scsih_probe - attach and add scsi host | 8432 | * _scsih_probe - attach and add scsi host |
| 7992 | * @pdev: PCI device struct | 8433 | * @pdev: PCI device struct |
| @@ -7994,26 +8435,72 @@ _scsih_scan_finished(struct Scsi_Host *shost, unsigned long time) | |||
| 7994 | * | 8435 | * |
| 7995 | * Returns 0 success, anything else error. | 8436 | * Returns 0 success, anything else error. |
| 7996 | */ | 8437 | */ |
| 7997 | static int | 8438 | int |
| 7998 | _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) | 8439 | _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
| 7999 | { | 8440 | { |
| 8000 | struct MPT3SAS_ADAPTER *ioc; | 8441 | struct MPT3SAS_ADAPTER *ioc; |
| 8001 | struct Scsi_Host *shost; | 8442 | struct Scsi_Host *shost = NULL; |
| 8002 | int rv; | 8443 | int rv; |
| 8444 | u16 hba_mpi_version; | ||
| 8003 | 8445 | ||
| 8004 | shost = scsi_host_alloc(&scsih_driver_template, | 8446 | /* Determine in which MPI version class this pci device belongs */ |
| 8005 | sizeof(struct MPT3SAS_ADAPTER)); | 8447 | hba_mpi_version = _scsih_determine_hba_mpi_version(pdev); |
| 8006 | if (!shost) | 8448 | if (hba_mpi_version == 0) |
| 8007 | return -ENODEV; | 8449 | return -ENODEV; |
| 8008 | 8450 | ||
| 8009 | /* init local params */ | 8451 | /* Enumerate only SAS 2.0 HBA's if hbas_to_enumerate is one, |
| 8010 | ioc = shost_priv(shost); | 8452 | * for other generation HBA's return with -ENODEV |
| 8011 | memset(ioc, 0, sizeof(struct MPT3SAS_ADAPTER)); | 8453 | */ |
| 8454 | if ((hbas_to_enumerate == 1) && (hba_mpi_version != MPI2_VERSION)) | ||
| 8455 | return -ENODEV; | ||
| 8456 | |||
| 8457 | /* Enumerate only SAS 3.0 HBA's if hbas_to_enumerate is two, | ||
| 8458 | * for other generation HBA's return with -ENODEV | ||
| 8459 | */ | ||
| 8460 | if ((hbas_to_enumerate == 2) && (hba_mpi_version != MPI25_VERSION)) | ||
| 8461 | return -ENODEV; | ||
| 8462 | |||
| 8463 | switch (hba_mpi_version) { | ||
| 8464 | case MPI2_VERSION: | ||
| 8465 | /* Use mpt2sas driver host template for SAS 2.0 HBA's */ | ||
| 8466 | shost = scsi_host_alloc(&mpt2sas_driver_template, | ||
| 8467 | sizeof(struct MPT3SAS_ADAPTER)); | ||
| 8468 | if (!shost) | ||
| 8469 | return -ENODEV; | ||
| 8470 | ioc = shost_priv(shost); | ||
| 8471 | memset(ioc, 0, sizeof(struct MPT3SAS_ADAPTER)); | ||
| 8472 | ioc->hba_mpi_version_belonged = hba_mpi_version; | ||
| 8473 | ioc->id = mpt2_ids++; | ||
| 8474 | sprintf(ioc->driver_name, "%s", MPT2SAS_DRIVER_NAME); | ||
| 8475 | if (pdev->device == MPI2_MFGPAGE_DEVID_SSS6200) { | ||
| 8476 | ioc->is_warpdrive = 1; | ||
| 8477 | ioc->hide_ir_msg = 1; | ||
| 8478 | } else | ||
| 8479 | ioc->mfg_pg10_hide_flag = MFG_PAGE10_EXPOSE_ALL_DISKS; | ||
| 8480 | break; | ||
| 8481 | case MPI25_VERSION: | ||
| 8482 | /* Use mpt3sas driver host template for SAS 3.0 HBA's */ | ||
| 8483 | shost = scsi_host_alloc(&mpt3sas_driver_template, | ||
| 8484 | sizeof(struct MPT3SAS_ADAPTER)); | ||
| 8485 | if (!shost) | ||
| 8486 | return -ENODEV; | ||
| 8487 | ioc = shost_priv(shost); | ||
| 8488 | memset(ioc, 0, sizeof(struct MPT3SAS_ADAPTER)); | ||
| 8489 | ioc->hba_mpi_version_belonged = hba_mpi_version; | ||
| 8490 | ioc->id = mpt3_ids++; | ||
| 8491 | sprintf(ioc->driver_name, "%s", MPT3SAS_DRIVER_NAME); | ||
| 8492 | if (pdev->revision >= SAS3_PCI_DEVICE_C0_REVISION) | ||
| 8493 | ioc->msix96_vector = 1; | ||
| 8494 | break; | ||
| 8495 | default: | ||
| 8496 | return -ENODEV; | ||
| 8497 | } | ||
| 8498 | |||
| 8012 | INIT_LIST_HEAD(&ioc->list); | 8499 | INIT_LIST_HEAD(&ioc->list); |
| 8500 | spin_lock(&gioc_lock); | ||
| 8013 | list_add_tail(&ioc->list, &mpt3sas_ioc_list); | 8501 | list_add_tail(&ioc->list, &mpt3sas_ioc_list); |
| 8502 | spin_unlock(&gioc_lock); | ||
| 8014 | ioc->shost = shost; | 8503 | ioc->shost = shost; |
| 8015 | ioc->id = mpt_ids++; | ||
| 8016 | sprintf(ioc->name, "%s%d", MPT3SAS_DRIVER_NAME, ioc->id); | ||
| 8017 | ioc->pdev = pdev; | 8504 | ioc->pdev = pdev; |
| 8018 | ioc->scsi_io_cb_idx = scsi_io_cb_idx; | 8505 | ioc->scsi_io_cb_idx = scsi_io_cb_idx; |
| 8019 | ioc->tm_cb_idx = tm_cb_idx; | 8506 | ioc->tm_cb_idx = tm_cb_idx; |
| @@ -8030,6 +8517,8 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 8030 | ioc->schedule_dead_ioc_flush_running_cmds = &_scsih_flush_running_cmds; | 8517 | ioc->schedule_dead_ioc_flush_running_cmds = &_scsih_flush_running_cmds; |
| 8031 | /* misc semaphores and spin locks */ | 8518 | /* misc semaphores and spin locks */ |
| 8032 | mutex_init(&ioc->reset_in_progress_mutex); | 8519 | mutex_init(&ioc->reset_in_progress_mutex); |
| 8520 | /* initializing pci_access_mutex lock */ | ||
| 8521 | mutex_init(&ioc->pci_access_mutex); | ||
| 8033 | spin_lock_init(&ioc->ioc_reset_in_progress_lock); | 8522 | spin_lock_init(&ioc->ioc_reset_in_progress_lock); |
| 8034 | spin_lock_init(&ioc->scsi_lookup_lock); | 8523 | spin_lock_init(&ioc->scsi_lookup_lock); |
| 8035 | spin_lock_init(&ioc->sas_device_lock); | 8524 | spin_lock_init(&ioc->sas_device_lock); |
| @@ -8048,6 +8537,8 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 8048 | INIT_LIST_HEAD(&ioc->delayed_tr_volume_list); | 8537 | INIT_LIST_HEAD(&ioc->delayed_tr_volume_list); |
| 8049 | INIT_LIST_HEAD(&ioc->reply_queue_list); | 8538 | INIT_LIST_HEAD(&ioc->reply_queue_list); |
| 8050 | 8539 | ||
| 8540 | sprintf(ioc->name, "%s_cm%d", ioc->driver_name, ioc->id); | ||
| 8541 | |||
| 8051 | /* init shost parameters */ | 8542 | /* init shost parameters */ |
| 8052 | shost->max_cmd_len = 32; | 8543 | shost->max_cmd_len = 32; |
| 8053 | shost->max_lun = max_lun; | 8544 | shost->max_lun = max_lun; |
| @@ -8086,7 +8577,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 8086 | 8577 | ||
| 8087 | /* event thread */ | 8578 | /* event thread */ |
| 8088 | snprintf(ioc->firmware_event_name, sizeof(ioc->firmware_event_name), | 8579 | snprintf(ioc->firmware_event_name, sizeof(ioc->firmware_event_name), |
| 8089 | "fw_event%d", ioc->id); | 8580 | "fw_event_%s%d", ioc->driver_name, ioc->id); |
| 8090 | ioc->firmware_event_thread = alloc_ordered_workqueue( | 8581 | ioc->firmware_event_thread = alloc_ordered_workqueue( |
| 8091 | ioc->firmware_event_name, WQ_MEM_RECLAIM); | 8582 | ioc->firmware_event_name, WQ_MEM_RECLAIM); |
| 8092 | if (!ioc->firmware_event_thread) { | 8583 | if (!ioc->firmware_event_thread) { |
| @@ -8103,6 +8594,21 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 8103 | rv = -ENODEV; | 8594 | rv = -ENODEV; |
| 8104 | goto out_attach_fail; | 8595 | goto out_attach_fail; |
| 8105 | } | 8596 | } |
| 8597 | |||
| 8598 | if (ioc->is_warpdrive) { | ||
| 8599 | if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_EXPOSE_ALL_DISKS) | ||
| 8600 | ioc->hide_drives = 0; | ||
| 8601 | else if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_HIDE_ALL_DISKS) | ||
| 8602 | ioc->hide_drives = 1; | ||
| 8603 | else { | ||
| 8604 | if (mpt3sas_get_num_volumes(ioc)) | ||
| 8605 | ioc->hide_drives = 1; | ||
| 8606 | else | ||
| 8607 | ioc->hide_drives = 0; | ||
| 8608 | } | ||
| 8609 | } else | ||
| 8610 | ioc->hide_drives = 0; | ||
| 8611 | |||
| 8106 | rv = scsi_add_host(shost, &pdev->dev); | 8612 | rv = scsi_add_host(shost, &pdev->dev); |
| 8107 | if (rv) { | 8613 | if (rv) { |
| 8108 | pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", | 8614 | pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", |
| @@ -8117,21 +8623,23 @@ out_add_shost_fail: | |||
| 8117 | out_attach_fail: | 8623 | out_attach_fail: |
| 8118 | destroy_workqueue(ioc->firmware_event_thread); | 8624 | destroy_workqueue(ioc->firmware_event_thread); |
| 8119 | out_thread_fail: | 8625 | out_thread_fail: |
| 8626 | spin_lock(&gioc_lock); | ||
| 8120 | list_del(&ioc->list); | 8627 | list_del(&ioc->list); |
| 8628 | spin_unlock(&gioc_lock); | ||
| 8121 | scsi_host_put(shost); | 8629 | scsi_host_put(shost); |
| 8122 | return rv; | 8630 | return rv; |
| 8123 | } | 8631 | } |
| 8124 | 8632 | ||
| 8125 | #ifdef CONFIG_PM | 8633 | #ifdef CONFIG_PM |
| 8126 | /** | 8634 | /** |
| 8127 | * _scsih_suspend - power management suspend main entry point | 8635 | * scsih_suspend - power management suspend main entry point |
| 8128 | * @pdev: PCI device struct | 8636 | * @pdev: PCI device struct |
| 8129 | * @state: PM state change to (usually PCI_D3) | 8637 | * @state: PM state change to (usually PCI_D3) |
| 8130 | * | 8638 | * |
| 8131 | * Returns 0 success, anything else error. | 8639 | * Returns 0 success, anything else error. |
| 8132 | */ | 8640 | */ |
| 8133 | static int | 8641 | int |
| 8134 | _scsih_suspend(struct pci_dev *pdev, pm_message_t state) | 8642 | scsih_suspend(struct pci_dev *pdev, pm_message_t state) |
| 8135 | { | 8643 | { |
| 8136 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | 8644 | struct Scsi_Host *shost = pci_get_drvdata(pdev); |
| 8137 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); | 8645 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); |
| @@ -8152,13 +8660,13 @@ _scsih_suspend(struct pci_dev *pdev, pm_message_t state) | |||
| 8152 | } | 8660 | } |
| 8153 | 8661 | ||
| 8154 | /** | 8662 | /** |
| 8155 | * _scsih_resume - power management resume main entry point | 8663 | * scsih_resume - power management resume main entry point |
| 8156 | * @pdev: PCI device struct | 8664 | * @pdev: PCI device struct |
| 8157 | * | 8665 | * |
| 8158 | * Returns 0 success, anything else error. | 8666 | * Returns 0 success, anything else error. |
| 8159 | */ | 8667 | */ |
| 8160 | static int | 8668 | int |
| 8161 | _scsih_resume(struct pci_dev *pdev) | 8669 | scsih_resume(struct pci_dev *pdev) |
| 8162 | { | 8670 | { |
| 8163 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | 8671 | struct Scsi_Host *shost = pci_get_drvdata(pdev); |
| 8164 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); | 8672 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); |
| @@ -8185,7 +8693,7 @@ _scsih_resume(struct pci_dev *pdev) | |||
| 8185 | #endif /* CONFIG_PM */ | 8693 | #endif /* CONFIG_PM */ |
| 8186 | 8694 | ||
| 8187 | /** | 8695 | /** |
| 8188 | * _scsih_pci_error_detected - Called when a PCI error is detected. | 8696 | * scsih_pci_error_detected - Called when a PCI error is detected. |
| 8189 | * @pdev: PCI device struct | 8697 | * @pdev: PCI device struct |
| 8190 | * @state: PCI channel state | 8698 | * @state: PCI channel state |
| 8191 | * | 8699 | * |
| @@ -8194,8 +8702,8 @@ _scsih_resume(struct pci_dev *pdev) | |||
| 8194 | * Return value: | 8702 | * Return value: |
| 8195 | * PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT | 8703 | * PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT |
| 8196 | */ | 8704 | */ |
| 8197 | static pci_ers_result_t | 8705 | pci_ers_result_t |
| 8198 | _scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) | 8706 | scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) |
| 8199 | { | 8707 | { |
| 8200 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | 8708 | struct Scsi_Host *shost = pci_get_drvdata(pdev); |
| 8201 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); | 8709 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); |
| @@ -8224,15 +8732,15 @@ _scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) | |||
| 8224 | } | 8732 | } |
| 8225 | 8733 | ||
| 8226 | /** | 8734 | /** |
| 8227 | * _scsih_pci_slot_reset - Called when PCI slot has been reset. | 8735 | * scsih_pci_slot_reset - Called when PCI slot has been reset. |
| 8228 | * @pdev: PCI device struct | 8736 | * @pdev: PCI device struct |
| 8229 | * | 8737 | * |
| 8230 | * Description: This routine is called by the pci error recovery | 8738 | * Description: This routine is called by the pci error recovery |
| 8231 | * code after the PCI slot has been reset, just before we | 8739 | * code after the PCI slot has been reset, just before we |
| 8232 | * should resume normal operations. | 8740 | * should resume normal operations. |
| 8233 | */ | 8741 | */ |
| 8234 | static pci_ers_result_t | 8742 | pci_ers_result_t |
| 8235 | _scsih_pci_slot_reset(struct pci_dev *pdev) | 8743 | scsih_pci_slot_reset(struct pci_dev *pdev) |
| 8236 | { | 8744 | { |
| 8237 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | 8745 | struct Scsi_Host *shost = pci_get_drvdata(pdev); |
| 8238 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); | 8746 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); |
| @@ -8261,15 +8769,15 @@ _scsih_pci_slot_reset(struct pci_dev *pdev) | |||
| 8261 | } | 8769 | } |
| 8262 | 8770 | ||
| 8263 | /** | 8771 | /** |
| 8264 | * _scsih_pci_resume() - resume normal ops after PCI reset | 8772 | * scsih_pci_resume() - resume normal ops after PCI reset |
| 8265 | * @pdev: pointer to PCI device | 8773 | * @pdev: pointer to PCI device |
| 8266 | * | 8774 | * |
| 8267 | * Called when the error recovery driver tells us that its | 8775 | * Called when the error recovery driver tells us that its |
| 8268 | * OK to resume normal operation. Use completion to allow | 8776 | * OK to resume normal operation. Use completion to allow |
| 8269 | * halted scsi ops to resume. | 8777 | * halted scsi ops to resume. |
| 8270 | */ | 8778 | */ |
| 8271 | static void | 8779 | void |
| 8272 | _scsih_pci_resume(struct pci_dev *pdev) | 8780 | scsih_pci_resume(struct pci_dev *pdev) |
| 8273 | { | 8781 | { |
| 8274 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | 8782 | struct Scsi_Host *shost = pci_get_drvdata(pdev); |
| 8275 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); | 8783 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); |
| @@ -8282,11 +8790,11 @@ _scsih_pci_resume(struct pci_dev *pdev) | |||
| 8282 | } | 8790 | } |
| 8283 | 8791 | ||
| 8284 | /** | 8792 | /** |
| 8285 | * _scsih_pci_mmio_enabled - Enable MMIO and dump debug registers | 8793 | * scsih_pci_mmio_enabled - Enable MMIO and dump debug registers |
| 8286 | * @pdev: pointer to PCI device | 8794 | * @pdev: pointer to PCI device |
| 8287 | */ | 8795 | */ |
| 8288 | static pci_ers_result_t | 8796 | pci_ers_result_t |
| 8289 | _scsih_pci_mmio_enabled(struct pci_dev *pdev) | 8797 | scsih_pci_mmio_enabled(struct pci_dev *pdev) |
| 8290 | { | 8798 | { |
| 8291 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | 8799 | struct Scsi_Host *shost = pci_get_drvdata(pdev); |
| 8292 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); | 8800 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); |
| @@ -8300,61 +8808,99 @@ _scsih_pci_mmio_enabled(struct pci_dev *pdev) | |||
| 8300 | return PCI_ERS_RESULT_NEED_RESET; | 8808 | return PCI_ERS_RESULT_NEED_RESET; |
| 8301 | } | 8809 | } |
| 8302 | 8810 | ||
| 8303 | /* raid transport support */ | 8811 | /* |
| 8304 | static struct raid_function_template mpt3sas_raid_functions = { | 8812 | * The pci device ids are defined in mpi/mpi2_cnfg.h. |
| 8305 | .cookie = &scsih_driver_template, | 8813 | */ |
| 8306 | .is_raid = _scsih_is_raid, | 8814 | static const struct pci_device_id mpt3sas_pci_table[] = { |
| 8307 | .get_resync = _scsih_get_resync, | 8815 | /* Spitfire ~ 2004 */ |
| 8308 | .get_state = _scsih_get_state, | 8816 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2004, |
| 8817 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 8818 | /* Falcon ~ 2008 */ | ||
| 8819 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2008, | ||
| 8820 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 8821 | /* Liberator ~ 2108 */ | ||
| 8822 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_1, | ||
| 8823 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 8824 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_2, | ||
| 8825 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 8826 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_3, | ||
| 8827 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 8828 | /* Meteor ~ 2116 */ | ||
| 8829 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_1, | ||
| 8830 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 8831 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_2, | ||
| 8832 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 8833 | /* Thunderbolt ~ 2208 */ | ||
| 8834 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_1, | ||
| 8835 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 8836 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_2, | ||
| 8837 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 8838 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_3, | ||
| 8839 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 8840 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_4, | ||
| 8841 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 8842 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_5, | ||
| 8843 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 8844 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_6, | ||
| 8845 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 8846 | /* Mustang ~ 2308 */ | ||
| 8847 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_1, | ||
| 8848 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 8849 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_2, | ||
| 8850 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 8851 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_3, | ||
| 8852 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 8853 | /* SSS6200 */ | ||
| 8854 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SSS6200, | ||
| 8855 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 8856 | /* Fury ~ 3004 and 3008 */ | ||
| 8857 | { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3004, | ||
| 8858 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 8859 | { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3008, | ||
| 8860 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 8861 | /* Invader ~ 3108 */ | ||
| 8862 | { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_1, | ||
| 8863 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 8864 | { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_2, | ||
| 8865 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 8866 | { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_5, | ||
| 8867 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 8868 | { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_6, | ||
| 8869 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 8870 | {0} /* Terminating entry */ | ||
| 8309 | }; | 8871 | }; |
| 8872 | MODULE_DEVICE_TABLE(pci, mpt3sas_pci_table); | ||
| 8310 | 8873 | ||
| 8311 | static struct pci_error_handlers _scsih_err_handler = { | 8874 | static struct pci_error_handlers _mpt3sas_err_handler = { |
| 8312 | .error_detected = _scsih_pci_error_detected, | 8875 | .error_detected = scsih_pci_error_detected, |
| 8313 | .mmio_enabled = _scsih_pci_mmio_enabled, | 8876 | .mmio_enabled = scsih_pci_mmio_enabled, |
| 8314 | .slot_reset = _scsih_pci_slot_reset, | 8877 | .slot_reset = scsih_pci_slot_reset, |
| 8315 | .resume = _scsih_pci_resume, | 8878 | .resume = scsih_pci_resume, |
| 8316 | }; | 8879 | }; |
| 8317 | 8880 | ||
| 8318 | static struct pci_driver scsih_driver = { | 8881 | static struct pci_driver mpt3sas_driver = { |
| 8319 | .name = MPT3SAS_DRIVER_NAME, | 8882 | .name = MPT3SAS_DRIVER_NAME, |
| 8320 | .id_table = scsih_pci_table, | 8883 | .id_table = mpt3sas_pci_table, |
| 8321 | .probe = _scsih_probe, | 8884 | .probe = _scsih_probe, |
| 8322 | .remove = _scsih_remove, | 8885 | .remove = scsih_remove, |
| 8323 | .shutdown = _scsih_shutdown, | 8886 | .shutdown = scsih_shutdown, |
| 8324 | .err_handler = &_scsih_err_handler, | 8887 | .err_handler = &_mpt3sas_err_handler, |
| 8325 | #ifdef CONFIG_PM | 8888 | #ifdef CONFIG_PM |
| 8326 | .suspend = _scsih_suspend, | 8889 | .suspend = scsih_suspend, |
| 8327 | .resume = _scsih_resume, | 8890 | .resume = scsih_resume, |
| 8328 | #endif | 8891 | #endif |
| 8329 | }; | 8892 | }; |
| 8330 | 8893 | ||
| 8331 | |||
| 8332 | /** | 8894 | /** |
| 8333 | * _scsih_init - main entry point for this driver. | 8895 | * scsih_init - main entry point for this driver. |
| 8334 | * | 8896 | * |
| 8335 | * Returns 0 success, anything else error. | 8897 | * Returns 0 success, anything else error. |
| 8336 | */ | 8898 | */ |
| 8337 | static int __init | 8899 | int |
| 8338 | _scsih_init(void) | 8900 | scsih_init(void) |
| 8339 | { | 8901 | { |
| 8340 | int error; | 8902 | mpt2_ids = 0; |
| 8341 | 8903 | mpt3_ids = 0; | |
| 8342 | mpt_ids = 0; | ||
| 8343 | |||
| 8344 | pr_info("%s version %s loaded\n", MPT3SAS_DRIVER_NAME, | ||
| 8345 | MPT3SAS_DRIVER_VERSION); | ||
| 8346 | |||
| 8347 | mpt3sas_transport_template = | ||
| 8348 | sas_attach_transport(&mpt3sas_transport_functions); | ||
| 8349 | if (!mpt3sas_transport_template) | ||
| 8350 | return -ENODEV; | ||
| 8351 | |||
| 8352 | /* raid transport support */ | ||
| 8353 | mpt3sas_raid_template = raid_class_attach(&mpt3sas_raid_functions); | ||
| 8354 | if (!mpt3sas_raid_template) { | ||
| 8355 | sas_release_transport(mpt3sas_transport_template); | ||
| 8356 | return -ENODEV; | ||
| 8357 | } | ||
| 8358 | 8904 | ||
| 8359 | mpt3sas_base_initialize_callback_handler(); | 8905 | mpt3sas_base_initialize_callback_handler(); |
| 8360 | 8906 | ||
| @@ -8392,33 +8938,17 @@ _scsih_init(void) | |||
| 8392 | tm_sas_control_cb_idx = mpt3sas_base_register_callback_handler( | 8938 | tm_sas_control_cb_idx = mpt3sas_base_register_callback_handler( |
| 8393 | _scsih_sas_control_complete); | 8939 | _scsih_sas_control_complete); |
| 8394 | 8940 | ||
| 8395 | mpt3sas_ctl_init(); | 8941 | return 0; |
| 8396 | |||
| 8397 | error = pci_register_driver(&scsih_driver); | ||
| 8398 | if (error) { | ||
| 8399 | /* raid transport support */ | ||
| 8400 | raid_class_release(mpt3sas_raid_template); | ||
| 8401 | sas_release_transport(mpt3sas_transport_template); | ||
| 8402 | } | ||
| 8403 | |||
| 8404 | return error; | ||
| 8405 | } | 8942 | } |
| 8406 | 8943 | ||
| 8407 | /** | 8944 | /** |
| 8408 | * _scsih_exit - exit point for this driver (when it is a module). | 8945 | * scsih_exit - exit point for this driver (when it is a module). |
| 8409 | * | 8946 | * |
| 8410 | * Returns 0 success, anything else error. | 8947 | * Returns 0 success, anything else error. |
| 8411 | */ | 8948 | */ |
| 8412 | static void __exit | 8949 | void |
| 8413 | _scsih_exit(void) | 8950 | scsih_exit(void) |
| 8414 | { | 8951 | { |
| 8415 | pr_info("mpt3sas version %s unloading\n", | ||
| 8416 | MPT3SAS_DRIVER_VERSION); | ||
| 8417 | |||
| 8418 | mpt3sas_ctl_exit(); | ||
| 8419 | |||
| 8420 | pci_unregister_driver(&scsih_driver); | ||
| 8421 | |||
| 8422 | 8952 | ||
| 8423 | mpt3sas_base_release_callback_handler(scsi_io_cb_idx); | 8953 | mpt3sas_base_release_callback_handler(scsi_io_cb_idx); |
| 8424 | mpt3sas_base_release_callback_handler(tm_cb_idx); | 8954 | mpt3sas_base_release_callback_handler(tm_cb_idx); |
| @@ -8434,9 +8964,86 @@ _scsih_exit(void) | |||
| 8434 | mpt3sas_base_release_callback_handler(tm_sas_control_cb_idx); | 8964 | mpt3sas_base_release_callback_handler(tm_sas_control_cb_idx); |
| 8435 | 8965 | ||
| 8436 | /* raid transport support */ | 8966 | /* raid transport support */ |
| 8437 | raid_class_release(mpt3sas_raid_template); | 8967 | if (hbas_to_enumerate != 1) |
| 8968 | raid_class_release(mpt3sas_raid_template); | ||
| 8969 | if (hbas_to_enumerate != 2) | ||
| 8970 | raid_class_release(mpt2sas_raid_template); | ||
| 8438 | sas_release_transport(mpt3sas_transport_template); | 8971 | sas_release_transport(mpt3sas_transport_template); |
| 8439 | } | 8972 | } |
| 8440 | 8973 | ||
| 8441 | module_init(_scsih_init); | 8974 | /** |
| 8442 | module_exit(_scsih_exit); | 8975 | * _mpt3sas_init - main entry point for this driver. |
| 8976 | * | ||
| 8977 | * Returns 0 success, anything else error. | ||
| 8978 | */ | ||
| 8979 | static int __init | ||
| 8980 | _mpt3sas_init(void) | ||
| 8981 | { | ||
| 8982 | int error; | ||
| 8983 | |||
| 8984 | pr_info("%s version %s loaded\n", MPT3SAS_DRIVER_NAME, | ||
| 8985 | MPT3SAS_DRIVER_VERSION); | ||
| 8986 | |||
| 8987 | mpt3sas_transport_template = | ||
| 8988 | sas_attach_transport(&mpt3sas_transport_functions); | ||
| 8989 | if (!mpt3sas_transport_template) | ||
| 8990 | return -ENODEV; | ||
| 8991 | |||
| 8992 | /* No need attach mpt3sas raid functions template | ||
| 8993 | * if hbas_to_enumarate value is one. | ||
| 8994 | */ | ||
| 8995 | if (hbas_to_enumerate != 1) { | ||
| 8996 | mpt3sas_raid_template = | ||
| 8997 | raid_class_attach(&mpt3sas_raid_functions); | ||
| 8998 | if (!mpt3sas_raid_template) { | ||
| 8999 | sas_release_transport(mpt3sas_transport_template); | ||
| 9000 | return -ENODEV; | ||
| 9001 | } | ||
| 9002 | } | ||
| 9003 | |||
| 9004 | /* No need to attach mpt2sas raid functions template | ||
| 9005 | * if hbas_to_enumarate value is two | ||
| 9006 | */ | ||
| 9007 | if (hbas_to_enumerate != 2) { | ||
| 9008 | mpt2sas_raid_template = | ||
| 9009 | raid_class_attach(&mpt2sas_raid_functions); | ||
| 9010 | if (!mpt2sas_raid_template) { | ||
| 9011 | sas_release_transport(mpt3sas_transport_template); | ||
| 9012 | return -ENODEV; | ||
| 9013 | } | ||
| 9014 | } | ||
| 9015 | |||
| 9016 | error = scsih_init(); | ||
| 9017 | if (error) { | ||
| 9018 | scsih_exit(); | ||
| 9019 | return error; | ||
| 9020 | } | ||
| 9021 | |||
| 9022 | mpt3sas_ctl_init(hbas_to_enumerate); | ||
| 9023 | |||
| 9024 | error = pci_register_driver(&mpt3sas_driver); | ||
| 9025 | if (error) | ||
| 9026 | scsih_exit(); | ||
| 9027 | |||
| 9028 | return error; | ||
| 9029 | } | ||
| 9030 | |||
| 9031 | /** | ||
| 9032 | * _mpt3sas_exit - exit point for this driver (when it is a module). | ||
| 9033 | * | ||
| 9034 | */ | ||
| 9035 | static void __exit | ||
| 9036 | _mpt3sas_exit(void) | ||
| 9037 | { | ||
| 9038 | pr_info("mpt3sas version %s unloading\n", | ||
| 9039 | MPT3SAS_DRIVER_VERSION); | ||
| 9040 | |||
| 9041 | pci_unregister_driver(&mpt3sas_driver); | ||
| 9042 | |||
| 9043 | mpt3sas_ctl_exit(hbas_to_enumerate); | ||
| 9044 | |||
| 9045 | scsih_exit(); | ||
| 9046 | } | ||
| 9047 | |||
| 9048 | module_init(_mpt3sas_init); | ||
| 9049 | module_exit(_mpt3sas_exit); | ||
diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c index 70fd019e7ee5..ca36d7ea0964 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_transport.c +++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c | |||
| @@ -734,7 +734,7 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle, | |||
| 734 | rphy->identify = mpt3sas_port->remote_identify; | 734 | rphy->identify = mpt3sas_port->remote_identify; |
| 735 | 735 | ||
| 736 | if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) { | 736 | if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) { |
| 737 | sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc, | 737 | sas_device = mpt3sas_get_sdev_by_addr(ioc, |
| 738 | mpt3sas_port->remote_identify.sas_address); | 738 | mpt3sas_port->remote_identify.sas_address); |
| 739 | if (!sas_device) { | 739 | if (!sas_device) { |
| 740 | dfailprintk(ioc, printk(MPT3SAS_FMT | 740 | dfailprintk(ioc, printk(MPT3SAS_FMT |
| @@ -750,8 +750,10 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle, | |||
| 750 | ioc->name, __FILE__, __LINE__, __func__); | 750 | ioc->name, __FILE__, __LINE__, __func__); |
| 751 | } | 751 | } |
| 752 | 752 | ||
| 753 | if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) | 753 | if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) { |
| 754 | sas_device->pend_sas_rphy_add = 0; | 754 | sas_device->pend_sas_rphy_add = 0; |
| 755 | sas_device_put(sas_device); | ||
| 756 | } | ||
| 755 | 757 | ||
| 756 | if ((ioc->logging_level & MPT_DEBUG_TRANSPORT)) | 758 | if ((ioc->logging_level & MPT_DEBUG_TRANSPORT)) |
| 757 | dev_printk(KERN_INFO, &rphy->dev, | 759 | dev_printk(KERN_INFO, &rphy->dev, |
| @@ -1324,15 +1326,17 @@ _transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier) | |||
| 1324 | int rc; | 1326 | int rc; |
| 1325 | 1327 | ||
| 1326 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 1328 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 1327 | sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc, | 1329 | sas_device = __mpt3sas_get_sdev_by_addr(ioc, |
| 1328 | rphy->identify.sas_address); | 1330 | rphy->identify.sas_address); |
| 1329 | if (sas_device) { | 1331 | if (sas_device) { |
| 1330 | *identifier = sas_device->enclosure_logical_id; | 1332 | *identifier = sas_device->enclosure_logical_id; |
| 1331 | rc = 0; | 1333 | rc = 0; |
| 1334 | sas_device_put(sas_device); | ||
| 1332 | } else { | 1335 | } else { |
| 1333 | *identifier = 0; | 1336 | *identifier = 0; |
| 1334 | rc = -ENXIO; | 1337 | rc = -ENXIO; |
| 1335 | } | 1338 | } |
| 1339 | |||
| 1336 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 1340 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 1337 | return rc; | 1341 | return rc; |
| 1338 | } | 1342 | } |
| @@ -1352,12 +1356,14 @@ _transport_get_bay_identifier(struct sas_rphy *rphy) | |||
| 1352 | int rc; | 1356 | int rc; |
| 1353 | 1357 | ||
| 1354 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 1358 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 1355 | sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc, | 1359 | sas_device = __mpt3sas_get_sdev_by_addr(ioc, |
| 1356 | rphy->identify.sas_address); | 1360 | rphy->identify.sas_address); |
| 1357 | if (sas_device) | 1361 | if (sas_device) { |
| 1358 | rc = sas_device->slot; | 1362 | rc = sas_device->slot; |
| 1359 | else | 1363 | sas_device_put(sas_device); |
| 1364 | } else { | ||
| 1360 | rc = -ENXIO; | 1365 | rc = -ENXIO; |
| 1366 | } | ||
| 1361 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 1367 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 1362 | return rc; | 1368 | return rc; |
| 1363 | } | 1369 | } |
diff --git a/drivers/scsi/mpt3sas/mpt3sas_warpdrive.c b/drivers/scsi/mpt3sas/mpt3sas_warpdrive.c new file mode 100644 index 000000000000..540bd5005149 --- /dev/null +++ b/drivers/scsi/mpt3sas/mpt3sas_warpdrive.c | |||
| @@ -0,0 +1,344 @@ | |||
| 1 | /* | ||
| 2 | * Scsi Host Layer for MPT (Message Passing Technology) based controllers | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012-2014 LSI Corporation | ||
| 5 | * Copyright (C) 2013-2015 Avago Technologies | ||
| 6 | * (mailto: MPT-FusionLinux.pdl@avagotech.com) | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or | ||
| 9 | * modify it under the terms of the GNU General Public License | ||
| 10 | * as published by the Free Software Foundation; either version 2 | ||
| 11 | * of the License, or (at your option) any later version. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | * | ||
| 18 | * NO WARRANTY | ||
| 19 | * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR | ||
| 20 | * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT | ||
| 21 | * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, | ||
| 22 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is | ||
| 23 | * solely responsible for determining the appropriateness of using and | ||
| 24 | * distributing the Program and assumes all risks associated with its | ||
| 25 | * exercise of rights under this Agreement, including but not limited to | ||
| 26 | * the risks and costs of program errors, damage to or loss of data, | ||
| 27 | * programs or equipment, and unavailability or interruption of operations. | ||
| 28 | |||
| 29 | * DISCLAIMER OF LIABILITY | ||
| 30 | * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY | ||
| 31 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 32 | * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND | ||
| 33 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR | ||
| 34 | * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | ||
| 35 | * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED | ||
| 36 | * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES | ||
| 37 | |||
| 38 | * You should have received a copy of the GNU General Public License | ||
| 39 | * along with this program. | ||
| 40 | */ | ||
| 41 | #include <linux/kernel.h> | ||
| 42 | #include <linux/module.h> | ||
| 43 | #include <linux/errno.h> | ||
| 44 | #include <linux/types.h> | ||
| 45 | #include <asm/unaligned.h> | ||
| 46 | |||
| 47 | #include "mpt3sas_base.h" | ||
| 48 | |||
| 49 | /** | ||
| 50 | * _warpdrive_disable_ddio - Disable direct I/O for all the volumes | ||
| 51 | * @ioc: per adapter object | ||
| 52 | */ | ||
| 53 | static void | ||
| 54 | _warpdrive_disable_ddio(struct MPT3SAS_ADAPTER *ioc) | ||
| 55 | { | ||
| 56 | Mpi2RaidVolPage1_t vol_pg1; | ||
| 57 | Mpi2ConfigReply_t mpi_reply; | ||
| 58 | struct _raid_device *raid_device; | ||
| 59 | u16 handle; | ||
| 60 | u16 ioc_status; | ||
| 61 | unsigned long flags; | ||
| 62 | |||
| 63 | handle = 0xFFFF; | ||
| 64 | while (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply, | ||
| 65 | &vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) { | ||
| 66 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
| 67 | MPI2_IOCSTATUS_MASK; | ||
| 68 | if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) | ||
| 69 | break; | ||
| 70 | handle = le16_to_cpu(vol_pg1.DevHandle); | ||
| 71 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | ||
| 72 | raid_device = mpt3sas_raid_device_find_by_handle(ioc, handle); | ||
| 73 | if (raid_device) | ||
| 74 | raid_device->direct_io_enabled = 0; | ||
| 75 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); | ||
| 76 | } | ||
| 77 | return; | ||
| 78 | } | ||
| 79 | |||
| 80 | |||
| 81 | /** | ||
| 82 | * mpt3sas_get_num_volumes - Get number of volumes in the ioc | ||
| 83 | * @ioc: per adapter object | ||
| 84 | */ | ||
| 85 | u8 | ||
| 86 | mpt3sas_get_num_volumes(struct MPT3SAS_ADAPTER *ioc) | ||
| 87 | { | ||
| 88 | Mpi2RaidVolPage1_t vol_pg1; | ||
| 89 | Mpi2ConfigReply_t mpi_reply; | ||
| 90 | u16 handle; | ||
| 91 | u8 vol_cnt = 0; | ||
| 92 | u16 ioc_status; | ||
| 93 | |||
| 94 | handle = 0xFFFF; | ||
| 95 | while (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply, | ||
| 96 | &vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) { | ||
| 97 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
| 98 | MPI2_IOCSTATUS_MASK; | ||
| 99 | if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) | ||
| 100 | break; | ||
| 101 | vol_cnt++; | ||
| 102 | handle = le16_to_cpu(vol_pg1.DevHandle); | ||
| 103 | } | ||
| 104 | return vol_cnt; | ||
| 105 | } | ||
| 106 | |||
| 107 | |||
| 108 | /** | ||
| 109 | * mpt3sas_init_warpdrive_properties - Set properties for warpdrive direct I/O. | ||
| 110 | * @ioc: per adapter object | ||
| 111 | * @raid_device: the raid_device object | ||
| 112 | */ | ||
| 113 | void | ||
| 114 | mpt3sas_init_warpdrive_properties(struct MPT3SAS_ADAPTER *ioc, | ||
| 115 | struct _raid_device *raid_device) | ||
| 116 | { | ||
| 117 | Mpi2RaidVolPage0_t *vol_pg0; | ||
| 118 | Mpi2RaidPhysDiskPage0_t pd_pg0; | ||
| 119 | Mpi2ConfigReply_t mpi_reply; | ||
| 120 | u16 sz; | ||
| 121 | u8 num_pds, count; | ||
| 122 | unsigned long stripe_sz, block_sz; | ||
| 123 | u8 stripe_exp, block_exp; | ||
| 124 | u64 dev_max_lba; | ||
| 125 | |||
| 126 | if (!ioc->is_warpdrive) | ||
| 127 | return; | ||
| 128 | |||
| 129 | if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_EXPOSE_ALL_DISKS) { | ||
| 130 | pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is disabled " | ||
| 131 | "globally as drives are exposed\n", ioc->name); | ||
| 132 | return; | ||
| 133 | } | ||
| 134 | if (mpt3sas_get_num_volumes(ioc) > 1) { | ||
| 135 | _warpdrive_disable_ddio(ioc); | ||
| 136 | pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is disabled " | ||
| 137 | "globally as number of drives > 1\n", ioc->name); | ||
| 138 | return; | ||
| 139 | } | ||
| 140 | if ((mpt3sas_config_get_number_pds(ioc, raid_device->handle, | ||
| 141 | &num_pds)) || !num_pds) { | ||
| 142 | pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is disabled " | ||
| 143 | "Failure in computing number of drives\n", ioc->name); | ||
| 144 | return; | ||
| 145 | } | ||
| 146 | |||
| 147 | sz = offsetof(Mpi2RaidVolPage0_t, PhysDisk) + (num_pds * | ||
| 148 | sizeof(Mpi2RaidVol0PhysDisk_t)); | ||
| 149 | vol_pg0 = kzalloc(sz, GFP_KERNEL); | ||
| 150 | if (!vol_pg0) { | ||
| 151 | pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is disabled " | ||
| 152 | "Memory allocation failure for RVPG0\n", ioc->name); | ||
| 153 | return; | ||
| 154 | } | ||
| 155 | |||
| 156 | if ((mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply, vol_pg0, | ||
| 157 | MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle, sz))) { | ||
| 158 | pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is disabled " | ||
| 159 | "Failure in retrieving RVPG0\n", ioc->name); | ||
| 160 | kfree(vol_pg0); | ||
| 161 | return; | ||
| 162 | } | ||
| 163 | |||
| 164 | /* | ||
| 165 | * WARPDRIVE:If number of physical disks in a volume exceeds the max pds | ||
| 166 | * assumed for WARPDRIVE, disable direct I/O | ||
| 167 | */ | ||
| 168 | if (num_pds > MPT_MAX_WARPDRIVE_PDS) { | ||
| 169 | pr_warn(MPT3SAS_FMT "WarpDrive : Direct IO is disabled " | ||
| 170 | "for the drive with handle(0x%04x): num_mem=%d, " | ||
| 171 | "max_mem_allowed=%d\n", ioc->name, raid_device->handle, | ||
| 172 | num_pds, MPT_MAX_WARPDRIVE_PDS); | ||
| 173 | kfree(vol_pg0); | ||
| 174 | return; | ||
| 175 | } | ||
| 176 | for (count = 0; count < num_pds; count++) { | ||
| 177 | if (mpt3sas_config_get_phys_disk_pg0(ioc, &mpi_reply, | ||
| 178 | &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM, | ||
| 179 | vol_pg0->PhysDisk[count].PhysDiskNum) || | ||
| 180 | pd_pg0.DevHandle == MPT3SAS_INVALID_DEVICE_HANDLE) { | ||
| 181 | pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is " | ||
| 182 | "disabled for the drive with handle(0x%04x) member" | ||
| 183 | "handle retrieval failed for member number=%d\n", | ||
| 184 | ioc->name, raid_device->handle, | ||
| 185 | vol_pg0->PhysDisk[count].PhysDiskNum); | ||
| 186 | goto out_error; | ||
| 187 | } | ||
| 188 | /* Disable direct I/O if member drive lba exceeds 4 bytes */ | ||
| 189 | dev_max_lba = le64_to_cpu(pd_pg0.DeviceMaxLBA); | ||
| 190 | if (dev_max_lba >> 32) { | ||
| 191 | pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is " | ||
| 192 | "disabled for the drive with handle(0x%04x) member" | ||
| 193 | " handle (0x%04x) unsupported max lba 0x%016llx\n", | ||
| 194 | ioc->name, raid_device->handle, | ||
| 195 | le16_to_cpu(pd_pg0.DevHandle), | ||
| 196 | (unsigned long long)dev_max_lba); | ||
| 197 | goto out_error; | ||
| 198 | } | ||
| 199 | |||
| 200 | raid_device->pd_handle[count] = le16_to_cpu(pd_pg0.DevHandle); | ||
| 201 | } | ||
| 202 | |||
| 203 | /* | ||
| 204 | * Assumption for WD: Direct I/O is not supported if the volume is | ||
| 205 | * not RAID0 | ||
| 206 | */ | ||
| 207 | if (raid_device->volume_type != MPI2_RAID_VOL_TYPE_RAID0) { | ||
| 208 | pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is disabled " | ||
| 209 | "for the drive with handle(0x%04x): type=%d, " | ||
| 210 | "s_sz=%uK, blk_size=%u\n", ioc->name, | ||
| 211 | raid_device->handle, raid_device->volume_type, | ||
| 212 | (le32_to_cpu(vol_pg0->StripeSize) * | ||
| 213 | le16_to_cpu(vol_pg0->BlockSize)) / 1024, | ||
| 214 | le16_to_cpu(vol_pg0->BlockSize)); | ||
| 215 | goto out_error; | ||
| 216 | } | ||
| 217 | |||
| 218 | stripe_sz = le32_to_cpu(vol_pg0->StripeSize); | ||
| 219 | stripe_exp = find_first_bit(&stripe_sz, 32); | ||
| 220 | if (stripe_exp == 32) { | ||
| 221 | pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is disabled " | ||
| 222 | "for the drive with handle(0x%04x) invalid stripe sz %uK\n", | ||
| 223 | ioc->name, raid_device->handle, | ||
| 224 | (le32_to_cpu(vol_pg0->StripeSize) * | ||
| 225 | le16_to_cpu(vol_pg0->BlockSize)) / 1024); | ||
| 226 | goto out_error; | ||
| 227 | } | ||
| 228 | raid_device->stripe_exponent = stripe_exp; | ||
| 229 | block_sz = le16_to_cpu(vol_pg0->BlockSize); | ||
| 230 | block_exp = find_first_bit(&block_sz, 16); | ||
| 231 | if (block_exp == 16) { | ||
| 232 | pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is disabled " | ||
| 233 | "for the drive with handle(0x%04x) invalid block sz %u\n", | ||
| 234 | ioc->name, raid_device->handle, | ||
| 235 | le16_to_cpu(vol_pg0->BlockSize)); | ||
| 236 | goto out_error; | ||
| 237 | } | ||
| 238 | raid_device->block_exponent = block_exp; | ||
| 239 | raid_device->direct_io_enabled = 1; | ||
| 240 | |||
| 241 | pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is Enabled for the drive" | ||
| 242 | " with handle(0x%04x)\n", ioc->name, raid_device->handle); | ||
| 243 | /* | ||
| 244 | * WARPDRIVE: Though the following fields are not used for direct IO, | ||
| 245 | * stored for future purpose: | ||
| 246 | */ | ||
| 247 | raid_device->max_lba = le64_to_cpu(vol_pg0->MaxLBA); | ||
| 248 | raid_device->stripe_sz = le32_to_cpu(vol_pg0->StripeSize); | ||
| 249 | raid_device->block_sz = le16_to_cpu(vol_pg0->BlockSize); | ||
| 250 | |||
| 251 | |||
| 252 | kfree(vol_pg0); | ||
| 253 | return; | ||
| 254 | |||
| 255 | out_error: | ||
| 256 | raid_device->direct_io_enabled = 0; | ||
| 257 | for (count = 0; count < num_pds; count++) | ||
| 258 | raid_device->pd_handle[count] = 0; | ||
| 259 | kfree(vol_pg0); | ||
| 260 | return; | ||
| 261 | } | ||
| 262 | |||
| 263 | /** | ||
| 264 | * mpt3sas_scsi_direct_io_get - returns direct io flag | ||
| 265 | * @ioc: per adapter object | ||
| 266 | * @smid: system request message index | ||
| 267 | * | ||
| 268 | * Returns the smid stored scmd pointer. | ||
| 269 | */ | ||
| 270 | inline u8 | ||
| 271 | mpt3sas_scsi_direct_io_get(struct MPT3SAS_ADAPTER *ioc, u16 smid) | ||
| 272 | { | ||
| 273 | return ioc->scsi_lookup[smid - 1].direct_io; | ||
| 274 | } | ||
| 275 | |||
| 276 | /** | ||
| 277 | * mpt3sas_scsi_direct_io_set - sets direct io flag | ||
| 278 | * @ioc: per adapter object | ||
| 279 | * @smid: system request message index | ||
| 280 | * @direct_io: Zero or non-zero value to set in the direct_io flag | ||
| 281 | * | ||
| 282 | * Returns Nothing. | ||
| 283 | */ | ||
| 284 | inline void | ||
| 285 | mpt3sas_scsi_direct_io_set(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 direct_io) | ||
| 286 | { | ||
| 287 | ioc->scsi_lookup[smid - 1].direct_io = direct_io; | ||
| 288 | } | ||
| 289 | |||
| 290 | /** | ||
| 291 | * mpt3sas_setup_direct_io - setup MPI request for WARPDRIVE Direct I/O | ||
| 292 | * @ioc: per adapter object | ||
| 293 | * @scmd: pointer to scsi command object | ||
| 294 | * @raid_device: pointer to raid device data structure | ||
| 295 | * @mpi_request: pointer to the SCSI_IO reqest message frame | ||
| 296 | * @smid: system request message index | ||
| 297 | * | ||
| 298 | * Returns nothing | ||
| 299 | */ | ||
| 300 | void | ||
| 301 | mpt3sas_setup_direct_io(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, | ||
| 302 | struct _raid_device *raid_device, Mpi2SCSIIORequest_t *mpi_request, | ||
| 303 | u16 smid) | ||
| 304 | { | ||
| 305 | sector_t v_lba, p_lba, stripe_off, column, io_size; | ||
| 306 | u32 stripe_sz, stripe_exp; | ||
| 307 | u8 num_pds, cmd = scmd->cmnd[0]; | ||
| 308 | |||
| 309 | if (cmd != READ_10 && cmd != WRITE_10 && | ||
| 310 | cmd != READ_16 && cmd != WRITE_16) | ||
| 311 | return; | ||
| 312 | |||
| 313 | if (cmd == READ_10 || cmd == WRITE_10) | ||
| 314 | v_lba = get_unaligned_be32(&mpi_request->CDB.CDB32[2]); | ||
| 315 | else | ||
| 316 | v_lba = get_unaligned_be64(&mpi_request->CDB.CDB32[2]); | ||
| 317 | |||
| 318 | io_size = scsi_bufflen(scmd) >> raid_device->block_exponent; | ||
| 319 | |||
| 320 | if (v_lba + io_size - 1 > raid_device->max_lba) | ||
| 321 | return; | ||
| 322 | |||
| 323 | stripe_sz = raid_device->stripe_sz; | ||
| 324 | stripe_exp = raid_device->stripe_exponent; | ||
| 325 | stripe_off = v_lba & (stripe_sz - 1); | ||
| 326 | |||
| 327 | /* Return unless IO falls within a stripe */ | ||
| 328 | if (stripe_off + io_size > stripe_sz) | ||
| 329 | return; | ||
| 330 | |||
| 331 | num_pds = raid_device->num_pds; | ||
| 332 | p_lba = v_lba >> stripe_exp; | ||
| 333 | column = sector_div(p_lba, num_pds); | ||
| 334 | p_lba = (p_lba << stripe_exp) + stripe_off; | ||
| 335 | mpi_request->DevHandle = cpu_to_le16(raid_device->pd_handle[column]); | ||
| 336 | |||
| 337 | if (cmd == READ_10 || cmd == WRITE_10) | ||
| 338 | put_unaligned_be32(lower_32_bits(p_lba), | ||
| 339 | &mpi_request->CDB.CDB32[2]); | ||
| 340 | else | ||
| 341 | put_unaligned_be64(p_lba, &mpi_request->CDB.CDB32[2]); | ||
| 342 | |||
| 343 | mpt3sas_scsi_direct_io_set(ioc, smid, 1); | ||
| 344 | } | ||
diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c index 221d25e9dc5f..90fdf0e859e3 100644 --- a/drivers/scsi/mvsas/mv_init.c +++ b/drivers/scsi/mvsas/mv_init.c | |||
| @@ -640,9 +640,9 @@ static void mvs_pci_remove(struct pci_dev *pdev) | |||
| 640 | tasklet_kill(&((struct mvs_prv_info *)sha->lldd_ha)->mv_tasklet); | 640 | tasklet_kill(&((struct mvs_prv_info *)sha->lldd_ha)->mv_tasklet); |
| 641 | #endif | 641 | #endif |
| 642 | 642 | ||
| 643 | scsi_remove_host(mvi->shost); | ||
| 643 | sas_unregister_ha(sha); | 644 | sas_unregister_ha(sha); |
| 644 | sas_remove_host(mvi->shost); | 645 | sas_remove_host(mvi->shost); |
| 645 | scsi_remove_host(mvi->shost); | ||
| 646 | 646 | ||
| 647 | MVS_CHIP_DISP->interrupt_disable(mvi); | 647 | MVS_CHIP_DISP->interrupt_disable(mvi); |
| 648 | free_irq(mvi->pdev->irq, sha); | 648 | free_irq(mvi->pdev->irq, sha); |
diff --git a/drivers/scsi/mvumi.c b/drivers/scsi/mvumi.c index 3e6b866759fe..02360de6b7e0 100644 --- a/drivers/scsi/mvumi.c +++ b/drivers/scsi/mvumi.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include <linux/spinlock.h> | 31 | #include <linux/spinlock.h> |
| 32 | #include <linux/interrupt.h> | 32 | #include <linux/interrupt.h> |
| 33 | #include <linux/delay.h> | 33 | #include <linux/delay.h> |
| 34 | #include <linux/ktime.h> | ||
| 34 | #include <linux/blkdev.h> | 35 | #include <linux/blkdev.h> |
| 35 | #include <linux/io.h> | 36 | #include <linux/io.h> |
| 36 | #include <scsi/scsi.h> | 37 | #include <scsi/scsi.h> |
| @@ -858,8 +859,8 @@ static void mvumi_hs_build_page(struct mvumi_hba *mhba, | |||
| 858 | struct mvumi_hs_page2 *hs_page2; | 859 | struct mvumi_hs_page2 *hs_page2; |
| 859 | struct mvumi_hs_page4 *hs_page4; | 860 | struct mvumi_hs_page4 *hs_page4; |
| 860 | struct mvumi_hs_page3 *hs_page3; | 861 | struct mvumi_hs_page3 *hs_page3; |
| 861 | struct timeval time; | 862 | u64 time; |
| 862 | unsigned int local_time; | 863 | u64 local_time; |
| 863 | 864 | ||
| 864 | switch (hs_header->page_code) { | 865 | switch (hs_header->page_code) { |
| 865 | case HS_PAGE_HOST_INFO: | 866 | case HS_PAGE_HOST_INFO: |
| @@ -877,9 +878,8 @@ static void mvumi_hs_build_page(struct mvumi_hba *mhba, | |||
| 877 | hs_page2->slot_number = 0; | 878 | hs_page2->slot_number = 0; |
| 878 | hs_page2->intr_level = 0; | 879 | hs_page2->intr_level = 0; |
| 879 | hs_page2->intr_vector = 0; | 880 | hs_page2->intr_vector = 0; |
| 880 | do_gettimeofday(&time); | 881 | time = ktime_get_real_seconds(); |
| 881 | local_time = (unsigned int) (time.tv_sec - | 882 | local_time = (time - (sys_tz.tz_minuteswest * 60)); |
| 882 | (sys_tz.tz_minuteswest * 60)); | ||
| 883 | hs_page2->seconds_since1970 = local_time; | 883 | hs_page2->seconds_since1970 = local_time; |
| 884 | hs_header->checksum = mvumi_calculate_checksum(hs_header, | 884 | hs_header->checksum = mvumi_calculate_checksum(hs_header, |
| 885 | hs_header->frame_length); | 885 | hs_header->frame_length); |
diff --git a/drivers/scsi/pm8001/pm8001_defs.h b/drivers/scsi/pm8001/pm8001_defs.h index f14ec6e042b9..199527dbaaa1 100644 --- a/drivers/scsi/pm8001/pm8001_defs.h +++ b/drivers/scsi/pm8001/pm8001_defs.h | |||
| @@ -51,6 +51,8 @@ enum chip_flavors { | |||
| 51 | chip_8076, | 51 | chip_8076, |
| 52 | chip_8077, | 52 | chip_8077, |
| 53 | chip_8006, | 53 | chip_8006, |
| 54 | chip_8070, | ||
| 55 | chip_8072 | ||
| 54 | }; | 56 | }; |
| 55 | 57 | ||
| 56 | enum phy_speed { | 58 | enum phy_speed { |
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index e64b8bfafd80..062ab34b86f8 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c | |||
| @@ -58,6 +58,8 @@ static const struct pm8001_chip_info pm8001_chips[] = { | |||
| 58 | [chip_8076] = {0, 16, &pm8001_80xx_dispatch,}, | 58 | [chip_8076] = {0, 16, &pm8001_80xx_dispatch,}, |
| 59 | [chip_8077] = {0, 16, &pm8001_80xx_dispatch,}, | 59 | [chip_8077] = {0, 16, &pm8001_80xx_dispatch,}, |
| 60 | [chip_8006] = {0, 16, &pm8001_80xx_dispatch,}, | 60 | [chip_8006] = {0, 16, &pm8001_80xx_dispatch,}, |
| 61 | [chip_8070] = {0, 8, &pm8001_80xx_dispatch,}, | ||
| 62 | [chip_8072] = {0, 16, &pm8001_80xx_dispatch,}, | ||
| 61 | }; | 63 | }; |
| 62 | static int pm8001_id; | 64 | static int pm8001_id; |
| 63 | 65 | ||
| @@ -479,7 +481,8 @@ static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev, | |||
| 479 | 481 | ||
| 480 | #ifdef PM8001_USE_TASKLET | 482 | #ifdef PM8001_USE_TASKLET |
| 481 | /* Tasklet for non msi-x interrupt handler */ | 483 | /* Tasklet for non msi-x interrupt handler */ |
| 482 | if ((!pdev->msix_cap) || (pm8001_ha->chip_id == chip_8001)) | 484 | if ((!pdev->msix_cap || !pci_msi_enabled()) |
| 485 | || (pm8001_ha->chip_id == chip_8001)) | ||
| 483 | tasklet_init(&pm8001_ha->tasklet[0], pm8001_tasklet, | 486 | tasklet_init(&pm8001_ha->tasklet[0], pm8001_tasklet, |
| 484 | (unsigned long)&(pm8001_ha->irq_vector[0])); | 487 | (unsigned long)&(pm8001_ha->irq_vector[0])); |
| 485 | else | 488 | else |
| @@ -633,6 +636,11 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha) | |||
| 633 | payload.minor_function = 0; | 636 | payload.minor_function = 0; |
| 634 | payload.length = 128; | 637 | payload.length = 128; |
| 635 | } | 638 | } |
| 639 | } else if ((pm8001_ha->chip_id == chip_8070 || | ||
| 640 | pm8001_ha->chip_id == chip_8072) && | ||
| 641 | pm8001_ha->pdev->subsystem_vendor == PCI_VENDOR_ID_ATTO) { | ||
| 642 | payload.minor_function = 4; | ||
| 643 | payload.length = 4096; | ||
| 636 | } else { | 644 | } else { |
| 637 | payload.minor_function = 1; | 645 | payload.minor_function = 1; |
| 638 | payload.length = 4096; | 646 | payload.length = 4096; |
| @@ -659,6 +667,11 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha) | |||
| 659 | else if (deviceid == 0x0042) | 667 | else if (deviceid == 0x0042) |
| 660 | pm8001_ha->sas_addr[j] = | 668 | pm8001_ha->sas_addr[j] = |
| 661 | payload.func_specific[0x010 + i]; | 669 | payload.func_specific[0x010 + i]; |
| 670 | } else if ((pm8001_ha->chip_id == chip_8070 || | ||
| 671 | pm8001_ha->chip_id == chip_8072) && | ||
| 672 | pm8001_ha->pdev->subsystem_vendor == PCI_VENDOR_ID_ATTO) { | ||
| 673 | pm8001_ha->sas_addr[j] = | ||
| 674 | payload.func_specific[0x010 + i]; | ||
| 662 | } else | 675 | } else |
| 663 | pm8001_ha->sas_addr[j] = | 676 | pm8001_ha->sas_addr[j] = |
| 664 | payload.func_specific[0x804 + i]; | 677 | payload.func_specific[0x804 + i]; |
| @@ -719,6 +732,153 @@ static int pm8001_get_phy_settings_info(struct pm8001_hba_info *pm8001_ha) | |||
| 719 | return 0; | 732 | return 0; |
| 720 | } | 733 | } |
| 721 | 734 | ||
| 735 | struct pm8001_mpi3_phy_pg_trx_config { | ||
| 736 | u32 LaneLosCfg; | ||
| 737 | u32 LanePgaCfg1; | ||
| 738 | u32 LanePisoCfg1; | ||
| 739 | u32 LanePisoCfg2; | ||
| 740 | u32 LanePisoCfg3; | ||
| 741 | u32 LanePisoCfg4; | ||
| 742 | u32 LanePisoCfg5; | ||
| 743 | u32 LanePisoCfg6; | ||
| 744 | u32 LaneBctCtrl; | ||
| 745 | }; | ||
| 746 | |||
| 747 | /** | ||
| 748 | * pm8001_get_internal_phy_settings : Retrieves the internal PHY settings | ||
| 749 | * @pm8001_ha : our adapter | ||
| 750 | * @phycfg : PHY config page to populate | ||
| 751 | */ | ||
| 752 | static | ||
| 753 | void pm8001_get_internal_phy_settings(struct pm8001_hba_info *pm8001_ha, | ||
| 754 | struct pm8001_mpi3_phy_pg_trx_config *phycfg) | ||
| 755 | { | ||
| 756 | phycfg->LaneLosCfg = 0x00000132; | ||
| 757 | phycfg->LanePgaCfg1 = 0x00203949; | ||
| 758 | phycfg->LanePisoCfg1 = 0x000000FF; | ||
| 759 | phycfg->LanePisoCfg2 = 0xFF000001; | ||
| 760 | phycfg->LanePisoCfg3 = 0xE7011300; | ||
| 761 | phycfg->LanePisoCfg4 = 0x631C40C0; | ||
| 762 | phycfg->LanePisoCfg5 = 0xF8102036; | ||
| 763 | phycfg->LanePisoCfg6 = 0xF74A1000; | ||
| 764 | phycfg->LaneBctCtrl = 0x00FB33F8; | ||
| 765 | } | ||
| 766 | |||
| 767 | /** | ||
| 768 | * pm8001_get_external_phy_settings : Retrieves the external PHY settings | ||
| 769 | * @pm8001_ha : our adapter | ||
| 770 | * @phycfg : PHY config page to populate | ||
| 771 | */ | ||
| 772 | static | ||
| 773 | void pm8001_get_external_phy_settings(struct pm8001_hba_info *pm8001_ha, | ||
| 774 | struct pm8001_mpi3_phy_pg_trx_config *phycfg) | ||
| 775 | { | ||
| 776 | phycfg->LaneLosCfg = 0x00000132; | ||
| 777 | phycfg->LanePgaCfg1 = 0x00203949; | ||
| 778 | phycfg->LanePisoCfg1 = 0x000000FF; | ||
| 779 | phycfg->LanePisoCfg2 = 0xFF000001; | ||
| 780 | phycfg->LanePisoCfg3 = 0xE7011300; | ||
| 781 | phycfg->LanePisoCfg4 = 0x63349140; | ||
| 782 | phycfg->LanePisoCfg5 = 0xF8102036; | ||
| 783 | phycfg->LanePisoCfg6 = 0xF80D9300; | ||
| 784 | phycfg->LaneBctCtrl = 0x00FB33F8; | ||
| 785 | } | ||
| 786 | |||
| 787 | /** | ||
| 788 | * pm8001_get_phy_mask : Retrieves the mask that denotes if a PHY is int/ext | ||
| 789 | * @pm8001_ha : our adapter | ||
| 790 | * @phymask : The PHY mask | ||
| 791 | */ | ||
| 792 | static | ||
| 793 | void pm8001_get_phy_mask(struct pm8001_hba_info *pm8001_ha, int *phymask) | ||
| 794 | { | ||
| 795 | switch (pm8001_ha->pdev->subsystem_device) { | ||
| 796 | case 0x0070: /* H1280 - 8 external 0 internal */ | ||
| 797 | case 0x0072: /* H12F0 - 16 external 0 internal */ | ||
| 798 | *phymask = 0x0000; | ||
| 799 | break; | ||
| 800 | |||
| 801 | case 0x0071: /* H1208 - 0 external 8 internal */ | ||
| 802 | case 0x0073: /* H120F - 0 external 16 internal */ | ||
| 803 | *phymask = 0xFFFF; | ||
| 804 | break; | ||
| 805 | |||
| 806 | case 0x0080: /* H1244 - 4 external 4 internal */ | ||
| 807 | *phymask = 0x00F0; | ||
| 808 | break; | ||
| 809 | |||
| 810 | case 0x0081: /* H1248 - 4 external 8 internal */ | ||
| 811 | *phymask = 0x0FF0; | ||
| 812 | break; | ||
| 813 | |||
| 814 | case 0x0082: /* H1288 - 8 external 8 internal */ | ||
| 815 | *phymask = 0xFF00; | ||
| 816 | break; | ||
| 817 | |||
| 818 | default: | ||
| 819 | PM8001_INIT_DBG(pm8001_ha, | ||
| 820 | pm8001_printk("Unknown subsystem device=0x%.04x", | ||
| 821 | pm8001_ha->pdev->subsystem_device)); | ||
| 822 | } | ||
| 823 | } | ||
| 824 | |||
| 825 | /** | ||
| 826 | * pm8001_set_phy_settings_ven_117c_12Gb : Configure ATTO 12Gb PHY settings | ||
| 827 | * @pm8001_ha : our adapter | ||
| 828 | */ | ||
| 829 | static | ||
| 830 | int pm8001_set_phy_settings_ven_117c_12G(struct pm8001_hba_info *pm8001_ha) | ||
| 831 | { | ||
| 832 | struct pm8001_mpi3_phy_pg_trx_config phycfg_int; | ||
| 833 | struct pm8001_mpi3_phy_pg_trx_config phycfg_ext; | ||
| 834 | int phymask = 0; | ||
| 835 | int i = 0; | ||
| 836 | |||
| 837 | memset(&phycfg_int, 0, sizeof(phycfg_int)); | ||
| 838 | memset(&phycfg_ext, 0, sizeof(phycfg_ext)); | ||
| 839 | |||
| 840 | pm8001_get_internal_phy_settings(pm8001_ha, &phycfg_int); | ||
| 841 | pm8001_get_external_phy_settings(pm8001_ha, &phycfg_ext); | ||
| 842 | pm8001_get_phy_mask(pm8001_ha, &phymask); | ||
| 843 | |||
| 844 | for (i = 0; i < pm8001_ha->chip->n_phy; i++) { | ||
| 845 | if (phymask & (1 << i)) {/* Internal PHY */ | ||
| 846 | pm8001_set_phy_profile_single(pm8001_ha, i, | ||
| 847 | sizeof(phycfg_int) / sizeof(u32), | ||
| 848 | (u32 *)&phycfg_int); | ||
| 849 | |||
| 850 | } else { /* External PHY */ | ||
| 851 | pm8001_set_phy_profile_single(pm8001_ha, i, | ||
| 852 | sizeof(phycfg_ext) / sizeof(u32), | ||
| 853 | (u32 *)&phycfg_ext); | ||
| 854 | } | ||
| 855 | } | ||
| 856 | |||
| 857 | return 0; | ||
| 858 | } | ||
| 859 | |||
| 860 | /** | ||
| 861 | * pm8001_configure_phy_settings : Configures PHY settings based on vendor ID. | ||
| 862 | * @pm8001_ha : our hba. | ||
| 863 | */ | ||
| 864 | static int pm8001_configure_phy_settings(struct pm8001_hba_info *pm8001_ha) | ||
| 865 | { | ||
| 866 | switch (pm8001_ha->pdev->subsystem_vendor) { | ||
| 867 | case PCI_VENDOR_ID_ATTO: | ||
| 868 | if (pm8001_ha->pdev->device == 0x0042) /* 6Gb */ | ||
| 869 | return 0; | ||
| 870 | else | ||
| 871 | return pm8001_set_phy_settings_ven_117c_12G(pm8001_ha); | ||
| 872 | |||
| 873 | case PCI_VENDOR_ID_ADAPTEC2: | ||
| 874 | case 0: | ||
| 875 | return 0; | ||
| 876 | |||
| 877 | default: | ||
| 878 | return pm8001_get_phy_settings_info(pm8001_ha); | ||
| 879 | } | ||
| 880 | } | ||
| 881 | |||
| 722 | #ifdef PM8001_USE_MSIX | 882 | #ifdef PM8001_USE_MSIX |
| 723 | /** | 883 | /** |
| 724 | * pm8001_setup_msix - enable MSI-X interrupt | 884 | * pm8001_setup_msix - enable MSI-X interrupt |
| @@ -791,7 +951,7 @@ static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha) | |||
| 791 | pdev = pm8001_ha->pdev; | 951 | pdev = pm8001_ha->pdev; |
| 792 | 952 | ||
| 793 | #ifdef PM8001_USE_MSIX | 953 | #ifdef PM8001_USE_MSIX |
| 794 | if (pdev->msix_cap) | 954 | if (pdev->msix_cap && pci_msi_enabled()) |
| 795 | return pm8001_setup_msix(pm8001_ha); | 955 | return pm8001_setup_msix(pm8001_ha); |
| 796 | else { | 956 | else { |
| 797 | PM8001_INIT_DBG(pm8001_ha, | 957 | PM8001_INIT_DBG(pm8001_ha, |
| @@ -802,6 +962,8 @@ static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha) | |||
| 802 | 962 | ||
| 803 | intx: | 963 | intx: |
| 804 | /* initialize the INT-X interrupt */ | 964 | /* initialize the INT-X interrupt */ |
| 965 | pm8001_ha->irq_vector[0].irq_id = 0; | ||
| 966 | pm8001_ha->irq_vector[0].drv_inst = pm8001_ha; | ||
| 805 | rc = request_irq(pdev->irq, pm8001_interrupt_handler_intx, IRQF_SHARED, | 967 | rc = request_irq(pdev->irq, pm8001_interrupt_handler_intx, IRQF_SHARED, |
| 806 | DRV_NAME, SHOST_TO_SAS_HA(pm8001_ha->shost)); | 968 | DRV_NAME, SHOST_TO_SAS_HA(pm8001_ha->shost)); |
| 807 | return rc; | 969 | return rc; |
| @@ -901,12 +1063,9 @@ static int pm8001_pci_probe(struct pci_dev *pdev, | |||
| 901 | 1063 | ||
| 902 | pm8001_init_sas_add(pm8001_ha); | 1064 | pm8001_init_sas_add(pm8001_ha); |
| 903 | /* phy setting support for motherboard controller */ | 1065 | /* phy setting support for motherboard controller */ |
| 904 | if (pdev->subsystem_vendor != PCI_VENDOR_ID_ADAPTEC2 && | 1066 | if (pm8001_configure_phy_settings(pm8001_ha)) |
| 905 | pdev->subsystem_vendor != 0) { | 1067 | goto err_out_shost; |
| 906 | rc = pm8001_get_phy_settings_info(pm8001_ha); | 1068 | |
| 907 | if (rc) | ||
| 908 | goto err_out_shost; | ||
| 909 | } | ||
| 910 | pm8001_post_sas_ha_init(shost, chip); | 1069 | pm8001_post_sas_ha_init(shost, chip); |
| 911 | rc = sas_register_ha(SHOST_TO_SAS_HA(shost)); | 1070 | rc = sas_register_ha(SHOST_TO_SAS_HA(shost)); |
| 912 | if (rc) | 1071 | if (rc) |
| @@ -936,10 +1095,10 @@ static void pm8001_pci_remove(struct pci_dev *pdev) | |||
| 936 | struct pm8001_hba_info *pm8001_ha; | 1095 | struct pm8001_hba_info *pm8001_ha; |
| 937 | int i, j; | 1096 | int i, j; |
| 938 | pm8001_ha = sha->lldd_ha; | 1097 | pm8001_ha = sha->lldd_ha; |
| 1098 | scsi_remove_host(pm8001_ha->shost); | ||
| 939 | sas_unregister_ha(sha); | 1099 | sas_unregister_ha(sha); |
| 940 | sas_remove_host(pm8001_ha->shost); | 1100 | sas_remove_host(pm8001_ha->shost); |
| 941 | list_del(&pm8001_ha->list); | 1101 | list_del(&pm8001_ha->list); |
| 942 | scsi_remove_host(pm8001_ha->shost); | ||
| 943 | PM8001_CHIP_DISP->interrupt_disable(pm8001_ha, 0xFF); | 1102 | PM8001_CHIP_DISP->interrupt_disable(pm8001_ha, 0xFF); |
| 944 | PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha); | 1103 | PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha); |
| 945 | 1104 | ||
| @@ -955,7 +1114,8 @@ static void pm8001_pci_remove(struct pci_dev *pdev) | |||
| 955 | #endif | 1114 | #endif |
| 956 | #ifdef PM8001_USE_TASKLET | 1115 | #ifdef PM8001_USE_TASKLET |
| 957 | /* For non-msix and msix interrupts */ | 1116 | /* For non-msix and msix interrupts */ |
| 958 | if ((!pdev->msix_cap) || (pm8001_ha->chip_id == chip_8001)) | 1117 | if ((!pdev->msix_cap || !pci_msi_enabled()) || |
| 1118 | (pm8001_ha->chip_id == chip_8001)) | ||
| 959 | tasklet_kill(&pm8001_ha->tasklet[0]); | 1119 | tasklet_kill(&pm8001_ha->tasklet[0]); |
| 960 | else | 1120 | else |
| 961 | for (j = 0; j < PM8001_MAX_MSIX_VEC; j++) | 1121 | for (j = 0; j < PM8001_MAX_MSIX_VEC; j++) |
| @@ -1004,7 +1164,8 @@ static int pm8001_pci_suspend(struct pci_dev *pdev, pm_message_t state) | |||
| 1004 | #endif | 1164 | #endif |
| 1005 | #ifdef PM8001_USE_TASKLET | 1165 | #ifdef PM8001_USE_TASKLET |
| 1006 | /* For non-msix and msix interrupts */ | 1166 | /* For non-msix and msix interrupts */ |
| 1007 | if ((!pdev->msix_cap) || (pm8001_ha->chip_id == chip_8001)) | 1167 | if ((!pdev->msix_cap || !pci_msi_enabled()) || |
| 1168 | (pm8001_ha->chip_id == chip_8001)) | ||
| 1008 | tasklet_kill(&pm8001_ha->tasklet[0]); | 1169 | tasklet_kill(&pm8001_ha->tasklet[0]); |
| 1009 | else | 1170 | else |
| 1010 | for (j = 0; j < PM8001_MAX_MSIX_VEC; j++) | 1171 | for (j = 0; j < PM8001_MAX_MSIX_VEC; j++) |
| @@ -1073,7 +1234,8 @@ static int pm8001_pci_resume(struct pci_dev *pdev) | |||
| 1073 | goto err_out_disable; | 1234 | goto err_out_disable; |
| 1074 | #ifdef PM8001_USE_TASKLET | 1235 | #ifdef PM8001_USE_TASKLET |
| 1075 | /* Tasklet for non msi-x interrupt handler */ | 1236 | /* Tasklet for non msi-x interrupt handler */ |
| 1076 | if ((!pdev->msix_cap) || (pm8001_ha->chip_id == chip_8001)) | 1237 | if ((!pdev->msix_cap || !pci_msi_enabled()) || |
| 1238 | (pm8001_ha->chip_id == chip_8001)) | ||
| 1077 | tasklet_init(&pm8001_ha->tasklet[0], pm8001_tasklet, | 1239 | tasklet_init(&pm8001_ha->tasklet[0], pm8001_tasklet, |
| 1078 | (unsigned long)&(pm8001_ha->irq_vector[0])); | 1240 | (unsigned long)&(pm8001_ha->irq_vector[0])); |
| 1079 | else | 1241 | else |
| @@ -1086,6 +1248,19 @@ static int pm8001_pci_resume(struct pci_dev *pdev) | |||
| 1086 | for (i = 1; i < pm8001_ha->number_of_intr; i++) | 1248 | for (i = 1; i < pm8001_ha->number_of_intr; i++) |
| 1087 | PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, i); | 1249 | PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, i); |
| 1088 | } | 1250 | } |
| 1251 | |||
| 1252 | /* Chip documentation for the 8070 and 8072 SPCv */ | ||
| 1253 | /* states that a 500ms minimum delay is required */ | ||
| 1254 | /* before issuing commands. Otherwise, the firmare */ | ||
| 1255 | /* will enter an unrecoverable state. */ | ||
| 1256 | |||
| 1257 | if (pm8001_ha->chip_id == chip_8070 || | ||
| 1258 | pm8001_ha->chip_id == chip_8072) { | ||
| 1259 | mdelay(500); | ||
| 1260 | } | ||
| 1261 | |||
| 1262 | /* Spin up the PHYs */ | ||
| 1263 | |||
| 1089 | pm8001_ha->flags = PM8001F_RUN_TIME; | 1264 | pm8001_ha->flags = PM8001F_RUN_TIME; |
| 1090 | for (i = 0; i < pm8001_ha->chip->n_phy; i++) { | 1265 | for (i = 0; i < pm8001_ha->chip->n_phy; i++) { |
| 1091 | pm8001_ha->phy[i].enable_completion = &completion; | 1266 | pm8001_ha->phy[i].enable_completion = &completion; |
| @@ -1164,6 +1339,20 @@ static struct pci_device_id pm8001_pci_table[] = { | |||
| 1164 | PCI_VENDOR_ID_ADAPTEC2, 0x0808, 0, 0, chip_8077 }, | 1339 | PCI_VENDOR_ID_ADAPTEC2, 0x0808, 0, 0, chip_8077 }, |
| 1165 | { PCI_VENDOR_ID_ADAPTEC2, 0x8074, | 1340 | { PCI_VENDOR_ID_ADAPTEC2, 0x8074, |
| 1166 | PCI_VENDOR_ID_ADAPTEC2, 0x0404, 0, 0, chip_8074 }, | 1341 | PCI_VENDOR_ID_ADAPTEC2, 0x0404, 0, 0, chip_8074 }, |
| 1342 | { PCI_VENDOR_ID_ATTO, 0x8070, | ||
| 1343 | PCI_VENDOR_ID_ATTO, 0x0070, 0, 0, chip_8070 }, | ||
| 1344 | { PCI_VENDOR_ID_ATTO, 0x8070, | ||
| 1345 | PCI_VENDOR_ID_ATTO, 0x0071, 0, 0, chip_8070 }, | ||
| 1346 | { PCI_VENDOR_ID_ATTO, 0x8072, | ||
| 1347 | PCI_VENDOR_ID_ATTO, 0x0072, 0, 0, chip_8072 }, | ||
| 1348 | { PCI_VENDOR_ID_ATTO, 0x8072, | ||
| 1349 | PCI_VENDOR_ID_ATTO, 0x0073, 0, 0, chip_8072 }, | ||
| 1350 | { PCI_VENDOR_ID_ATTO, 0x8070, | ||
| 1351 | PCI_VENDOR_ID_ATTO, 0x0080, 0, 0, chip_8070 }, | ||
| 1352 | { PCI_VENDOR_ID_ATTO, 0x8072, | ||
| 1353 | PCI_VENDOR_ID_ATTO, 0x0081, 0, 0, chip_8072 }, | ||
| 1354 | { PCI_VENDOR_ID_ATTO, 0x8072, | ||
| 1355 | PCI_VENDOR_ID_ATTO, 0x0082, 0, 0, chip_8072 }, | ||
| 1167 | {} /* terminate list */ | 1356 | {} /* terminate list */ |
| 1168 | }; | 1357 | }; |
| 1169 | 1358 | ||
| @@ -1219,7 +1408,7 @@ MODULE_AUTHOR("Anand Kumar Santhanam <AnandKumar.Santhanam@pmcs.com>"); | |||
| 1219 | MODULE_AUTHOR("Sangeetha Gnanasekaran <Sangeetha.Gnanasekaran@pmcs.com>"); | 1408 | MODULE_AUTHOR("Sangeetha Gnanasekaran <Sangeetha.Gnanasekaran@pmcs.com>"); |
| 1220 | MODULE_AUTHOR("Nikith Ganigarakoppal <Nikith.Ganigarakoppal@pmcs.com>"); | 1409 | MODULE_AUTHOR("Nikith Ganigarakoppal <Nikith.Ganigarakoppal@pmcs.com>"); |
| 1221 | MODULE_DESCRIPTION( | 1410 | MODULE_DESCRIPTION( |
| 1222 | "PMC-Sierra PM8001/8006/8081/8088/8089/8074/8076/8077 " | 1411 | "PMC-Sierra PM8001/8006/8081/8088/8089/8074/8076/8077/8070/8072 " |
| 1223 | "SAS/SATA controller driver"); | 1412 | "SAS/SATA controller driver"); |
| 1224 | MODULE_VERSION(DRV_VERSION); | 1413 | MODULE_VERSION(DRV_VERSION); |
| 1225 | MODULE_LICENSE("GPL"); | 1414 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h index e2e97db38ae8..6628cc38316c 100644 --- a/drivers/scsi/pm8001/pm8001_sas.h +++ b/drivers/scsi/pm8001/pm8001_sas.h | |||
| @@ -106,7 +106,9 @@ do { \ | |||
| 106 | #define DEV_IS_EXPANDER(type) ((type == SAS_EDGE_EXPANDER_DEVICE) || (type == SAS_FANOUT_EXPANDER_DEVICE)) | 106 | #define DEV_IS_EXPANDER(type) ((type == SAS_EDGE_EXPANDER_DEVICE) || (type == SAS_FANOUT_EXPANDER_DEVICE)) |
| 107 | #define IS_SPCV_12G(dev) ((dev->device == 0X8074) \ | 107 | #define IS_SPCV_12G(dev) ((dev->device == 0X8074) \ |
| 108 | || (dev->device == 0X8076) \ | 108 | || (dev->device == 0X8076) \ |
| 109 | || (dev->device == 0X8077)) | 109 | || (dev->device == 0X8077) \ |
| 110 | || (dev->device == 0X8070) \ | ||
| 111 | || (dev->device == 0X8072)) | ||
| 110 | 112 | ||
| 111 | #define PM8001_NAME_LENGTH 32/* generic length of strings */ | 113 | #define PM8001_NAME_LENGTH 32/* generic length of strings */ |
| 112 | extern struct list_head hba_list; | 114 | extern struct list_head hba_list; |
| @@ -708,6 +710,8 @@ int pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha); | |||
| 708 | int pm8001_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue); | 710 | int pm8001_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue); |
| 709 | void pm8001_set_phy_profile(struct pm8001_hba_info *pm8001_ha, | 711 | void pm8001_set_phy_profile(struct pm8001_hba_info *pm8001_ha, |
| 710 | u32 length, u8 *buf); | 712 | u32 length, u8 *buf); |
| 713 | void pm8001_set_phy_profile_single(struct pm8001_hba_info *pm8001_ha, | ||
| 714 | u32 phy, u32 length, u32 *buf); | ||
| 711 | int pm80xx_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue); | 715 | int pm80xx_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue); |
| 712 | ssize_t pm80xx_get_fatal_dump(struct device *cdev, | 716 | ssize_t pm80xx_get_fatal_dump(struct device *cdev, |
| 713 | struct device_attribute *attr, char *buf); | 717 | struct device_attribute *attr, char *buf); |
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c index 9a389f1508de..eb4fee61df72 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.c +++ b/drivers/scsi/pm8001/pm80xx_hwi.c | |||
| @@ -1267,6 +1267,8 @@ pm80xx_chip_soft_rst(struct pm8001_hba_info *pm8001_ha) | |||
| 1267 | /* check iButton feature support for motherboard controller */ | 1267 | /* check iButton feature support for motherboard controller */ |
| 1268 | if (pm8001_ha->pdev->subsystem_vendor != | 1268 | if (pm8001_ha->pdev->subsystem_vendor != |
| 1269 | PCI_VENDOR_ID_ADAPTEC2 && | 1269 | PCI_VENDOR_ID_ADAPTEC2 && |
| 1270 | pm8001_ha->pdev->subsystem_vendor != | ||
| 1271 | PCI_VENDOR_ID_ATTO && | ||
| 1270 | pm8001_ha->pdev->subsystem_vendor != 0) { | 1272 | pm8001_ha->pdev->subsystem_vendor != 0) { |
| 1271 | ibutton0 = pm8001_cr32(pm8001_ha, 0, | 1273 | ibutton0 = pm8001_cr32(pm8001_ha, 0, |
| 1272 | MSGU_HOST_SCRATCH_PAD_6); | 1274 | MSGU_HOST_SCRATCH_PAD_6); |
| @@ -4576,6 +4578,38 @@ void pm8001_set_phy_profile(struct pm8001_hba_info *pm8001_ha, | |||
| 4576 | } | 4578 | } |
| 4577 | PM8001_INIT_DBG(pm8001_ha, pm8001_printk("phy settings completed\n")); | 4579 | PM8001_INIT_DBG(pm8001_ha, pm8001_printk("phy settings completed\n")); |
| 4578 | } | 4580 | } |
| 4581 | |||
| 4582 | void pm8001_set_phy_profile_single(struct pm8001_hba_info *pm8001_ha, | ||
| 4583 | u32 phy, u32 length, u32 *buf) | ||
| 4584 | { | ||
| 4585 | u32 tag, opc; | ||
| 4586 | int rc, i; | ||
| 4587 | struct set_phy_profile_req payload; | ||
| 4588 | struct inbound_queue_table *circularQ; | ||
| 4589 | |||
| 4590 | memset(&payload, 0, sizeof(payload)); | ||
| 4591 | |||
| 4592 | rc = pm8001_tag_alloc(pm8001_ha, &tag); | ||
| 4593 | if (rc) | ||
| 4594 | PM8001_INIT_DBG(pm8001_ha, pm8001_printk("Invalid tag")); | ||
| 4595 | |||
| 4596 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | ||
| 4597 | opc = OPC_INB_SET_PHY_PROFILE; | ||
| 4598 | |||
| 4599 | payload.tag = cpu_to_le32(tag); | ||
| 4600 | payload.ppc_phyid = (((SAS_PHY_ANALOG_SETTINGS_PAGE & 0xF) << 8) | ||
| 4601 | | (phy & 0xFF)); | ||
| 4602 | |||
| 4603 | for (i = 0; i < length; i++) | ||
| 4604 | payload.reserved[i] = cpu_to_le32(*(buf + i)); | ||
| 4605 | |||
| 4606 | rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); | ||
| 4607 | if (rc) | ||
| 4608 | pm8001_tag_free(pm8001_ha, tag); | ||
| 4609 | |||
| 4610 | PM8001_INIT_DBG(pm8001_ha, | ||
| 4611 | pm8001_printk("PHY %d settings applied", phy)); | ||
| 4612 | } | ||
| 4579 | const struct pm8001_dispatch pm8001_80xx_dispatch = { | 4613 | const struct pm8001_dispatch pm8001_80xx_dispatch = { |
| 4580 | .name = "pmc80xx", | 4614 | .name = "pmc80xx", |
| 4581 | .chip_init = pm80xx_chip_init, | 4615 | .chip_init = pm80xx_chip_init, |
diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c index 48d62249c226..b2a88200fe54 100644 --- a/drivers/scsi/pmcraid.c +++ b/drivers/scsi/pmcraid.c | |||
| @@ -45,6 +45,7 @@ | |||
| 45 | #include <asm/processor.h> | 45 | #include <asm/processor.h> |
| 46 | #include <linux/libata.h> | 46 | #include <linux/libata.h> |
| 47 | #include <linux/mutex.h> | 47 | #include <linux/mutex.h> |
| 48 | #include <linux/ktime.h> | ||
| 48 | #include <scsi/scsi.h> | 49 | #include <scsi/scsi.h> |
| 49 | #include <scsi/scsi_host.h> | 50 | #include <scsi/scsi_host.h> |
| 50 | #include <scsi/scsi_device.h> | 51 | #include <scsi/scsi_device.h> |
| @@ -5562,11 +5563,9 @@ static void pmcraid_set_timestamp(struct pmcraid_cmd *cmd) | |||
| 5562 | __be32 time_stamp_len = cpu_to_be32(PMCRAID_TIMESTAMP_LEN); | 5563 | __be32 time_stamp_len = cpu_to_be32(PMCRAID_TIMESTAMP_LEN); |
| 5563 | struct pmcraid_ioadl_desc *ioadl = ioarcb->add_data.u.ioadl; | 5564 | struct pmcraid_ioadl_desc *ioadl = ioarcb->add_data.u.ioadl; |
| 5564 | 5565 | ||
| 5565 | struct timeval tv; | ||
| 5566 | __le64 timestamp; | 5566 | __le64 timestamp; |
| 5567 | 5567 | ||
| 5568 | do_gettimeofday(&tv); | 5568 | timestamp = ktime_get_real_seconds() * 1000; |
| 5569 | timestamp = tv.tv_sec * 1000; | ||
| 5570 | 5569 | ||
| 5571 | pinstance->timestamp_data->timestamp[0] = (__u8)(timestamp); | 5570 | pinstance->timestamp_data->timestamp[0] = (__u8)(timestamp); |
| 5572 | pinstance->timestamp_data->timestamp[1] = (__u8)((timestamp) >> 8); | 5571 | pinstance->timestamp_data->timestamp[1] = (__u8)((timestamp) >> 8); |
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 998f3788d8e9..83245391e956 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c | |||
| @@ -55,6 +55,7 @@ | |||
| 55 | * Default timeout | 55 | * Default timeout |
| 56 | */ | 56 | */ |
| 57 | #define SCSI_TIMEOUT (2*HZ) | 57 | #define SCSI_TIMEOUT (2*HZ) |
| 58 | #define SCSI_REPORT_LUNS_TIMEOUT (30*HZ) | ||
| 58 | 59 | ||
| 59 | /* | 60 | /* |
| 60 | * Prefix values for the SCSI id's (stored in sysfs name field) | 61 | * Prefix values for the SCSI id's (stored in sysfs name field) |
| @@ -1382,7 +1383,7 @@ retry: | |||
| 1382 | 1383 | ||
| 1383 | result = scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, | 1384 | result = scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, |
| 1384 | lun_data, length, &sshdr, | 1385 | lun_data, length, &sshdr, |
| 1385 | SCSI_TIMEOUT + 4 * HZ, 3, NULL); | 1386 | SCSI_REPORT_LUNS_TIMEOUT, 3, NULL); |
| 1386 | 1387 | ||
| 1387 | SCSI_LOG_SCAN_BUS(3, sdev_printk (KERN_INFO, sdev, | 1388 | SCSI_LOG_SCAN_BUS(3, sdev_printk (KERN_INFO, sdev, |
| 1388 | "scsi scan: REPORT LUNS" | 1389 | "scsi scan: REPORT LUNS" |
| @@ -1711,8 +1712,7 @@ static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost) | |||
| 1711 | return NULL; | 1712 | return NULL; |
| 1712 | 1713 | ||
| 1713 | if (shost->async_scan) { | 1714 | if (shost->async_scan) { |
| 1714 | shost_printk(KERN_INFO, shost, "%s called twice\n", __func__); | 1715 | shost_printk(KERN_DEBUG, shost, "%s called twice\n", __func__); |
| 1715 | dump_stack(); | ||
| 1716 | return NULL; | 1716 | return NULL; |
| 1717 | } | 1717 | } |
| 1718 | 1718 | ||
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index db8b21b14117..658843bb162a 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c | |||
| @@ -773,6 +773,29 @@ static struct bin_attribute dev_attr_vpd_##_page = { \ | |||
| 773 | sdev_vpd_pg_attr(pg83); | 773 | sdev_vpd_pg_attr(pg83); |
| 774 | sdev_vpd_pg_attr(pg80); | 774 | sdev_vpd_pg_attr(pg80); |
| 775 | 775 | ||
| 776 | static ssize_t show_inquiry(struct file *filep, struct kobject *kobj, | ||
| 777 | struct bin_attribute *bin_attr, | ||
| 778 | char *buf, loff_t off, size_t count) | ||
| 779 | { | ||
| 780 | struct device *dev = container_of(kobj, struct device, kobj); | ||
| 781 | struct scsi_device *sdev = to_scsi_device(dev); | ||
| 782 | |||
| 783 | if (!sdev->inquiry) | ||
| 784 | return -EINVAL; | ||
| 785 | |||
| 786 | return memory_read_from_buffer(buf, count, &off, sdev->inquiry, | ||
| 787 | sdev->inquiry_len); | ||
| 788 | } | ||
| 789 | |||
| 790 | static struct bin_attribute dev_attr_inquiry = { | ||
| 791 | .attr = { | ||
| 792 | .name = "inquiry", | ||
| 793 | .mode = S_IRUGO, | ||
| 794 | }, | ||
| 795 | .size = 0, | ||
| 796 | .read = show_inquiry, | ||
| 797 | }; | ||
| 798 | |||
| 776 | static ssize_t | 799 | static ssize_t |
| 777 | show_iostat_counterbits(struct device *dev, struct device_attribute *attr, | 800 | show_iostat_counterbits(struct device *dev, struct device_attribute *attr, |
| 778 | char *buf) | 801 | char *buf) |
| @@ -957,6 +980,7 @@ static struct attribute *scsi_sdev_attrs[] = { | |||
| 957 | static struct bin_attribute *scsi_sdev_bin_attrs[] = { | 980 | static struct bin_attribute *scsi_sdev_bin_attrs[] = { |
| 958 | &dev_attr_vpd_pg83, | 981 | &dev_attr_vpd_pg83, |
| 959 | &dev_attr_vpd_pg80, | 982 | &dev_attr_vpd_pg80, |
| 983 | &dev_attr_inquiry, | ||
| 960 | NULL | 984 | NULL |
| 961 | }; | 985 | }; |
| 962 | static struct attribute_group scsi_sdev_attr_group = { | 986 | static struct attribute_group scsi_sdev_attr_group = { |
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 3f370228bf31..f7247778c225 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
| @@ -204,6 +204,7 @@ cache_type_store(struct device *dev, struct device_attribute *attr, | |||
| 204 | buffer_data[2] &= ~0x05; | 204 | buffer_data[2] &= ~0x05; |
| 205 | buffer_data[2] |= wce << 2 | rcd; | 205 | buffer_data[2] |= wce << 2 | rcd; |
| 206 | sp = buffer_data[0] & 0x80 ? 1 : 0; | 206 | sp = buffer_data[0] & 0x80 ? 1 : 0; |
| 207 | buffer_data[0] &= ~0x80; | ||
| 207 | 208 | ||
| 208 | if (scsi_mode_select(sdp, 1, sp, 8, buffer_data, len, SD_TIMEOUT, | 209 | if (scsi_mode_select(sdp, 1, sp, 8, buffer_data, len, SD_TIMEOUT, |
| 209 | SD_MAX_RETRIES, &data, &sshdr)) { | 210 | SD_MAX_RETRIES, &data, &sshdr)) { |
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 9d7b7db75e4b..503ab8b46c0b 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c | |||
| @@ -787,8 +787,14 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp, | |||
| 787 | return k; /* probably out of space --> ENOMEM */ | 787 | return k; /* probably out of space --> ENOMEM */ |
| 788 | } | 788 | } |
| 789 | if (atomic_read(&sdp->detaching)) { | 789 | if (atomic_read(&sdp->detaching)) { |
| 790 | if (srp->bio) | 790 | if (srp->bio) { |
| 791 | if (srp->rq->cmd != srp->rq->__cmd) | ||
| 792 | kfree(srp->rq->cmd); | ||
| 793 | |||
| 791 | blk_end_request_all(srp->rq, -EIO); | 794 | blk_end_request_all(srp->rq, -EIO); |
| 795 | srp->rq = NULL; | ||
| 796 | } | ||
| 797 | |||
| 792 | sg_finish_rem_req(srp); | 798 | sg_finish_rem_req(srp); |
| 793 | return -ENODEV; | 799 | return -ENODEV; |
| 794 | } | 800 | } |
diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig index e94538362536..5f4530744e0a 100644 --- a/drivers/scsi/ufs/Kconfig +++ b/drivers/scsi/ufs/Kconfig | |||
| @@ -72,7 +72,7 @@ config SCSI_UFSHCD_PLATFORM | |||
| 72 | If unsure, say N. | 72 | If unsure, say N. |
| 73 | 73 | ||
| 74 | config SCSI_UFS_QCOM | 74 | config SCSI_UFS_QCOM |
| 75 | bool "QCOM specific hooks to UFS controller platform driver" | 75 | tristate "QCOM specific hooks to UFS controller platform driver" |
| 76 | depends on SCSI_UFSHCD_PLATFORM && ARCH_QCOM | 76 | depends on SCSI_UFSHCD_PLATFORM && ARCH_QCOM |
| 77 | select PHY_QCOM_UFS | 77 | select PHY_QCOM_UFS |
| 78 | help | 78 | help |
diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 4cdffa46d401..4f38d008bfb4 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c | |||
| @@ -19,16 +19,44 @@ | |||
| 19 | 19 | ||
| 20 | #include <linux/phy/phy-qcom-ufs.h> | 20 | #include <linux/phy/phy-qcom-ufs.h> |
| 21 | #include "ufshcd.h" | 21 | #include "ufshcd.h" |
| 22 | #include "ufshcd-pltfrm.h" | ||
| 22 | #include "unipro.h" | 23 | #include "unipro.h" |
| 23 | #include "ufs-qcom.h" | 24 | #include "ufs-qcom.h" |
| 24 | #include "ufshci.h" | 25 | #include "ufshci.h" |
| 26 | #define UFS_QCOM_DEFAULT_DBG_PRINT_EN \ | ||
| 27 | (UFS_QCOM_DBG_PRINT_REGS_EN | UFS_QCOM_DBG_PRINT_TEST_BUS_EN) | ||
| 28 | |||
| 29 | enum { | ||
| 30 | TSTBUS_UAWM, | ||
| 31 | TSTBUS_UARM, | ||
| 32 | TSTBUS_TXUC, | ||
| 33 | TSTBUS_RXUC, | ||
| 34 | TSTBUS_DFC, | ||
| 35 | TSTBUS_TRLUT, | ||
| 36 | TSTBUS_TMRLUT, | ||
| 37 | TSTBUS_OCSC, | ||
| 38 | TSTBUS_UTP_HCI, | ||
| 39 | TSTBUS_COMBINED, | ||
| 40 | TSTBUS_WRAPPER, | ||
| 41 | TSTBUS_UNIPRO, | ||
| 42 | TSTBUS_MAX, | ||
| 43 | }; | ||
| 25 | 44 | ||
| 26 | static struct ufs_qcom_host *ufs_qcom_hosts[MAX_UFS_QCOM_HOSTS]; | 45 | static struct ufs_qcom_host *ufs_qcom_hosts[MAX_UFS_QCOM_HOSTS]; |
| 27 | 46 | ||
| 28 | static void ufs_qcom_get_speed_mode(struct ufs_pa_layer_attr *p, char *result); | ||
| 29 | static int ufs_qcom_get_bus_vote(struct ufs_qcom_host *host, | ||
| 30 | const char *speed_mode); | ||
| 31 | static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote); | 47 | static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote); |
| 48 | static void ufs_qcom_get_default_testbus_cfg(struct ufs_qcom_host *host); | ||
| 49 | static int ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(struct ufs_hba *hba, | ||
| 50 | u32 clk_cycles); | ||
| 51 | |||
| 52 | static void ufs_qcom_dump_regs(struct ufs_hba *hba, int offset, int len, | ||
| 53 | char *prefix) | ||
| 54 | { | ||
| 55 | print_hex_dump(KERN_ERR, prefix, | ||
| 56 | len > 4 ? DUMP_PREFIX_OFFSET : DUMP_PREFIX_NONE, | ||
| 57 | 16, 4, (void __force *)hba->mmio_base + offset, | ||
| 58 | len * 4, false); | ||
| 59 | } | ||
| 32 | 60 | ||
| 33 | static int ufs_qcom_get_connected_tx_lanes(struct ufs_hba *hba, u32 *tx_lanes) | 61 | static int ufs_qcom_get_connected_tx_lanes(struct ufs_hba *hba, u32 *tx_lanes) |
| 34 | { | 62 | { |
| @@ -149,13 +177,14 @@ static int ufs_qcom_init_lane_clks(struct ufs_qcom_host *host) | |||
| 149 | 177 | ||
| 150 | err = ufs_qcom_host_clk_get(dev, "tx_lane1_sync_clk", | 178 | err = ufs_qcom_host_clk_get(dev, "tx_lane1_sync_clk", |
| 151 | &host->tx_l1_sync_clk); | 179 | &host->tx_l1_sync_clk); |
| 180 | |||
| 152 | out: | 181 | out: |
| 153 | return err; | 182 | return err; |
| 154 | } | 183 | } |
| 155 | 184 | ||
| 156 | static int ufs_qcom_link_startup_post_change(struct ufs_hba *hba) | 185 | static int ufs_qcom_link_startup_post_change(struct ufs_hba *hba) |
| 157 | { | 186 | { |
| 158 | struct ufs_qcom_host *host = hba->priv; | 187 | struct ufs_qcom_host *host = ufshcd_get_variant(hba); |
| 159 | struct phy *phy = host->generic_phy; | 188 | struct phy *phy = host->generic_phy; |
| 160 | u32 tx_lanes; | 189 | u32 tx_lanes; |
| 161 | int err = 0; | 190 | int err = 0; |
| @@ -181,7 +210,9 @@ static int ufs_qcom_check_hibern8(struct ufs_hba *hba) | |||
| 181 | 210 | ||
| 182 | do { | 211 | do { |
| 183 | err = ufshcd_dme_get(hba, | 212 | err = ufshcd_dme_get(hba, |
| 184 | UIC_ARG_MIB(MPHY_TX_FSM_STATE), &tx_fsm_val); | 213 | UIC_ARG_MIB_SEL(MPHY_TX_FSM_STATE, |
| 214 | UIC_ARG_MPHY_TX_GEN_SEL_INDEX(0)), | ||
| 215 | &tx_fsm_val); | ||
| 185 | if (err || tx_fsm_val == TX_FSM_HIBERN8) | 216 | if (err || tx_fsm_val == TX_FSM_HIBERN8) |
| 186 | break; | 217 | break; |
| 187 | 218 | ||
| @@ -195,7 +226,9 @@ static int ufs_qcom_check_hibern8(struct ufs_hba *hba) | |||
| 195 | */ | 226 | */ |
| 196 | if (time_after(jiffies, timeout)) | 227 | if (time_after(jiffies, timeout)) |
| 197 | err = ufshcd_dme_get(hba, | 228 | err = ufshcd_dme_get(hba, |
| 198 | UIC_ARG_MIB(MPHY_TX_FSM_STATE), &tx_fsm_val); | 229 | UIC_ARG_MIB_SEL(MPHY_TX_FSM_STATE, |
| 230 | UIC_ARG_MPHY_TX_GEN_SEL_INDEX(0)), | ||
| 231 | &tx_fsm_val); | ||
| 199 | 232 | ||
| 200 | if (err) { | 233 | if (err) { |
| 201 | dev_err(hba->dev, "%s: unable to get TX_FSM_STATE, err %d\n", | 234 | dev_err(hba->dev, "%s: unable to get TX_FSM_STATE, err %d\n", |
| @@ -209,9 +242,18 @@ static int ufs_qcom_check_hibern8(struct ufs_hba *hba) | |||
| 209 | return err; | 242 | return err; |
| 210 | } | 243 | } |
| 211 | 244 | ||
| 245 | static void ufs_qcom_select_unipro_mode(struct ufs_qcom_host *host) | ||
| 246 | { | ||
| 247 | ufshcd_rmwl(host->hba, QUNIPRO_SEL, | ||
| 248 | ufs_qcom_cap_qunipro(host) ? QUNIPRO_SEL : 0, | ||
| 249 | REG_UFS_CFG1); | ||
| 250 | /* make sure above configuration is applied before we return */ | ||
| 251 | mb(); | ||
| 252 | } | ||
| 253 | |||
| 212 | static int ufs_qcom_power_up_sequence(struct ufs_hba *hba) | 254 | static int ufs_qcom_power_up_sequence(struct ufs_hba *hba) |
| 213 | { | 255 | { |
| 214 | struct ufs_qcom_host *host = hba->priv; | 256 | struct ufs_qcom_host *host = ufshcd_get_variant(hba); |
| 215 | struct phy *phy = host->generic_phy; | 257 | struct phy *phy = host->generic_phy; |
| 216 | int ret = 0; | 258 | int ret = 0; |
| 217 | bool is_rate_B = (UFS_QCOM_LIMIT_HS_RATE == PA_HS_MODE_B) | 259 | bool is_rate_B = (UFS_QCOM_LIMIT_HS_RATE == PA_HS_MODE_B) |
| @@ -223,9 +265,11 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba *hba) | |||
| 223 | usleep_range(1000, 1100); | 265 | usleep_range(1000, 1100); |
| 224 | 266 | ||
| 225 | ret = ufs_qcom_phy_calibrate_phy(phy, is_rate_B); | 267 | ret = ufs_qcom_phy_calibrate_phy(phy, is_rate_B); |
| 268 | |||
| 226 | if (ret) { | 269 | if (ret) { |
| 227 | dev_err(hba->dev, "%s: ufs_qcom_phy_calibrate_phy() failed, ret = %d\n", | 270 | dev_err(hba->dev, |
| 228 | __func__, ret); | 271 | "%s: ufs_qcom_phy_calibrate_phy()failed, ret = %d\n", |
| 272 | __func__, ret); | ||
| 229 | goto out; | 273 | goto out; |
| 230 | } | 274 | } |
| 231 | 275 | ||
| @@ -246,9 +290,12 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba *hba) | |||
| 246 | 290 | ||
| 247 | ret = ufs_qcom_phy_is_pcs_ready(phy); | 291 | ret = ufs_qcom_phy_is_pcs_ready(phy); |
| 248 | if (ret) | 292 | if (ret) |
| 249 | dev_err(hba->dev, "%s: is_physical_coding_sublayer_ready() failed, ret = %d\n", | 293 | dev_err(hba->dev, |
| 294 | "%s: is_physical_coding_sublayer_ready() failed, ret = %d\n", | ||
| 250 | __func__, ret); | 295 | __func__, ret); |
| 251 | 296 | ||
| 297 | ufs_qcom_select_unipro_mode(host); | ||
| 298 | |||
| 252 | out: | 299 | out: |
| 253 | return ret; | 300 | return ret; |
| 254 | } | 301 | } |
| @@ -271,9 +318,10 @@ static void ufs_qcom_enable_hw_clk_gating(struct ufs_hba *hba) | |||
| 271 | mb(); | 318 | mb(); |
| 272 | } | 319 | } |
| 273 | 320 | ||
| 274 | static int ufs_qcom_hce_enable_notify(struct ufs_hba *hba, bool status) | 321 | static int ufs_qcom_hce_enable_notify(struct ufs_hba *hba, |
| 322 | enum ufs_notify_change_status status) | ||
| 275 | { | 323 | { |
| 276 | struct ufs_qcom_host *host = hba->priv; | 324 | struct ufs_qcom_host *host = ufshcd_get_variant(hba); |
| 277 | int err = 0; | 325 | int err = 0; |
| 278 | 326 | ||
| 279 | switch (status) { | 327 | switch (status) { |
| @@ -301,13 +349,13 @@ static int ufs_qcom_hce_enable_notify(struct ufs_hba *hba, bool status) | |||
| 301 | } | 349 | } |
| 302 | 350 | ||
| 303 | /** | 351 | /** |
| 304 | * Returns non-zero for success (which rate of core_clk) and 0 | 352 | * Returns zero for success and non-zero in case of a failure |
| 305 | * in case of a failure | ||
| 306 | */ | 353 | */ |
| 307 | static unsigned long | 354 | static int ufs_qcom_cfg_timers(struct ufs_hba *hba, u32 gear, |
| 308 | ufs_qcom_cfg_timers(struct ufs_hba *hba, u32 gear, u32 hs, u32 rate) | 355 | u32 hs, u32 rate, bool update_link_startup_timer) |
| 309 | { | 356 | { |
| 310 | struct ufs_qcom_host *host = hba->priv; | 357 | int ret = 0; |
| 358 | struct ufs_qcom_host *host = ufshcd_get_variant(hba); | ||
| 311 | struct ufs_clk_info *clki; | 359 | struct ufs_clk_info *clki; |
| 312 | u32 core_clk_period_in_ns; | 360 | u32 core_clk_period_in_ns; |
| 313 | u32 tx_clk_cycles_per_us = 0; | 361 | u32 tx_clk_cycles_per_us = 0; |
| @@ -324,11 +372,13 @@ ufs_qcom_cfg_timers(struct ufs_hba *hba, u32 gear, u32 hs, u32 rate) | |||
| 324 | static u32 hs_fr_table_rA[][2] = { | 372 | static u32 hs_fr_table_rA[][2] = { |
| 325 | {UFS_HS_G1, 0x1F}, | 373 | {UFS_HS_G1, 0x1F}, |
| 326 | {UFS_HS_G2, 0x3e}, | 374 | {UFS_HS_G2, 0x3e}, |
| 375 | {UFS_HS_G3, 0x7D}, | ||
| 327 | }; | 376 | }; |
| 328 | 377 | ||
| 329 | static u32 hs_fr_table_rB[][2] = { | 378 | static u32 hs_fr_table_rB[][2] = { |
| 330 | {UFS_HS_G1, 0x24}, | 379 | {UFS_HS_G1, 0x24}, |
| 331 | {UFS_HS_G2, 0x49}, | 380 | {UFS_HS_G2, 0x49}, |
| 381 | {UFS_HS_G3, 0x92}, | ||
| 332 | }; | 382 | }; |
| 333 | 383 | ||
| 334 | /* | 384 | /* |
| @@ -356,7 +406,17 @@ ufs_qcom_cfg_timers(struct ufs_hba *hba, u32 gear, u32 hs, u32 rate) | |||
| 356 | core_clk_rate = DEFAULT_CLK_RATE_HZ; | 406 | core_clk_rate = DEFAULT_CLK_RATE_HZ; |
| 357 | 407 | ||
| 358 | core_clk_cycles_per_us = core_clk_rate / USEC_PER_SEC; | 408 | core_clk_cycles_per_us = core_clk_rate / USEC_PER_SEC; |
| 359 | ufshcd_writel(hba, core_clk_cycles_per_us, REG_UFS_SYS1CLK_1US); | 409 | if (ufshcd_readl(hba, REG_UFS_SYS1CLK_1US) != core_clk_cycles_per_us) { |
| 410 | ufshcd_writel(hba, core_clk_cycles_per_us, REG_UFS_SYS1CLK_1US); | ||
| 411 | /* | ||
| 412 | * make sure above write gets applied before we return from | ||
| 413 | * this function. | ||
| 414 | */ | ||
| 415 | mb(); | ||
| 416 | } | ||
| 417 | |||
| 418 | if (ufs_qcom_cap_qunipro(host)) | ||
| 419 | goto out; | ||
| 360 | 420 | ||
| 361 | core_clk_period_in_ns = NSEC_PER_SEC / core_clk_rate; | 421 | core_clk_period_in_ns = NSEC_PER_SEC / core_clk_rate; |
| 362 | core_clk_period_in_ns <<= OFFSET_CLK_NS_REG; | 422 | core_clk_period_in_ns <<= OFFSET_CLK_NS_REG; |
| @@ -406,35 +466,59 @@ ufs_qcom_cfg_timers(struct ufs_hba *hba, u32 gear, u32 hs, u32 rate) | |||
| 406 | goto out_error; | 466 | goto out_error; |
| 407 | } | 467 | } |
| 408 | 468 | ||
| 409 | /* this register 2 fields shall be written at once */ | 469 | if (ufshcd_readl(hba, REG_UFS_TX_SYMBOL_CLK_NS_US) != |
| 410 | ufshcd_writel(hba, core_clk_period_in_ns | tx_clk_cycles_per_us, | 470 | (core_clk_period_in_ns | tx_clk_cycles_per_us)) { |
| 411 | REG_UFS_TX_SYMBOL_CLK_NS_US); | 471 | /* this register 2 fields shall be written at once */ |
| 472 | ufshcd_writel(hba, core_clk_period_in_ns | tx_clk_cycles_per_us, | ||
| 473 | REG_UFS_TX_SYMBOL_CLK_NS_US); | ||
| 474 | /* | ||
| 475 | * make sure above write gets applied before we return from | ||
| 476 | * this function. | ||
| 477 | */ | ||
| 478 | mb(); | ||
| 479 | } | ||
| 480 | |||
| 481 | if (update_link_startup_timer) { | ||
| 482 | ufshcd_writel(hba, ((core_clk_rate / MSEC_PER_SEC) * 100), | ||
| 483 | REG_UFS_PA_LINK_STARTUP_TIMER); | ||
| 484 | /* | ||
| 485 | * make sure that this configuration is applied before | ||
| 486 | * we return | ||
| 487 | */ | ||
| 488 | mb(); | ||
| 489 | } | ||
| 412 | goto out; | 490 | goto out; |
| 413 | 491 | ||
| 414 | out_error: | 492 | out_error: |
| 415 | core_clk_rate = 0; | 493 | ret = -EINVAL; |
| 416 | out: | 494 | out: |
| 417 | return core_clk_rate; | 495 | return ret; |
| 418 | } | 496 | } |
| 419 | 497 | ||
| 420 | static int ufs_qcom_link_startup_notify(struct ufs_hba *hba, bool status) | 498 | static int ufs_qcom_link_startup_notify(struct ufs_hba *hba, |
| 499 | enum ufs_notify_change_status status) | ||
| 421 | { | 500 | { |
| 422 | unsigned long core_clk_rate = 0; | 501 | int err = 0; |
| 423 | u32 core_clk_cycles_per_100ms; | 502 | struct ufs_qcom_host *host = ufshcd_get_variant(hba); |
| 424 | 503 | ||
| 425 | switch (status) { | 504 | switch (status) { |
| 426 | case PRE_CHANGE: | 505 | case PRE_CHANGE: |
| 427 | core_clk_rate = ufs_qcom_cfg_timers(hba, UFS_PWM_G1, | 506 | if (ufs_qcom_cfg_timers(hba, UFS_PWM_G1, SLOWAUTO_MODE, |
| 428 | SLOWAUTO_MODE, 0); | 507 | 0, true)) { |
| 429 | if (!core_clk_rate) { | ||
| 430 | dev_err(hba->dev, "%s: ufs_qcom_cfg_timers() failed\n", | 508 | dev_err(hba->dev, "%s: ufs_qcom_cfg_timers() failed\n", |
| 431 | __func__); | 509 | __func__); |
| 432 | return -EINVAL; | 510 | err = -EINVAL; |
| 511 | goto out; | ||
| 433 | } | 512 | } |
| 434 | core_clk_cycles_per_100ms = | 513 | |
| 435 | (core_clk_rate / MSEC_PER_SEC) * 100; | 514 | if (ufs_qcom_cap_qunipro(host)) |
| 436 | ufshcd_writel(hba, core_clk_cycles_per_100ms, | 515 | /* |
| 437 | REG_UFS_PA_LINK_STARTUP_TIMER); | 516 | * set unipro core clock cycles to 150 & clear clock |
| 517 | * divider | ||
| 518 | */ | ||
| 519 | err = ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(hba, | ||
| 520 | 150); | ||
| 521 | |||
| 438 | break; | 522 | break; |
| 439 | case POST_CHANGE: | 523 | case POST_CHANGE: |
| 440 | ufs_qcom_link_startup_post_change(hba); | 524 | ufs_qcom_link_startup_post_change(hba); |
| @@ -443,12 +527,13 @@ static int ufs_qcom_link_startup_notify(struct ufs_hba *hba, bool status) | |||
| 443 | break; | 527 | break; |
| 444 | } | 528 | } |
| 445 | 529 | ||
| 446 | return 0; | 530 | out: |
| 531 | return err; | ||
| 447 | } | 532 | } |
| 448 | 533 | ||
| 449 | static int ufs_qcom_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) | 534 | static int ufs_qcom_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) |
| 450 | { | 535 | { |
| 451 | struct ufs_qcom_host *host = hba->priv; | 536 | struct ufs_qcom_host *host = ufshcd_get_variant(hba); |
| 452 | struct phy *phy = host->generic_phy; | 537 | struct phy *phy = host->generic_phy; |
| 453 | int ret = 0; | 538 | int ret = 0; |
| 454 | 539 | ||
| @@ -470,8 +555,10 @@ static int ufs_qcom_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) | |||
| 470 | * If UniPro link is not active, PHY ref_clk, main PHY analog power | 555 | * If UniPro link is not active, PHY ref_clk, main PHY analog power |
| 471 | * rail and low noise analog power rail for PLL can be switched off. | 556 | * rail and low noise analog power rail for PLL can be switched off. |
| 472 | */ | 557 | */ |
| 473 | if (!ufs_qcom_is_link_active(hba)) | 558 | if (!ufs_qcom_is_link_active(hba)) { |
| 559 | ufs_qcom_disable_lane_clks(host); | ||
| 474 | phy_power_off(phy); | 560 | phy_power_off(phy); |
| 561 | } | ||
| 475 | 562 | ||
| 476 | out: | 563 | out: |
| 477 | return ret; | 564 | return ret; |
| @@ -479,7 +566,7 @@ out: | |||
| 479 | 566 | ||
| 480 | static int ufs_qcom_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) | 567 | static int ufs_qcom_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) |
| 481 | { | 568 | { |
| 482 | struct ufs_qcom_host *host = hba->priv; | 569 | struct ufs_qcom_host *host = ufshcd_get_variant(hba); |
| 483 | struct phy *phy = host->generic_phy; | 570 | struct phy *phy = host->generic_phy; |
| 484 | int err; | 571 | int err; |
| 485 | 572 | ||
| @@ -490,6 +577,10 @@ static int ufs_qcom_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) | |||
| 490 | goto out; | 577 | goto out; |
| 491 | } | 578 | } |
| 492 | 579 | ||
| 580 | err = ufs_qcom_enable_lane_clks(host); | ||
| 581 | if (err) | ||
| 582 | goto out; | ||
| 583 | |||
| 493 | hba->is_sys_suspended = false; | 584 | hba->is_sys_suspended = false; |
| 494 | 585 | ||
| 495 | out: | 586 | out: |
| @@ -594,6 +685,81 @@ static int ufs_qcom_get_pwr_dev_param(struct ufs_qcom_dev_params *qcom_param, | |||
| 594 | return 0; | 685 | return 0; |
| 595 | } | 686 | } |
| 596 | 687 | ||
| 688 | #ifdef CONFIG_MSM_BUS_SCALING | ||
| 689 | static int ufs_qcom_get_bus_vote(struct ufs_qcom_host *host, | ||
| 690 | const char *speed_mode) | ||
| 691 | { | ||
| 692 | struct device *dev = host->hba->dev; | ||
| 693 | struct device_node *np = dev->of_node; | ||
| 694 | int err; | ||
| 695 | const char *key = "qcom,bus-vector-names"; | ||
| 696 | |||
| 697 | if (!speed_mode) { | ||
| 698 | err = -EINVAL; | ||
| 699 | goto out; | ||
| 700 | } | ||
| 701 | |||
| 702 | if (host->bus_vote.is_max_bw_needed && !!strcmp(speed_mode, "MIN")) | ||
| 703 | err = of_property_match_string(np, key, "MAX"); | ||
| 704 | else | ||
| 705 | err = of_property_match_string(np, key, speed_mode); | ||
| 706 | |||
| 707 | out: | ||
| 708 | if (err < 0) | ||
| 709 | dev_err(dev, "%s: Invalid %s mode %d\n", | ||
| 710 | __func__, speed_mode, err); | ||
| 711 | return err; | ||
| 712 | } | ||
| 713 | |||
| 714 | static void ufs_qcom_get_speed_mode(struct ufs_pa_layer_attr *p, char *result) | ||
| 715 | { | ||
| 716 | int gear = max_t(u32, p->gear_rx, p->gear_tx); | ||
| 717 | int lanes = max_t(u32, p->lane_rx, p->lane_tx); | ||
| 718 | int pwr; | ||
| 719 | |||
| 720 | /* default to PWM Gear 1, Lane 1 if power mode is not initialized */ | ||
| 721 | if (!gear) | ||
| 722 | gear = 1; | ||
| 723 | |||
| 724 | if (!lanes) | ||
| 725 | lanes = 1; | ||
| 726 | |||
| 727 | if (!p->pwr_rx && !p->pwr_tx) { | ||
| 728 | pwr = SLOWAUTO_MODE; | ||
| 729 | snprintf(result, BUS_VECTOR_NAME_LEN, "MIN"); | ||
| 730 | } else if (p->pwr_rx == FAST_MODE || p->pwr_rx == FASTAUTO_MODE || | ||
| 731 | p->pwr_tx == FAST_MODE || p->pwr_tx == FASTAUTO_MODE) { | ||
| 732 | pwr = FAST_MODE; | ||
| 733 | snprintf(result, BUS_VECTOR_NAME_LEN, "%s_R%s_G%d_L%d", "HS", | ||
| 734 | p->hs_rate == PA_HS_MODE_B ? "B" : "A", gear, lanes); | ||
| 735 | } else { | ||
| 736 | pwr = SLOW_MODE; | ||
| 737 | snprintf(result, BUS_VECTOR_NAME_LEN, "%s_G%d_L%d", | ||
| 738 | "PWM", gear, lanes); | ||
| 739 | } | ||
| 740 | } | ||
| 741 | |||
| 742 | static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote) | ||
| 743 | { | ||
| 744 | int err = 0; | ||
| 745 | |||
| 746 | if (vote != host->bus_vote.curr_vote) { | ||
| 747 | err = msm_bus_scale_client_update_request( | ||
| 748 | host->bus_vote.client_handle, vote); | ||
| 749 | if (err) { | ||
| 750 | dev_err(host->hba->dev, | ||
| 751 | "%s: msm_bus_scale_client_update_request() failed: bus_client_handle=0x%x, vote=%d, err=%d\n", | ||
| 752 | __func__, host->bus_vote.client_handle, | ||
| 753 | vote, err); | ||
| 754 | goto out; | ||
| 755 | } | ||
| 756 | |||
| 757 | host->bus_vote.curr_vote = vote; | ||
| 758 | } | ||
| 759 | out: | ||
| 760 | return err; | ||
| 761 | } | ||
| 762 | |||
| 597 | static int ufs_qcom_update_bus_bw_vote(struct ufs_qcom_host *host) | 763 | static int ufs_qcom_update_bus_bw_vote(struct ufs_qcom_host *host) |
| 598 | { | 764 | { |
| 599 | int vote; | 765 | int vote; |
| @@ -615,13 +781,137 @@ static int ufs_qcom_update_bus_bw_vote(struct ufs_qcom_host *host) | |||
| 615 | return err; | 781 | return err; |
| 616 | } | 782 | } |
| 617 | 783 | ||
| 784 | static ssize_t | ||
| 785 | show_ufs_to_mem_max_bus_bw(struct device *dev, struct device_attribute *attr, | ||
| 786 | char *buf) | ||
| 787 | { | ||
| 788 | struct ufs_hba *hba = dev_get_drvdata(dev); | ||
| 789 | struct ufs_qcom_host *host = ufshcd_get_variant(hba); | ||
| 790 | |||
| 791 | return snprintf(buf, PAGE_SIZE, "%u\n", | ||
| 792 | host->bus_vote.is_max_bw_needed); | ||
| 793 | } | ||
| 794 | |||
| 795 | static ssize_t | ||
| 796 | store_ufs_to_mem_max_bus_bw(struct device *dev, struct device_attribute *attr, | ||
| 797 | const char *buf, size_t count) | ||
| 798 | { | ||
| 799 | struct ufs_hba *hba = dev_get_drvdata(dev); | ||
| 800 | struct ufs_qcom_host *host = ufshcd_get_variant(hba); | ||
| 801 | uint32_t value; | ||
| 802 | |||
| 803 | if (!kstrtou32(buf, 0, &value)) { | ||
| 804 | host->bus_vote.is_max_bw_needed = !!value; | ||
| 805 | ufs_qcom_update_bus_bw_vote(host); | ||
| 806 | } | ||
| 807 | |||
| 808 | return count; | ||
| 809 | } | ||
| 810 | |||
| 811 | static int ufs_qcom_bus_register(struct ufs_qcom_host *host) | ||
| 812 | { | ||
| 813 | int err; | ||
| 814 | struct msm_bus_scale_pdata *bus_pdata; | ||
| 815 | struct device *dev = host->hba->dev; | ||
| 816 | struct platform_device *pdev = to_platform_device(dev); | ||
| 817 | struct device_node *np = dev->of_node; | ||
| 818 | |||
| 819 | bus_pdata = msm_bus_cl_get_pdata(pdev); | ||
| 820 | if (!bus_pdata) { | ||
| 821 | dev_err(dev, "%s: failed to get bus vectors\n", __func__); | ||
| 822 | err = -ENODATA; | ||
| 823 | goto out; | ||
| 824 | } | ||
| 825 | |||
| 826 | err = of_property_count_strings(np, "qcom,bus-vector-names"); | ||
| 827 | if (err < 0 || err != bus_pdata->num_usecases) { | ||
| 828 | dev_err(dev, "%s: qcom,bus-vector-names not specified correctly %d\n", | ||
| 829 | __func__, err); | ||
| 830 | goto out; | ||
| 831 | } | ||
| 832 | |||
| 833 | host->bus_vote.client_handle = msm_bus_scale_register_client(bus_pdata); | ||
| 834 | if (!host->bus_vote.client_handle) { | ||
| 835 | dev_err(dev, "%s: msm_bus_scale_register_client failed\n", | ||
| 836 | __func__); | ||
| 837 | err = -EFAULT; | ||
| 838 | goto out; | ||
| 839 | } | ||
| 840 | |||
| 841 | /* cache the vote index for minimum and maximum bandwidth */ | ||
| 842 | host->bus_vote.min_bw_vote = ufs_qcom_get_bus_vote(host, "MIN"); | ||
| 843 | host->bus_vote.max_bw_vote = ufs_qcom_get_bus_vote(host, "MAX"); | ||
| 844 | |||
| 845 | host->bus_vote.max_bus_bw.show = show_ufs_to_mem_max_bus_bw; | ||
| 846 | host->bus_vote.max_bus_bw.store = store_ufs_to_mem_max_bus_bw; | ||
| 847 | sysfs_attr_init(&host->bus_vote.max_bus_bw.attr); | ||
| 848 | host->bus_vote.max_bus_bw.attr.name = "max_bus_bw"; | ||
| 849 | host->bus_vote.max_bus_bw.attr.mode = S_IRUGO | S_IWUSR; | ||
| 850 | err = device_create_file(dev, &host->bus_vote.max_bus_bw); | ||
| 851 | out: | ||
| 852 | return err; | ||
| 853 | } | ||
| 854 | #else /* CONFIG_MSM_BUS_SCALING */ | ||
| 855 | static int ufs_qcom_update_bus_bw_vote(struct ufs_qcom_host *host) | ||
| 856 | { | ||
| 857 | return 0; | ||
| 858 | } | ||
| 859 | |||
| 860 | static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote) | ||
| 861 | { | ||
| 862 | return 0; | ||
| 863 | } | ||
| 864 | |||
| 865 | static int ufs_qcom_bus_register(struct ufs_qcom_host *host) | ||
| 866 | { | ||
| 867 | return 0; | ||
| 868 | } | ||
| 869 | #endif /* CONFIG_MSM_BUS_SCALING */ | ||
| 870 | |||
| 871 | static void ufs_qcom_dev_ref_clk_ctrl(struct ufs_qcom_host *host, bool enable) | ||
| 872 | { | ||
| 873 | if (host->dev_ref_clk_ctrl_mmio && | ||
| 874 | (enable ^ host->is_dev_ref_clk_enabled)) { | ||
| 875 | u32 temp = readl_relaxed(host->dev_ref_clk_ctrl_mmio); | ||
| 876 | |||
| 877 | if (enable) | ||
| 878 | temp |= host->dev_ref_clk_en_mask; | ||
| 879 | else | ||
| 880 | temp &= ~host->dev_ref_clk_en_mask; | ||
| 881 | |||
| 882 | /* | ||
| 883 | * If we are here to disable this clock it might be immediately | ||
| 884 | * after entering into hibern8 in which case we need to make | ||
| 885 | * sure that device ref_clk is active at least 1us after the | ||
| 886 | * hibern8 enter. | ||
| 887 | */ | ||
| 888 | if (!enable) | ||
| 889 | udelay(1); | ||
| 890 | |||
| 891 | writel_relaxed(temp, host->dev_ref_clk_ctrl_mmio); | ||
| 892 | |||
| 893 | /* ensure that ref_clk is enabled/disabled before we return */ | ||
| 894 | wmb(); | ||
| 895 | |||
| 896 | /* | ||
| 897 | * If we call hibern8 exit after this, we need to make sure that | ||
| 898 | * device ref_clk is stable for at least 1us before the hibern8 | ||
| 899 | * exit command. | ||
| 900 | */ | ||
| 901 | if (enable) | ||
| 902 | udelay(1); | ||
| 903 | |||
| 904 | host->is_dev_ref_clk_enabled = enable; | ||
| 905 | } | ||
| 906 | } | ||
| 907 | |||
| 618 | static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba, | 908 | static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba, |
| 619 | bool status, | 909 | enum ufs_notify_change_status status, |
| 620 | struct ufs_pa_layer_attr *dev_max_params, | 910 | struct ufs_pa_layer_attr *dev_max_params, |
| 621 | struct ufs_pa_layer_attr *dev_req_params) | 911 | struct ufs_pa_layer_attr *dev_req_params) |
| 622 | { | 912 | { |
| 623 | u32 val; | 913 | u32 val; |
| 624 | struct ufs_qcom_host *host = hba->priv; | 914 | struct ufs_qcom_host *host = ufshcd_get_variant(hba); |
| 625 | struct phy *phy = host->generic_phy; | 915 | struct phy *phy = host->generic_phy; |
| 626 | struct ufs_qcom_dev_params ufs_qcom_cap; | 916 | struct ufs_qcom_dev_params ufs_qcom_cap; |
| 627 | int ret = 0; | 917 | int ret = 0; |
| @@ -649,6 +939,20 @@ static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba, | |||
| 649 | ufs_qcom_cap.desired_working_mode = | 939 | ufs_qcom_cap.desired_working_mode = |
| 650 | UFS_QCOM_LIMIT_DESIRED_MODE; | 940 | UFS_QCOM_LIMIT_DESIRED_MODE; |
| 651 | 941 | ||
| 942 | if (host->hw_ver.major == 0x1) { | ||
| 943 | /* | ||
| 944 | * HS-G3 operations may not reliably work on legacy QCOM | ||
| 945 | * UFS host controller hardware even though capability | ||
| 946 | * exchange during link startup phase may end up | ||
| 947 | * negotiating maximum supported gear as G3. | ||
| 948 | * Hence downgrade the maximum supported gear to HS-G2. | ||
| 949 | */ | ||
| 950 | if (ufs_qcom_cap.hs_tx_gear > UFS_HS_G2) | ||
| 951 | ufs_qcom_cap.hs_tx_gear = UFS_HS_G2; | ||
| 952 | if (ufs_qcom_cap.hs_rx_gear > UFS_HS_G2) | ||
| 953 | ufs_qcom_cap.hs_rx_gear = UFS_HS_G2; | ||
| 954 | } | ||
| 955 | |||
| 652 | ret = ufs_qcom_get_pwr_dev_param(&ufs_qcom_cap, | 956 | ret = ufs_qcom_get_pwr_dev_param(&ufs_qcom_cap, |
| 653 | dev_max_params, | 957 | dev_max_params, |
| 654 | dev_req_params); | 958 | dev_req_params); |
| @@ -660,9 +964,9 @@ static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba, | |||
| 660 | 964 | ||
| 661 | break; | 965 | break; |
| 662 | case POST_CHANGE: | 966 | case POST_CHANGE: |
| 663 | if (!ufs_qcom_cfg_timers(hba, dev_req_params->gear_rx, | 967 | if (ufs_qcom_cfg_timers(hba, dev_req_params->gear_rx, |
| 664 | dev_req_params->pwr_rx, | 968 | dev_req_params->pwr_rx, |
| 665 | dev_req_params->hs_rate)) { | 969 | dev_req_params->hs_rate, false)) { |
| 666 | dev_err(hba->dev, "%s: ufs_qcom_cfg_timers() failed\n", | 970 | dev_err(hba->dev, "%s: ufs_qcom_cfg_timers() failed\n", |
| 667 | __func__); | 971 | __func__); |
| 668 | /* | 972 | /* |
| @@ -696,7 +1000,7 @@ out: | |||
| 696 | 1000 | ||
| 697 | static u32 ufs_qcom_get_ufs_hci_version(struct ufs_hba *hba) | 1001 | static u32 ufs_qcom_get_ufs_hci_version(struct ufs_hba *hba) |
| 698 | { | 1002 | { |
| 699 | struct ufs_qcom_host *host = hba->priv; | 1003 | struct ufs_qcom_host *host = ufshcd_get_variant(hba); |
| 700 | 1004 | ||
| 701 | if (host->hw_ver.major == 0x1) | 1005 | if (host->hw_ver.major == 0x1) |
| 702 | return UFSHCI_VERSION_11; | 1006 | return UFSHCI_VERSION_11; |
| @@ -715,7 +1019,7 @@ static u32 ufs_qcom_get_ufs_hci_version(struct ufs_hba *hba) | |||
| 715 | */ | 1019 | */ |
| 716 | static void ufs_qcom_advertise_quirks(struct ufs_hba *hba) | 1020 | static void ufs_qcom_advertise_quirks(struct ufs_hba *hba) |
| 717 | { | 1021 | { |
| 718 | struct ufs_qcom_host *host = hba->priv; | 1022 | struct ufs_qcom_host *host = ufshcd_get_variant(hba); |
| 719 | 1023 | ||
| 720 | if (host->hw_ver.major == 0x01) { | 1024 | if (host->hw_ver.major == 0x01) { |
| 721 | hba->quirks |= UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS | 1025 | hba->quirks |= UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS |
| @@ -724,10 +1028,11 @@ static void ufs_qcom_advertise_quirks(struct ufs_hba *hba) | |||
| 724 | 1028 | ||
| 725 | if (host->hw_ver.minor == 0x0001 && host->hw_ver.step == 0x0001) | 1029 | if (host->hw_ver.minor == 0x0001 && host->hw_ver.step == 0x0001) |
| 726 | hba->quirks |= UFSHCD_QUIRK_BROKEN_INTR_AGGR; | 1030 | hba->quirks |= UFSHCD_QUIRK_BROKEN_INTR_AGGR; |
| 1031 | |||
| 1032 | hba->quirks |= UFSHCD_QUIRK_BROKEN_LCC; | ||
| 727 | } | 1033 | } |
| 728 | 1034 | ||
| 729 | if (host->hw_ver.major >= 0x2) { | 1035 | if (host->hw_ver.major >= 0x2) { |
| 730 | hba->quirks |= UFSHCD_QUIRK_BROKEN_LCC; | ||
| 731 | hba->quirks |= UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION; | 1036 | hba->quirks |= UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION; |
| 732 | 1037 | ||
| 733 | if (!ufs_qcom_cap_qunipro(host)) | 1038 | if (!ufs_qcom_cap_qunipro(host)) |
| @@ -740,79 +1045,29 @@ static void ufs_qcom_advertise_quirks(struct ufs_hba *hba) | |||
| 740 | 1045 | ||
| 741 | static void ufs_qcom_set_caps(struct ufs_hba *hba) | 1046 | static void ufs_qcom_set_caps(struct ufs_hba *hba) |
| 742 | { | 1047 | { |
| 743 | struct ufs_qcom_host *host = hba->priv; | 1048 | struct ufs_qcom_host *host = ufshcd_get_variant(hba); |
| 744 | 1049 | ||
| 745 | if (host->hw_ver.major >= 0x2) | 1050 | hba->caps |= UFSHCD_CAP_CLK_GATING | UFSHCD_CAP_HIBERN8_WITH_CLK_GATING; |
| 746 | host->caps = UFS_QCOM_CAP_QUNIPRO; | 1051 | hba->caps |= UFSHCD_CAP_CLK_SCALING; |
| 747 | } | 1052 | hba->caps |= UFSHCD_CAP_AUTO_BKOPS_SUSPEND; |
| 748 | |||
| 749 | static int ufs_qcom_get_bus_vote(struct ufs_qcom_host *host, | ||
| 750 | const char *speed_mode) | ||
| 751 | { | ||
| 752 | struct device *dev = host->hba->dev; | ||
| 753 | struct device_node *np = dev->of_node; | ||
| 754 | int err; | ||
| 755 | const char *key = "qcom,bus-vector-names"; | ||
| 756 | |||
| 757 | if (!speed_mode) { | ||
| 758 | err = -EINVAL; | ||
| 759 | goto out; | ||
| 760 | } | ||
| 761 | |||
| 762 | if (host->bus_vote.is_max_bw_needed && !!strcmp(speed_mode, "MIN")) | ||
| 763 | err = of_property_match_string(np, key, "MAX"); | ||
| 764 | else | ||
| 765 | err = of_property_match_string(np, key, speed_mode); | ||
| 766 | |||
| 767 | out: | ||
| 768 | if (err < 0) | ||
| 769 | dev_err(dev, "%s: Invalid %s mode %d\n", | ||
| 770 | __func__, speed_mode, err); | ||
| 771 | return err; | ||
| 772 | } | ||
| 773 | |||
| 774 | static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote) | ||
| 775 | { | ||
| 776 | int err = 0; | ||
| 777 | |||
| 778 | if (vote != host->bus_vote.curr_vote) | ||
| 779 | host->bus_vote.curr_vote = vote; | ||
| 780 | |||
| 781 | return err; | ||
| 782 | } | ||
| 783 | |||
| 784 | static void ufs_qcom_get_speed_mode(struct ufs_pa_layer_attr *p, char *result) | ||
| 785 | { | ||
| 786 | int gear = max_t(u32, p->gear_rx, p->gear_tx); | ||
| 787 | int lanes = max_t(u32, p->lane_rx, p->lane_tx); | ||
| 788 | int pwr; | ||
| 789 | |||
| 790 | /* default to PWM Gear 1, Lane 1 if power mode is not initialized */ | ||
| 791 | if (!gear) | ||
| 792 | gear = 1; | ||
| 793 | |||
| 794 | if (!lanes) | ||
| 795 | lanes = 1; | ||
| 796 | 1053 | ||
| 797 | if (!p->pwr_rx && !p->pwr_tx) { | 1054 | if (host->hw_ver.major >= 0x2) { |
| 798 | pwr = SLOWAUTO_MODE; | 1055 | host->caps = UFS_QCOM_CAP_QUNIPRO | |
| 799 | snprintf(result, BUS_VECTOR_NAME_LEN, "MIN"); | 1056 | UFS_QCOM_CAP_RETAIN_SEC_CFG_AFTER_PWR_COLLAPSE; |
| 800 | } else if (p->pwr_rx == FAST_MODE || p->pwr_rx == FASTAUTO_MODE || | ||
| 801 | p->pwr_tx == FAST_MODE || p->pwr_tx == FASTAUTO_MODE) { | ||
| 802 | pwr = FAST_MODE; | ||
| 803 | snprintf(result, BUS_VECTOR_NAME_LEN, "%s_R%s_G%d_L%d", "HS", | ||
| 804 | p->hs_rate == PA_HS_MODE_B ? "B" : "A", gear, lanes); | ||
| 805 | } else { | ||
| 806 | pwr = SLOW_MODE; | ||
| 807 | snprintf(result, BUS_VECTOR_NAME_LEN, "%s_G%d_L%d", | ||
| 808 | "PWM", gear, lanes); | ||
| 809 | } | 1057 | } |
| 810 | } | 1058 | } |
| 811 | 1059 | ||
| 1060 | /** | ||
| 1061 | * ufs_qcom_setup_clocks - enables/disable clocks | ||
| 1062 | * @hba: host controller instance | ||
| 1063 | * @on: If true, enable clocks else disable them. | ||
| 1064 | * | ||
| 1065 | * Returns 0 on success, non-zero on failure. | ||
| 1066 | */ | ||
| 812 | static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on) | 1067 | static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on) |
| 813 | { | 1068 | { |
| 814 | struct ufs_qcom_host *host = hba->priv; | 1069 | struct ufs_qcom_host *host = ufshcd_get_variant(hba); |
| 815 | int err = 0; | 1070 | int err; |
| 816 | int vote = 0; | 1071 | int vote = 0; |
| 817 | 1072 | ||
| 818 | /* | 1073 | /* |
| @@ -835,20 +1090,18 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on) | |||
| 835 | ufs_qcom_phy_disable_iface_clk(host->generic_phy); | 1090 | ufs_qcom_phy_disable_iface_clk(host->generic_phy); |
| 836 | goto out; | 1091 | goto out; |
| 837 | } | 1092 | } |
| 838 | /* enable the device ref clock */ | ||
| 839 | ufs_qcom_phy_enable_dev_ref_clk(host->generic_phy); | ||
| 840 | vote = host->bus_vote.saved_vote; | 1093 | vote = host->bus_vote.saved_vote; |
| 841 | if (vote == host->bus_vote.min_bw_vote) | 1094 | if (vote == host->bus_vote.min_bw_vote) |
| 842 | ufs_qcom_update_bus_bw_vote(host); | 1095 | ufs_qcom_update_bus_bw_vote(host); |
| 1096 | |||
| 843 | } else { | 1097 | } else { |
| 1098 | |||
| 844 | /* M-PHY RMMI interface clocks can be turned off */ | 1099 | /* M-PHY RMMI interface clocks can be turned off */ |
| 845 | ufs_qcom_phy_disable_iface_clk(host->generic_phy); | 1100 | ufs_qcom_phy_disable_iface_clk(host->generic_phy); |
| 846 | if (!ufs_qcom_is_link_active(hba)) { | 1101 | if (!ufs_qcom_is_link_active(hba)) |
| 847 | /* turn off UFS local PHY ref_clk */ | ||
| 848 | ufs_qcom_phy_disable_ref_clk(host->generic_phy); | ||
| 849 | /* disable device ref_clk */ | 1102 | /* disable device ref_clk */ |
| 850 | ufs_qcom_phy_disable_dev_ref_clk(host->generic_phy); | 1103 | ufs_qcom_dev_ref_clk_ctrl(host, false); |
| 851 | } | 1104 | |
| 852 | vote = host->bus_vote.min_bw_vote; | 1105 | vote = host->bus_vote.min_bw_vote; |
| 853 | } | 1106 | } |
| 854 | 1107 | ||
| @@ -861,68 +1114,17 @@ out: | |||
| 861 | return err; | 1114 | return err; |
| 862 | } | 1115 | } |
| 863 | 1116 | ||
| 864 | static ssize_t | ||
| 865 | show_ufs_to_mem_max_bus_bw(struct device *dev, struct device_attribute *attr, | ||
| 866 | char *buf) | ||
| 867 | { | ||
| 868 | struct ufs_hba *hba = dev_get_drvdata(dev); | ||
| 869 | struct ufs_qcom_host *host = hba->priv; | ||
| 870 | |||
| 871 | return snprintf(buf, PAGE_SIZE, "%u\n", | ||
| 872 | host->bus_vote.is_max_bw_needed); | ||
| 873 | } | ||
| 874 | |||
| 875 | static ssize_t | ||
| 876 | store_ufs_to_mem_max_bus_bw(struct device *dev, struct device_attribute *attr, | ||
| 877 | const char *buf, size_t count) | ||
| 878 | { | ||
| 879 | struct ufs_hba *hba = dev_get_drvdata(dev); | ||
| 880 | struct ufs_qcom_host *host = hba->priv; | ||
| 881 | uint32_t value; | ||
| 882 | |||
| 883 | if (!kstrtou32(buf, 0, &value)) { | ||
| 884 | host->bus_vote.is_max_bw_needed = !!value; | ||
| 885 | ufs_qcom_update_bus_bw_vote(host); | ||
| 886 | } | ||
| 887 | |||
| 888 | return count; | ||
| 889 | } | ||
| 890 | |||
| 891 | static int ufs_qcom_bus_register(struct ufs_qcom_host *host) | ||
| 892 | { | ||
| 893 | int err; | ||
| 894 | struct device *dev = host->hba->dev; | ||
| 895 | struct device_node *np = dev->of_node; | ||
| 896 | |||
| 897 | err = of_property_count_strings(np, "qcom,bus-vector-names"); | ||
| 898 | if (err < 0 ) { | ||
| 899 | dev_err(dev, "%s: qcom,bus-vector-names not specified correctly %d\n", | ||
| 900 | __func__, err); | ||
| 901 | goto out; | ||
| 902 | } | ||
| 903 | |||
| 904 | /* cache the vote index for minimum and maximum bandwidth */ | ||
| 905 | host->bus_vote.min_bw_vote = ufs_qcom_get_bus_vote(host, "MIN"); | ||
| 906 | host->bus_vote.max_bw_vote = ufs_qcom_get_bus_vote(host, "MAX"); | ||
| 907 | |||
| 908 | host->bus_vote.max_bus_bw.show = show_ufs_to_mem_max_bus_bw; | ||
| 909 | host->bus_vote.max_bus_bw.store = store_ufs_to_mem_max_bus_bw; | ||
| 910 | sysfs_attr_init(&host->bus_vote.max_bus_bw.attr); | ||
| 911 | host->bus_vote.max_bus_bw.attr.name = "max_bus_bw"; | ||
| 912 | host->bus_vote.max_bus_bw.attr.mode = S_IRUGO | S_IWUSR; | ||
| 913 | err = device_create_file(dev, &host->bus_vote.max_bus_bw); | ||
| 914 | out: | ||
| 915 | return err; | ||
| 916 | } | ||
| 917 | |||
| 918 | #define ANDROID_BOOT_DEV_MAX 30 | 1117 | #define ANDROID_BOOT_DEV_MAX 30 |
| 919 | static char android_boot_dev[ANDROID_BOOT_DEV_MAX]; | 1118 | static char android_boot_dev[ANDROID_BOOT_DEV_MAX]; |
| 920 | static int get_android_boot_dev(char *str) | 1119 | |
| 1120 | #ifndef MODULE | ||
| 1121 | static int __init get_android_boot_dev(char *str) | ||
| 921 | { | 1122 | { |
| 922 | strlcpy(android_boot_dev, str, ANDROID_BOOT_DEV_MAX); | 1123 | strlcpy(android_boot_dev, str, ANDROID_BOOT_DEV_MAX); |
| 923 | return 1; | 1124 | return 1; |
| 924 | } | 1125 | } |
| 925 | __setup("androidboot.bootdevice=", get_android_boot_dev); | 1126 | __setup("androidboot.bootdevice=", get_android_boot_dev); |
| 1127 | #endif | ||
| 926 | 1128 | ||
| 927 | /** | 1129 | /** |
| 928 | * ufs_qcom_init - bind phy with controller | 1130 | * ufs_qcom_init - bind phy with controller |
| @@ -938,7 +1140,9 @@ static int ufs_qcom_init(struct ufs_hba *hba) | |||
| 938 | { | 1140 | { |
| 939 | int err; | 1141 | int err; |
| 940 | struct device *dev = hba->dev; | 1142 | struct device *dev = hba->dev; |
| 1143 | struct platform_device *pdev = to_platform_device(dev); | ||
| 941 | struct ufs_qcom_host *host; | 1144 | struct ufs_qcom_host *host; |
| 1145 | struct resource *res; | ||
| 942 | 1146 | ||
| 943 | if (strlen(android_boot_dev) && strcmp(android_boot_dev, dev_name(dev))) | 1147 | if (strlen(android_boot_dev) && strcmp(android_boot_dev, dev_name(dev))) |
| 944 | return -ENODEV; | 1148 | return -ENODEV; |
| @@ -950,9 +1154,15 @@ static int ufs_qcom_init(struct ufs_hba *hba) | |||
| 950 | goto out; | 1154 | goto out; |
| 951 | } | 1155 | } |
| 952 | 1156 | ||
| 1157 | /* Make a two way bind between the qcom host and the hba */ | ||
| 953 | host->hba = hba; | 1158 | host->hba = hba; |
| 954 | hba->priv = (void *)host; | 1159 | ufshcd_set_variant(hba, host); |
| 955 | 1160 | ||
| 1161 | /* | ||
| 1162 | * voting/devoting device ref_clk source is time consuming hence | ||
| 1163 | * skip devoting it during aggressive clock gating. This clock | ||
| 1164 | * will still be gated off during runtime suspend. | ||
| 1165 | */ | ||
| 956 | host->generic_phy = devm_phy_get(dev, "ufsphy"); | 1166 | host->generic_phy = devm_phy_get(dev, "ufsphy"); |
| 957 | 1167 | ||
| 958 | if (IS_ERR(host->generic_phy)) { | 1168 | if (IS_ERR(host->generic_phy)) { |
| @@ -968,6 +1178,30 @@ static int ufs_qcom_init(struct ufs_hba *hba) | |||
| 968 | ufs_qcom_get_controller_revision(hba, &host->hw_ver.major, | 1178 | ufs_qcom_get_controller_revision(hba, &host->hw_ver.major, |
| 969 | &host->hw_ver.minor, &host->hw_ver.step); | 1179 | &host->hw_ver.minor, &host->hw_ver.step); |
| 970 | 1180 | ||
| 1181 | /* | ||
| 1182 | * for newer controllers, device reference clock control bit has | ||
| 1183 | * moved inside UFS controller register address space itself. | ||
| 1184 | */ | ||
| 1185 | if (host->hw_ver.major >= 0x02) { | ||
| 1186 | host->dev_ref_clk_ctrl_mmio = hba->mmio_base + REG_UFS_CFG1; | ||
| 1187 | host->dev_ref_clk_en_mask = BIT(26); | ||
| 1188 | } else { | ||
| 1189 | /* "dev_ref_clk_ctrl_mem" is optional resource */ | ||
| 1190 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
| 1191 | if (res) { | ||
| 1192 | host->dev_ref_clk_ctrl_mmio = | ||
| 1193 | devm_ioremap_resource(dev, res); | ||
| 1194 | if (IS_ERR(host->dev_ref_clk_ctrl_mmio)) { | ||
| 1195 | dev_warn(dev, | ||
| 1196 | "%s: could not map dev_ref_clk_ctrl_mmio, err %ld\n", | ||
| 1197 | __func__, | ||
| 1198 | PTR_ERR(host->dev_ref_clk_ctrl_mmio)); | ||
| 1199 | host->dev_ref_clk_ctrl_mmio = NULL; | ||
| 1200 | } | ||
| 1201 | host->dev_ref_clk_en_mask = BIT(5); | ||
| 1202 | } | ||
| 1203 | } | ||
| 1204 | |||
| 971 | /* update phy revision information before calling phy_init() */ | 1205 | /* update phy revision information before calling phy_init() */ |
| 972 | ufs_qcom_phy_save_controller_version(host->generic_phy, | 1206 | ufs_qcom_phy_save_controller_version(host->generic_phy, |
| 973 | host->hw_ver.major, host->hw_ver.minor, host->hw_ver.step); | 1207 | host->hw_ver.major, host->hw_ver.minor, host->hw_ver.step); |
| @@ -984,14 +1218,20 @@ static int ufs_qcom_init(struct ufs_hba *hba) | |||
| 984 | ufs_qcom_set_caps(hba); | 1218 | ufs_qcom_set_caps(hba); |
| 985 | ufs_qcom_advertise_quirks(hba); | 1219 | ufs_qcom_advertise_quirks(hba); |
| 986 | 1220 | ||
| 987 | hba->caps |= UFSHCD_CAP_CLK_GATING | UFSHCD_CAP_CLK_SCALING; | ||
| 988 | hba->caps |= UFSHCD_CAP_AUTO_BKOPS_SUSPEND; | ||
| 989 | |||
| 990 | ufs_qcom_setup_clocks(hba, true); | 1221 | ufs_qcom_setup_clocks(hba, true); |
| 991 | 1222 | ||
| 992 | if (hba->dev->id < MAX_UFS_QCOM_HOSTS) | 1223 | if (hba->dev->id < MAX_UFS_QCOM_HOSTS) |
| 993 | ufs_qcom_hosts[hba->dev->id] = host; | 1224 | ufs_qcom_hosts[hba->dev->id] = host; |
| 994 | 1225 | ||
| 1226 | host->dbg_print_en |= UFS_QCOM_DEFAULT_DBG_PRINT_EN; | ||
| 1227 | ufs_qcom_get_default_testbus_cfg(host); | ||
| 1228 | err = ufs_qcom_testbus_config(host); | ||
| 1229 | if (err) { | ||
| 1230 | dev_warn(dev, "%s: failed to configure the testbus %d\n", | ||
| 1231 | __func__, err); | ||
| 1232 | err = 0; | ||
| 1233 | } | ||
| 1234 | |||
| 995 | goto out; | 1235 | goto out; |
| 996 | 1236 | ||
| 997 | out_disable_phy: | 1237 | out_disable_phy: |
| @@ -1000,40 +1240,266 @@ out_unregister_bus: | |||
| 1000 | phy_exit(host->generic_phy); | 1240 | phy_exit(host->generic_phy); |
| 1001 | out_host_free: | 1241 | out_host_free: |
| 1002 | devm_kfree(dev, host); | 1242 | devm_kfree(dev, host); |
| 1003 | hba->priv = NULL; | 1243 | ufshcd_set_variant(hba, NULL); |
| 1004 | out: | 1244 | out: |
| 1005 | return err; | 1245 | return err; |
| 1006 | } | 1246 | } |
| 1007 | 1247 | ||
| 1008 | static void ufs_qcom_exit(struct ufs_hba *hba) | 1248 | static void ufs_qcom_exit(struct ufs_hba *hba) |
| 1009 | { | 1249 | { |
| 1010 | struct ufs_qcom_host *host = hba->priv; | 1250 | struct ufs_qcom_host *host = ufshcd_get_variant(hba); |
| 1011 | 1251 | ||
| 1012 | ufs_qcom_disable_lane_clks(host); | 1252 | ufs_qcom_disable_lane_clks(host); |
| 1013 | phy_power_off(host->generic_phy); | 1253 | phy_power_off(host->generic_phy); |
| 1014 | } | 1254 | } |
| 1015 | 1255 | ||
| 1016 | static | 1256 | static int ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(struct ufs_hba *hba, |
| 1017 | void ufs_qcom_clk_scale_notify(struct ufs_hba *hba) | 1257 | u32 clk_cycles) |
| 1258 | { | ||
| 1259 | int err; | ||
| 1260 | u32 core_clk_ctrl_reg; | ||
| 1261 | |||
| 1262 | if (clk_cycles > DME_VS_CORE_CLK_CTRL_MAX_CORE_CLK_1US_CYCLES_MASK) | ||
| 1263 | return -EINVAL; | ||
| 1264 | |||
| 1265 | err = ufshcd_dme_get(hba, | ||
| 1266 | UIC_ARG_MIB(DME_VS_CORE_CLK_CTRL), | ||
| 1267 | &core_clk_ctrl_reg); | ||
| 1268 | if (err) | ||
| 1269 | goto out; | ||
| 1270 | |||
| 1271 | core_clk_ctrl_reg &= ~DME_VS_CORE_CLK_CTRL_MAX_CORE_CLK_1US_CYCLES_MASK; | ||
| 1272 | core_clk_ctrl_reg |= clk_cycles; | ||
| 1273 | |||
| 1274 | /* Clear CORE_CLK_DIV_EN */ | ||
| 1275 | core_clk_ctrl_reg &= ~DME_VS_CORE_CLK_CTRL_CORE_CLK_DIV_EN_BIT; | ||
| 1276 | |||
| 1277 | err = ufshcd_dme_set(hba, | ||
| 1278 | UIC_ARG_MIB(DME_VS_CORE_CLK_CTRL), | ||
| 1279 | core_clk_ctrl_reg); | ||
| 1280 | out: | ||
| 1281 | return err; | ||
| 1282 | } | ||
| 1283 | |||
| 1284 | static int ufs_qcom_clk_scale_up_pre_change(struct ufs_hba *hba) | ||
| 1285 | { | ||
| 1286 | /* nothing to do as of now */ | ||
| 1287 | return 0; | ||
| 1288 | } | ||
| 1289 | |||
| 1290 | static int ufs_qcom_clk_scale_up_post_change(struct ufs_hba *hba) | ||
| 1291 | { | ||
| 1292 | struct ufs_qcom_host *host = ufshcd_get_variant(hba); | ||
| 1293 | |||
| 1294 | if (!ufs_qcom_cap_qunipro(host)) | ||
| 1295 | return 0; | ||
| 1296 | |||
| 1297 | /* set unipro core clock cycles to 150 and clear clock divider */ | ||
| 1298 | return ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(hba, 150); | ||
| 1299 | } | ||
| 1300 | |||
| 1301 | static int ufs_qcom_clk_scale_down_pre_change(struct ufs_hba *hba) | ||
| 1302 | { | ||
| 1303 | struct ufs_qcom_host *host = ufshcd_get_variant(hba); | ||
| 1304 | int err; | ||
| 1305 | u32 core_clk_ctrl_reg; | ||
| 1306 | |||
| 1307 | if (!ufs_qcom_cap_qunipro(host)) | ||
| 1308 | return 0; | ||
| 1309 | |||
| 1310 | err = ufshcd_dme_get(hba, | ||
| 1311 | UIC_ARG_MIB(DME_VS_CORE_CLK_CTRL), | ||
| 1312 | &core_clk_ctrl_reg); | ||
| 1313 | |||
| 1314 | /* make sure CORE_CLK_DIV_EN is cleared */ | ||
| 1315 | if (!err && | ||
| 1316 | (core_clk_ctrl_reg & DME_VS_CORE_CLK_CTRL_CORE_CLK_DIV_EN_BIT)) { | ||
| 1317 | core_clk_ctrl_reg &= ~DME_VS_CORE_CLK_CTRL_CORE_CLK_DIV_EN_BIT; | ||
| 1318 | err = ufshcd_dme_set(hba, | ||
| 1319 | UIC_ARG_MIB(DME_VS_CORE_CLK_CTRL), | ||
| 1320 | core_clk_ctrl_reg); | ||
| 1321 | } | ||
| 1322 | |||
| 1323 | return err; | ||
| 1324 | } | ||
| 1325 | |||
| 1326 | static int ufs_qcom_clk_scale_down_post_change(struct ufs_hba *hba) | ||
| 1327 | { | ||
| 1328 | struct ufs_qcom_host *host = ufshcd_get_variant(hba); | ||
| 1329 | |||
| 1330 | if (!ufs_qcom_cap_qunipro(host)) | ||
| 1331 | return 0; | ||
| 1332 | |||
| 1333 | /* set unipro core clock cycles to 75 and clear clock divider */ | ||
| 1334 | return ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(hba, 75); | ||
| 1335 | } | ||
| 1336 | |||
| 1337 | static int ufs_qcom_clk_scale_notify(struct ufs_hba *hba, | ||
| 1338 | bool scale_up, enum ufs_notify_change_status status) | ||
| 1018 | { | 1339 | { |
| 1019 | struct ufs_qcom_host *host = hba->priv; | 1340 | struct ufs_qcom_host *host = ufshcd_get_variant(hba); |
| 1020 | struct ufs_pa_layer_attr *dev_req_params = &host->dev_req_params; | 1341 | struct ufs_pa_layer_attr *dev_req_params = &host->dev_req_params; |
| 1342 | int err = 0; | ||
| 1021 | 1343 | ||
| 1022 | if (!dev_req_params) | 1344 | if (status == PRE_CHANGE) { |
| 1023 | return; | 1345 | if (scale_up) |
| 1346 | err = ufs_qcom_clk_scale_up_pre_change(hba); | ||
| 1347 | else | ||
| 1348 | err = ufs_qcom_clk_scale_down_pre_change(hba); | ||
| 1349 | } else { | ||
| 1350 | if (scale_up) | ||
| 1351 | err = ufs_qcom_clk_scale_up_post_change(hba); | ||
| 1352 | else | ||
| 1353 | err = ufs_qcom_clk_scale_down_post_change(hba); | ||
| 1024 | 1354 | ||
| 1025 | ufs_qcom_cfg_timers(hba, dev_req_params->gear_rx, | 1355 | if (err || !dev_req_params) |
| 1026 | dev_req_params->pwr_rx, | 1356 | goto out; |
| 1027 | dev_req_params->hs_rate); | 1357 | |
| 1358 | ufs_qcom_cfg_timers(hba, | ||
| 1359 | dev_req_params->gear_rx, | ||
| 1360 | dev_req_params->pwr_rx, | ||
| 1361 | dev_req_params->hs_rate, | ||
| 1362 | false); | ||
| 1363 | ufs_qcom_update_bus_bw_vote(host); | ||
| 1364 | } | ||
| 1365 | |||
| 1366 | out: | ||
| 1367 | return err; | ||
| 1028 | } | 1368 | } |
| 1029 | 1369 | ||
| 1370 | static void ufs_qcom_get_default_testbus_cfg(struct ufs_qcom_host *host) | ||
| 1371 | { | ||
| 1372 | /* provide a legal default configuration */ | ||
| 1373 | host->testbus.select_major = TSTBUS_UAWM; | ||
| 1374 | host->testbus.select_minor = 1; | ||
| 1375 | } | ||
| 1376 | |||
| 1377 | static bool ufs_qcom_testbus_cfg_is_ok(struct ufs_qcom_host *host) | ||
| 1378 | { | ||
| 1379 | if (host->testbus.select_major >= TSTBUS_MAX) { | ||
| 1380 | dev_err(host->hba->dev, | ||
| 1381 | "%s: UFS_CFG1[TEST_BUS_SEL} may not equal 0x%05X\n", | ||
| 1382 | __func__, host->testbus.select_major); | ||
| 1383 | return false; | ||
| 1384 | } | ||
| 1385 | |||
| 1386 | /* | ||
| 1387 | * Not performing check for each individual select_major | ||
| 1388 | * mappings of select_minor, since there is no harm in | ||
| 1389 | * configuring a non-existent select_minor | ||
| 1390 | */ | ||
| 1391 | if (host->testbus.select_minor > 0x1F) { | ||
| 1392 | dev_err(host->hba->dev, | ||
| 1393 | "%s: 0x%05X is not a legal testbus option\n", | ||
| 1394 | __func__, host->testbus.select_minor); | ||
| 1395 | return false; | ||
| 1396 | } | ||
| 1397 | |||
| 1398 | return true; | ||
| 1399 | } | ||
| 1400 | |||
| 1401 | int ufs_qcom_testbus_config(struct ufs_qcom_host *host) | ||
| 1402 | { | ||
| 1403 | int reg; | ||
| 1404 | int offset; | ||
| 1405 | u32 mask = TEST_BUS_SUB_SEL_MASK; | ||
| 1406 | |||
| 1407 | if (!host) | ||
| 1408 | return -EINVAL; | ||
| 1409 | |||
| 1410 | if (!ufs_qcom_testbus_cfg_is_ok(host)) | ||
| 1411 | return -EPERM; | ||
| 1412 | |||
| 1413 | switch (host->testbus.select_major) { | ||
| 1414 | case TSTBUS_UAWM: | ||
| 1415 | reg = UFS_TEST_BUS_CTRL_0; | ||
| 1416 | offset = 24; | ||
| 1417 | break; | ||
| 1418 | case TSTBUS_UARM: | ||
| 1419 | reg = UFS_TEST_BUS_CTRL_0; | ||
| 1420 | offset = 16; | ||
| 1421 | break; | ||
| 1422 | case TSTBUS_TXUC: | ||
| 1423 | reg = UFS_TEST_BUS_CTRL_0; | ||
| 1424 | offset = 8; | ||
| 1425 | break; | ||
| 1426 | case TSTBUS_RXUC: | ||
| 1427 | reg = UFS_TEST_BUS_CTRL_0; | ||
| 1428 | offset = 0; | ||
| 1429 | break; | ||
| 1430 | case TSTBUS_DFC: | ||
| 1431 | reg = UFS_TEST_BUS_CTRL_1; | ||
| 1432 | offset = 24; | ||
| 1433 | break; | ||
| 1434 | case TSTBUS_TRLUT: | ||
| 1435 | reg = UFS_TEST_BUS_CTRL_1; | ||
| 1436 | offset = 16; | ||
| 1437 | break; | ||
| 1438 | case TSTBUS_TMRLUT: | ||
| 1439 | reg = UFS_TEST_BUS_CTRL_1; | ||
| 1440 | offset = 8; | ||
| 1441 | break; | ||
| 1442 | case TSTBUS_OCSC: | ||
| 1443 | reg = UFS_TEST_BUS_CTRL_1; | ||
| 1444 | offset = 0; | ||
| 1445 | break; | ||
| 1446 | case TSTBUS_WRAPPER: | ||
| 1447 | reg = UFS_TEST_BUS_CTRL_2; | ||
| 1448 | offset = 16; | ||
| 1449 | break; | ||
| 1450 | case TSTBUS_COMBINED: | ||
| 1451 | reg = UFS_TEST_BUS_CTRL_2; | ||
| 1452 | offset = 8; | ||
| 1453 | break; | ||
| 1454 | case TSTBUS_UTP_HCI: | ||
| 1455 | reg = UFS_TEST_BUS_CTRL_2; | ||
| 1456 | offset = 0; | ||
| 1457 | break; | ||
| 1458 | case TSTBUS_UNIPRO: | ||
| 1459 | reg = UFS_UNIPRO_CFG; | ||
| 1460 | offset = 1; | ||
| 1461 | break; | ||
| 1462 | /* | ||
| 1463 | * No need for a default case, since | ||
| 1464 | * ufs_qcom_testbus_cfg_is_ok() checks that the configuration | ||
| 1465 | * is legal | ||
| 1466 | */ | ||
| 1467 | } | ||
| 1468 | mask <<= offset; | ||
| 1469 | |||
| 1470 | pm_runtime_get_sync(host->hba->dev); | ||
| 1471 | ufshcd_hold(host->hba, false); | ||
| 1472 | ufshcd_rmwl(host->hba, TEST_BUS_SEL, | ||
| 1473 | (u32)host->testbus.select_major << 19, | ||
| 1474 | REG_UFS_CFG1); | ||
| 1475 | ufshcd_rmwl(host->hba, mask, | ||
| 1476 | (u32)host->testbus.select_minor << offset, | ||
| 1477 | reg); | ||
| 1478 | ufshcd_release(host->hba); | ||
| 1479 | pm_runtime_put_sync(host->hba->dev); | ||
| 1480 | |||
| 1481 | return 0; | ||
| 1482 | } | ||
| 1483 | |||
| 1484 | static void ufs_qcom_testbus_read(struct ufs_hba *hba) | ||
| 1485 | { | ||
| 1486 | ufs_qcom_dump_regs(hba, UFS_TEST_BUS, 1, "UFS_TEST_BUS "); | ||
| 1487 | } | ||
| 1488 | |||
| 1489 | static void ufs_qcom_dump_dbg_regs(struct ufs_hba *hba) | ||
| 1490 | { | ||
| 1491 | ufs_qcom_dump_regs(hba, REG_UFS_SYS1CLK_1US, 16, | ||
| 1492 | "HCI Vendor Specific Registers "); | ||
| 1493 | |||
| 1494 | ufs_qcom_testbus_read(hba); | ||
| 1495 | } | ||
| 1030 | /** | 1496 | /** |
| 1031 | * struct ufs_hba_qcom_vops - UFS QCOM specific variant operations | 1497 | * struct ufs_hba_qcom_vops - UFS QCOM specific variant operations |
| 1032 | * | 1498 | * |
| 1033 | * The variant operations configure the necessary controller and PHY | 1499 | * The variant operations configure the necessary controller and PHY |
| 1034 | * handshake during initialization. | 1500 | * handshake during initialization. |
| 1035 | */ | 1501 | */ |
| 1036 | static const struct ufs_hba_variant_ops ufs_hba_qcom_vops = { | 1502 | static struct ufs_hba_variant_ops ufs_hba_qcom_vops = { |
| 1037 | .name = "qcom", | 1503 | .name = "qcom", |
| 1038 | .init = ufs_qcom_init, | 1504 | .init = ufs_qcom_init, |
| 1039 | .exit = ufs_qcom_exit, | 1505 | .exit = ufs_qcom_exit, |
| @@ -1045,5 +1511,66 @@ static const struct ufs_hba_variant_ops ufs_hba_qcom_vops = { | |||
| 1045 | .pwr_change_notify = ufs_qcom_pwr_change_notify, | 1511 | .pwr_change_notify = ufs_qcom_pwr_change_notify, |
| 1046 | .suspend = ufs_qcom_suspend, | 1512 | .suspend = ufs_qcom_suspend, |
| 1047 | .resume = ufs_qcom_resume, | 1513 | .resume = ufs_qcom_resume, |
| 1514 | .dbg_register_dump = ufs_qcom_dump_dbg_regs, | ||
| 1515 | }; | ||
| 1516 | |||
| 1517 | /** | ||
| 1518 | * ufs_qcom_probe - probe routine of the driver | ||
| 1519 | * @pdev: pointer to Platform device handle | ||
| 1520 | * | ||
| 1521 | * Return zero for success and non-zero for failure | ||
| 1522 | */ | ||
| 1523 | static int ufs_qcom_probe(struct platform_device *pdev) | ||
| 1524 | { | ||
| 1525 | int err; | ||
| 1526 | struct device *dev = &pdev->dev; | ||
| 1527 | |||
| 1528 | /* Perform generic probe */ | ||
| 1529 | err = ufshcd_pltfrm_init(pdev, &ufs_hba_qcom_vops); | ||
| 1530 | if (err) | ||
| 1531 | dev_err(dev, "ufshcd_pltfrm_init() failed %d\n", err); | ||
| 1532 | |||
| 1533 | return err; | ||
| 1534 | } | ||
| 1535 | |||
| 1536 | /** | ||
| 1537 | * ufs_qcom_remove - set driver_data of the device to NULL | ||
| 1538 | * @pdev: pointer to platform device handle | ||
| 1539 | * | ||
| 1540 | * Always return 0 | ||
| 1541 | */ | ||
| 1542 | static int ufs_qcom_remove(struct platform_device *pdev) | ||
| 1543 | { | ||
| 1544 | struct ufs_hba *hba = platform_get_drvdata(pdev); | ||
| 1545 | |||
| 1546 | pm_runtime_get_sync(&(pdev)->dev); | ||
| 1547 | ufshcd_remove(hba); | ||
| 1548 | return 0; | ||
| 1549 | } | ||
| 1550 | |||
| 1551 | static const struct of_device_id ufs_qcom_of_match[] = { | ||
| 1552 | { .compatible = "qcom,ufshc"}, | ||
| 1553 | {}, | ||
| 1554 | }; | ||
| 1555 | |||
| 1556 | static const struct dev_pm_ops ufs_qcom_pm_ops = { | ||
| 1557 | .suspend = ufshcd_pltfrm_suspend, | ||
| 1558 | .resume = ufshcd_pltfrm_resume, | ||
| 1559 | .runtime_suspend = ufshcd_pltfrm_runtime_suspend, | ||
| 1560 | .runtime_resume = ufshcd_pltfrm_runtime_resume, | ||
| 1561 | .runtime_idle = ufshcd_pltfrm_runtime_idle, | ||
| 1048 | }; | 1562 | }; |
| 1049 | EXPORT_SYMBOL(ufs_hba_qcom_vops); | 1563 | |
| 1564 | static struct platform_driver ufs_qcom_pltform = { | ||
| 1565 | .probe = ufs_qcom_probe, | ||
| 1566 | .remove = ufs_qcom_remove, | ||
| 1567 | .shutdown = ufshcd_pltfrm_shutdown, | ||
| 1568 | .driver = { | ||
| 1569 | .name = "ufshcd-qcom", | ||
| 1570 | .pm = &ufs_qcom_pm_ops, | ||
| 1571 | .of_match_table = of_match_ptr(ufs_qcom_of_match), | ||
| 1572 | }, | ||
| 1573 | }; | ||
| 1574 | module_platform_driver(ufs_qcom_pltform); | ||
| 1575 | |||
| 1576 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/scsi/ufs/ufs-qcom.h b/drivers/scsi/ufs/ufs-qcom.h index db2c0a00e846..36249b35f858 100644 --- a/drivers/scsi/ufs/ufs-qcom.h +++ b/drivers/scsi/ufs/ufs-qcom.h | |||
| @@ -35,8 +35,8 @@ | |||
| 35 | 35 | ||
| 36 | #define UFS_QCOM_LIMIT_NUM_LANES_RX 2 | 36 | #define UFS_QCOM_LIMIT_NUM_LANES_RX 2 |
| 37 | #define UFS_QCOM_LIMIT_NUM_LANES_TX 2 | 37 | #define UFS_QCOM_LIMIT_NUM_LANES_TX 2 |
| 38 | #define UFS_QCOM_LIMIT_HSGEAR_RX UFS_HS_G2 | 38 | #define UFS_QCOM_LIMIT_HSGEAR_RX UFS_HS_G3 |
| 39 | #define UFS_QCOM_LIMIT_HSGEAR_TX UFS_HS_G2 | 39 | #define UFS_QCOM_LIMIT_HSGEAR_TX UFS_HS_G3 |
| 40 | #define UFS_QCOM_LIMIT_PWMGEAR_RX UFS_PWM_G4 | 40 | #define UFS_QCOM_LIMIT_PWMGEAR_RX UFS_PWM_G4 |
| 41 | #define UFS_QCOM_LIMIT_PWMGEAR_TX UFS_PWM_G4 | 41 | #define UFS_QCOM_LIMIT_PWMGEAR_TX UFS_PWM_G4 |
| 42 | #define UFS_QCOM_LIMIT_RX_PWR_PWM SLOW_MODE | 42 | #define UFS_QCOM_LIMIT_RX_PWR_PWM SLOW_MODE |
| @@ -58,6 +58,21 @@ enum { | |||
| 58 | REG_UFS_CFG2 = 0xE0, | 58 | REG_UFS_CFG2 = 0xE0, |
| 59 | REG_UFS_HW_VERSION = 0xE4, | 59 | REG_UFS_HW_VERSION = 0xE4, |
| 60 | 60 | ||
| 61 | UFS_TEST_BUS = 0xE8, | ||
| 62 | UFS_TEST_BUS_CTRL_0 = 0xEC, | ||
| 63 | UFS_TEST_BUS_CTRL_1 = 0xF0, | ||
| 64 | UFS_TEST_BUS_CTRL_2 = 0xF4, | ||
| 65 | UFS_UNIPRO_CFG = 0xF8, | ||
| 66 | |||
| 67 | /* | ||
| 68 | * QCOM UFS host controller vendor specific registers | ||
| 69 | * added in HW Version 3.0.0 | ||
| 70 | */ | ||
| 71 | UFS_AH8_CFG = 0xFC, | ||
| 72 | }; | ||
| 73 | |||
| 74 | /* QCOM UFS host controller vendor specific debug registers */ | ||
| 75 | enum { | ||
| 61 | UFS_DBG_RD_REG_UAWM = 0x100, | 76 | UFS_DBG_RD_REG_UAWM = 0x100, |
| 62 | UFS_DBG_RD_REG_UARM = 0x200, | 77 | UFS_DBG_RD_REG_UARM = 0x200, |
| 63 | UFS_DBG_RD_REG_TXUC = 0x300, | 78 | UFS_DBG_RD_REG_TXUC = 0x300, |
| @@ -73,6 +88,14 @@ enum { | |||
| 73 | UFS_UFS_DBG_RD_EDTL_RAM = 0x1900, | 88 | UFS_UFS_DBG_RD_EDTL_RAM = 0x1900, |
| 74 | }; | 89 | }; |
| 75 | 90 | ||
| 91 | #define UFS_CNTLR_2_x_x_VEN_REGS_OFFSET(x) (0x000 + x) | ||
| 92 | #define UFS_CNTLR_3_x_x_VEN_REGS_OFFSET(x) (0x400 + x) | ||
| 93 | |||
| 94 | /* bit definitions for REG_UFS_CFG1 register */ | ||
| 95 | #define QUNIPRO_SEL UFS_BIT(0) | ||
| 96 | #define TEST_BUS_EN BIT(18) | ||
| 97 | #define TEST_BUS_SEL GENMASK(22, 19) | ||
| 98 | |||
| 76 | /* bit definitions for REG_UFS_CFG2 register */ | 99 | /* bit definitions for REG_UFS_CFG2 register */ |
| 77 | #define UAWM_HW_CGC_EN (1 << 0) | 100 | #define UAWM_HW_CGC_EN (1 << 0) |
| 78 | #define UARM_HW_CGC_EN (1 << 1) | 101 | #define UARM_HW_CGC_EN (1 << 1) |
| @@ -83,6 +106,9 @@ enum { | |||
| 83 | #define TMRLUT_HW_CGC_EN (1 << 6) | 106 | #define TMRLUT_HW_CGC_EN (1 << 6) |
| 84 | #define OCSC_HW_CGC_EN (1 << 7) | 107 | #define OCSC_HW_CGC_EN (1 << 7) |
| 85 | 108 | ||
| 109 | /* bit definition for UFS_UFS_TEST_BUS_CTRL_n */ | ||
| 110 | #define TEST_BUS_SUB_SEL_MASK 0x1F /* All XXX_SEL fields are 5 bits wide */ | ||
| 111 | |||
| 86 | #define REG_UFS_CFG2_CGC_EN_ALL (UAWM_HW_CGC_EN | UARM_HW_CGC_EN |\ | 112 | #define REG_UFS_CFG2_CGC_EN_ALL (UAWM_HW_CGC_EN | UARM_HW_CGC_EN |\ |
| 87 | TXUC_HW_CGC_EN | RXUC_HW_CGC_EN |\ | 113 | TXUC_HW_CGC_EN | RXUC_HW_CGC_EN |\ |
| 88 | DFC_HW_CGC_EN | TRLUT_HW_CGC_EN |\ | 114 | DFC_HW_CGC_EN | TRLUT_HW_CGC_EN |\ |
| @@ -106,6 +132,21 @@ enum ufs_qcom_phy_init_type { | |||
| 106 | UFS_PHY_INIT_CFG_RESTORE, | 132 | UFS_PHY_INIT_CFG_RESTORE, |
| 107 | }; | 133 | }; |
| 108 | 134 | ||
| 135 | /* QCOM UFS debug print bit mask */ | ||
| 136 | #define UFS_QCOM_DBG_PRINT_REGS_EN BIT(0) | ||
| 137 | #define UFS_QCOM_DBG_PRINT_ICE_REGS_EN BIT(1) | ||
| 138 | #define UFS_QCOM_DBG_PRINT_TEST_BUS_EN BIT(2) | ||
| 139 | |||
| 140 | #define UFS_QCOM_DBG_PRINT_ALL \ | ||
| 141 | (UFS_QCOM_DBG_PRINT_REGS_EN | UFS_QCOM_DBG_PRINT_ICE_REGS_EN | \ | ||
| 142 | UFS_QCOM_DBG_PRINT_TEST_BUS_EN) | ||
| 143 | |||
| 144 | /* QUniPro Vendor specific attributes */ | ||
| 145 | #define DME_VS_CORE_CLK_CTRL 0xD002 | ||
| 146 | /* bit and mask definitions for DME_VS_CORE_CLK_CTRL attribute */ | ||
| 147 | #define DME_VS_CORE_CLK_CTRL_CORE_CLK_DIV_EN_BIT BIT(8) | ||
| 148 | #define DME_VS_CORE_CLK_CTRL_MAX_CORE_CLK_1US_CYCLES_MASK 0xFF | ||
| 149 | |||
| 109 | static inline void | 150 | static inline void |
| 110 | ufs_qcom_get_controller_revision(struct ufs_hba *hba, | 151 | ufs_qcom_get_controller_revision(struct ufs_hba *hba, |
| 111 | u8 *major, u16 *minor, u16 *step) | 152 | u8 *major, u16 *minor, u16 *step) |
| @@ -157,8 +198,13 @@ struct ufs_hw_version { | |||
| 157 | u16 minor; | 198 | u16 minor; |
| 158 | u8 major; | 199 | u8 major; |
| 159 | }; | 200 | }; |
| 160 | struct ufs_qcom_host { | ||
| 161 | 201 | ||
| 202 | struct ufs_qcom_testbus { | ||
| 203 | u8 select_major; | ||
| 204 | u8 select_minor; | ||
| 205 | }; | ||
| 206 | |||
| 207 | struct ufs_qcom_host { | ||
| 162 | /* | 208 | /* |
| 163 | * Set this capability if host controller supports the QUniPro mode | 209 | * Set this capability if host controller supports the QUniPro mode |
| 164 | * and if driver wants the Host controller to operate in QUniPro mode. | 210 | * and if driver wants the Host controller to operate in QUniPro mode. |
| @@ -166,6 +212,12 @@ struct ufs_qcom_host { | |||
| 166 | * controller supports the QUniPro mode. | 212 | * controller supports the QUniPro mode. |
| 167 | */ | 213 | */ |
| 168 | #define UFS_QCOM_CAP_QUNIPRO UFS_BIT(0) | 214 | #define UFS_QCOM_CAP_QUNIPRO UFS_BIT(0) |
| 215 | |||
| 216 | /* | ||
| 217 | * Set this capability if host controller can retain the secure | ||
| 218 | * configuration even after UFS controller core power collapse. | ||
| 219 | */ | ||
| 220 | #define UFS_QCOM_CAP_RETAIN_SEC_CFG_AFTER_PWR_COLLAPSE UFS_BIT(1) | ||
| 169 | u32 caps; | 221 | u32 caps; |
| 170 | 222 | ||
| 171 | struct phy *generic_phy; | 223 | struct phy *generic_phy; |
| @@ -178,13 +230,23 @@ struct ufs_qcom_host { | |||
| 178 | struct clk *tx_l1_sync_clk; | 230 | struct clk *tx_l1_sync_clk; |
| 179 | bool is_lane_clks_enabled; | 231 | bool is_lane_clks_enabled; |
| 180 | 232 | ||
| 233 | void __iomem *dev_ref_clk_ctrl_mmio; | ||
| 234 | bool is_dev_ref_clk_enabled; | ||
| 181 | struct ufs_hw_version hw_ver; | 235 | struct ufs_hw_version hw_ver; |
| 236 | |||
| 237 | u32 dev_ref_clk_en_mask; | ||
| 238 | |||
| 239 | /* Bitmask for enabling debug prints */ | ||
| 240 | u32 dbg_print_en; | ||
| 241 | struct ufs_qcom_testbus testbus; | ||
| 182 | }; | 242 | }; |
| 183 | 243 | ||
| 184 | #define ufs_qcom_is_link_off(hba) ufshcd_is_link_off(hba) | 244 | #define ufs_qcom_is_link_off(hba) ufshcd_is_link_off(hba) |
| 185 | #define ufs_qcom_is_link_active(hba) ufshcd_is_link_active(hba) | 245 | #define ufs_qcom_is_link_active(hba) ufshcd_is_link_active(hba) |
| 186 | #define ufs_qcom_is_link_hibern8(hba) ufshcd_is_link_hibern8(hba) | 246 | #define ufs_qcom_is_link_hibern8(hba) ufshcd_is_link_hibern8(hba) |
| 187 | 247 | ||
| 248 | int ufs_qcom_testbus_config(struct ufs_qcom_host *host); | ||
| 249 | |||
| 188 | static inline bool ufs_qcom_cap_qunipro(struct ufs_qcom_host *host) | 250 | static inline bool ufs_qcom_cap_qunipro(struct ufs_qcom_host *host) |
| 189 | { | 251 | { |
| 190 | if (host->caps & UFS_QCOM_CAP_QUNIPRO) | 252 | if (host->caps & UFS_QCOM_CAP_QUNIPRO) |
diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c index 7db9564f507d..9714f2a8b329 100644 --- a/drivers/scsi/ufs/ufshcd-pltfrm.c +++ b/drivers/scsi/ufs/ufshcd-pltfrm.c | |||
| @@ -38,20 +38,7 @@ | |||
| 38 | #include <linux/of.h> | 38 | #include <linux/of.h> |
| 39 | 39 | ||
| 40 | #include "ufshcd.h" | 40 | #include "ufshcd.h" |
| 41 | 41 | #include "ufshcd-pltfrm.h" | |
| 42 | static const struct of_device_id ufs_of_match[]; | ||
| 43 | static struct ufs_hba_variant_ops *get_variant_ops(struct device *dev) | ||
| 44 | { | ||
| 45 | if (dev->of_node) { | ||
| 46 | const struct of_device_id *match; | ||
| 47 | |||
| 48 | match = of_match_node(ufs_of_match, dev->of_node); | ||
| 49 | if (match) | ||
| 50 | return (struct ufs_hba_variant_ops *)match->data; | ||
| 51 | } | ||
| 52 | |||
| 53 | return NULL; | ||
| 54 | } | ||
| 55 | 42 | ||
| 56 | static int ufshcd_parse_clock_info(struct ufs_hba *hba) | 43 | static int ufshcd_parse_clock_info(struct ufs_hba *hba) |
| 57 | { | 44 | { |
| @@ -245,10 +232,11 @@ out: | |||
| 245 | * Returns 0 if successful | 232 | * Returns 0 if successful |
| 246 | * Returns non-zero otherwise | 233 | * Returns non-zero otherwise |
| 247 | */ | 234 | */ |
| 248 | static int ufshcd_pltfrm_suspend(struct device *dev) | 235 | int ufshcd_pltfrm_suspend(struct device *dev) |
| 249 | { | 236 | { |
| 250 | return ufshcd_system_suspend(dev_get_drvdata(dev)); | 237 | return ufshcd_system_suspend(dev_get_drvdata(dev)); |
| 251 | } | 238 | } |
| 239 | EXPORT_SYMBOL_GPL(ufshcd_pltfrm_suspend); | ||
| 252 | 240 | ||
| 253 | /** | 241 | /** |
| 254 | * ufshcd_pltfrm_resume - resume power management function | 242 | * ufshcd_pltfrm_resume - resume power management function |
| @@ -257,43 +245,47 @@ static int ufshcd_pltfrm_suspend(struct device *dev) | |||
| 257 | * Returns 0 if successful | 245 | * Returns 0 if successful |
| 258 | * Returns non-zero otherwise | 246 | * Returns non-zero otherwise |
| 259 | */ | 247 | */ |
| 260 | static int ufshcd_pltfrm_resume(struct device *dev) | 248 | int ufshcd_pltfrm_resume(struct device *dev) |
| 261 | { | 249 | { |
| 262 | return ufshcd_system_resume(dev_get_drvdata(dev)); | 250 | return ufshcd_system_resume(dev_get_drvdata(dev)); |
| 263 | } | 251 | } |
| 252 | EXPORT_SYMBOL_GPL(ufshcd_pltfrm_resume); | ||
| 264 | 253 | ||
| 265 | static int ufshcd_pltfrm_runtime_suspend(struct device *dev) | 254 | int ufshcd_pltfrm_runtime_suspend(struct device *dev) |
| 266 | { | 255 | { |
| 267 | return ufshcd_runtime_suspend(dev_get_drvdata(dev)); | 256 | return ufshcd_runtime_suspend(dev_get_drvdata(dev)); |
| 268 | } | 257 | } |
| 269 | static int ufshcd_pltfrm_runtime_resume(struct device *dev) | 258 | EXPORT_SYMBOL_GPL(ufshcd_pltfrm_runtime_suspend); |
| 259 | |||
| 260 | int ufshcd_pltfrm_runtime_resume(struct device *dev) | ||
| 270 | { | 261 | { |
| 271 | return ufshcd_runtime_resume(dev_get_drvdata(dev)); | 262 | return ufshcd_runtime_resume(dev_get_drvdata(dev)); |
| 272 | } | 263 | } |
| 273 | static int ufshcd_pltfrm_runtime_idle(struct device *dev) | 264 | EXPORT_SYMBOL_GPL(ufshcd_pltfrm_runtime_resume); |
| 265 | |||
| 266 | int ufshcd_pltfrm_runtime_idle(struct device *dev) | ||
| 274 | { | 267 | { |
| 275 | return ufshcd_runtime_idle(dev_get_drvdata(dev)); | 268 | return ufshcd_runtime_idle(dev_get_drvdata(dev)); |
| 276 | } | 269 | } |
| 277 | #else /* !CONFIG_PM */ | 270 | EXPORT_SYMBOL_GPL(ufshcd_pltfrm_runtime_idle); |
| 278 | #define ufshcd_pltfrm_suspend NULL | 271 | |
| 279 | #define ufshcd_pltfrm_resume NULL | ||
| 280 | #define ufshcd_pltfrm_runtime_suspend NULL | ||
| 281 | #define ufshcd_pltfrm_runtime_resume NULL | ||
| 282 | #define ufshcd_pltfrm_runtime_idle NULL | ||
| 283 | #endif /* CONFIG_PM */ | 272 | #endif /* CONFIG_PM */ |
| 284 | 273 | ||
| 285 | static void ufshcd_pltfrm_shutdown(struct platform_device *pdev) | 274 | void ufshcd_pltfrm_shutdown(struct platform_device *pdev) |
| 286 | { | 275 | { |
| 287 | ufshcd_shutdown((struct ufs_hba *)platform_get_drvdata(pdev)); | 276 | ufshcd_shutdown((struct ufs_hba *)platform_get_drvdata(pdev)); |
| 288 | } | 277 | } |
| 278 | EXPORT_SYMBOL_GPL(ufshcd_pltfrm_shutdown); | ||
| 289 | 279 | ||
| 290 | /** | 280 | /** |
| 291 | * ufshcd_pltfrm_probe - probe routine of the driver | 281 | * ufshcd_pltfrm_init - probe routine of the driver |
| 292 | * @pdev: pointer to Platform device handle | 282 | * @pdev: pointer to Platform device handle |
| 283 | * @vops: pointer to variant ops | ||
| 293 | * | 284 | * |
| 294 | * Returns 0 on success, non-zero value on failure | 285 | * Returns 0 on success, non-zero value on failure |
| 295 | */ | 286 | */ |
| 296 | static int ufshcd_pltfrm_probe(struct platform_device *pdev) | 287 | int ufshcd_pltfrm_init(struct platform_device *pdev, |
| 288 | struct ufs_hba_variant_ops *vops) | ||
| 297 | { | 289 | { |
| 298 | struct ufs_hba *hba; | 290 | struct ufs_hba *hba; |
| 299 | void __iomem *mmio_base; | 291 | void __iomem *mmio_base; |
| @@ -321,19 +313,19 @@ static int ufshcd_pltfrm_probe(struct platform_device *pdev) | |||
| 321 | goto out; | 313 | goto out; |
| 322 | } | 314 | } |
| 323 | 315 | ||
| 324 | hba->vops = get_variant_ops(&pdev->dev); | 316 | hba->vops = vops; |
| 325 | 317 | ||
| 326 | err = ufshcd_parse_clock_info(hba); | 318 | err = ufshcd_parse_clock_info(hba); |
| 327 | if (err) { | 319 | if (err) { |
| 328 | dev_err(&pdev->dev, "%s: clock parse failed %d\n", | 320 | dev_err(&pdev->dev, "%s: clock parse failed %d\n", |
| 329 | __func__, err); | 321 | __func__, err); |
| 330 | goto out; | 322 | goto dealloc_host; |
| 331 | } | 323 | } |
| 332 | err = ufshcd_parse_regulator_info(hba); | 324 | err = ufshcd_parse_regulator_info(hba); |
| 333 | if (err) { | 325 | if (err) { |
| 334 | dev_err(&pdev->dev, "%s: regulator init failed %d\n", | 326 | dev_err(&pdev->dev, "%s: regulator init failed %d\n", |
| 335 | __func__, err); | 327 | __func__, err); |
| 336 | goto out; | 328 | goto dealloc_host; |
| 337 | } | 329 | } |
| 338 | 330 | ||
| 339 | pm_runtime_set_active(&pdev->dev); | 331 | pm_runtime_set_active(&pdev->dev); |
| @@ -352,50 +344,12 @@ static int ufshcd_pltfrm_probe(struct platform_device *pdev) | |||
| 352 | out_disable_rpm: | 344 | out_disable_rpm: |
| 353 | pm_runtime_disable(&pdev->dev); | 345 | pm_runtime_disable(&pdev->dev); |
| 354 | pm_runtime_set_suspended(&pdev->dev); | 346 | pm_runtime_set_suspended(&pdev->dev); |
| 347 | dealloc_host: | ||
| 348 | ufshcd_dealloc_host(hba); | ||
| 355 | out: | 349 | out: |
| 356 | return err; | 350 | return err; |
| 357 | } | 351 | } |
| 358 | 352 | EXPORT_SYMBOL_GPL(ufshcd_pltfrm_init); | |
| 359 | /** | ||
| 360 | * ufshcd_pltfrm_remove - remove platform driver routine | ||
| 361 | * @pdev: pointer to platform device handle | ||
| 362 | * | ||
| 363 | * Returns 0 on success, non-zero value on failure | ||
| 364 | */ | ||
| 365 | static int ufshcd_pltfrm_remove(struct platform_device *pdev) | ||
| 366 | { | ||
| 367 | struct ufs_hba *hba = platform_get_drvdata(pdev); | ||
| 368 | |||
| 369 | pm_runtime_get_sync(&(pdev)->dev); | ||
| 370 | ufshcd_remove(hba); | ||
| 371 | return 0; | ||
| 372 | } | ||
| 373 | |||
| 374 | static const struct of_device_id ufs_of_match[] = { | ||
| 375 | { .compatible = "jedec,ufs-1.1"}, | ||
| 376 | {}, | ||
| 377 | }; | ||
| 378 | |||
| 379 | static const struct dev_pm_ops ufshcd_dev_pm_ops = { | ||
| 380 | .suspend = ufshcd_pltfrm_suspend, | ||
| 381 | .resume = ufshcd_pltfrm_resume, | ||
| 382 | .runtime_suspend = ufshcd_pltfrm_runtime_suspend, | ||
| 383 | .runtime_resume = ufshcd_pltfrm_runtime_resume, | ||
| 384 | .runtime_idle = ufshcd_pltfrm_runtime_idle, | ||
| 385 | }; | ||
| 386 | |||
| 387 | static struct platform_driver ufshcd_pltfrm_driver = { | ||
| 388 | .probe = ufshcd_pltfrm_probe, | ||
| 389 | .remove = ufshcd_pltfrm_remove, | ||
| 390 | .shutdown = ufshcd_pltfrm_shutdown, | ||
| 391 | .driver = { | ||
| 392 | .name = "ufshcd", | ||
| 393 | .pm = &ufshcd_dev_pm_ops, | ||
| 394 | .of_match_table = ufs_of_match, | ||
| 395 | }, | ||
| 396 | }; | ||
| 397 | |||
| 398 | module_platform_driver(ufshcd_pltfrm_driver); | ||
| 399 | 353 | ||
| 400 | MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>"); | 354 | MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>"); |
| 401 | MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>"); | 355 | MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>"); |
diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.h b/drivers/scsi/ufs/ufshcd-pltfrm.h new file mode 100644 index 000000000000..df64c4180340 --- /dev/null +++ b/drivers/scsi/ufs/ufshcd-pltfrm.h | |||
| @@ -0,0 +1,41 @@ | |||
| 1 | /* Copyright (c) 2015, The Linux Foundation. All rights reserved. | ||
| 2 | * | ||
| 3 | * This program is free software; you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License version 2 and | ||
| 5 | * only version 2 as published by the Free Software Foundation. | ||
| 6 | * | ||
| 7 | * This program is distributed in the hope that it will be useful, | ||
| 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 10 | * GNU General Public License for more details. | ||
| 11 | * | ||
| 12 | */ | ||
| 13 | |||
| 14 | #ifndef UFSHCD_PLTFRM_H_ | ||
| 15 | #define UFSHCD_PLTFRM_H_ | ||
| 16 | |||
| 17 | #include "ufshcd.h" | ||
| 18 | |||
| 19 | int ufshcd_pltfrm_init(struct platform_device *pdev, | ||
| 20 | struct ufs_hba_variant_ops *vops); | ||
| 21 | void ufshcd_pltfrm_shutdown(struct platform_device *pdev); | ||
| 22 | |||
| 23 | #ifdef CONFIG_PM | ||
| 24 | |||
| 25 | int ufshcd_pltfrm_suspend(struct device *dev); | ||
| 26 | int ufshcd_pltfrm_resume(struct device *dev); | ||
| 27 | int ufshcd_pltfrm_runtime_suspend(struct device *dev); | ||
| 28 | int ufshcd_pltfrm_runtime_resume(struct device *dev); | ||
| 29 | int ufshcd_pltfrm_runtime_idle(struct device *dev); | ||
| 30 | |||
| 31 | #else /* !CONFIG_PM */ | ||
| 32 | |||
| 33 | #define ufshcd_pltfrm_suspend NULL | ||
| 34 | #define ufshcd_pltfrm_resume NULL | ||
| 35 | #define ufshcd_pltfrm_runtime_suspend NULL | ||
| 36 | #define ufshcd_pltfrm_runtime_resume NULL | ||
| 37 | #define ufshcd_pltfrm_runtime_idle NULL | ||
| 38 | |||
| 39 | #endif /* CONFIG_PM */ | ||
| 40 | |||
| 41 | #endif /* UFSHCD_PLTFRM_H_ */ | ||
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 9065eb451677..85cd2564c157 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c | |||
| @@ -271,10 +271,8 @@ static inline u32 ufshcd_get_intr_mask(struct ufs_hba *hba) | |||
| 271 | */ | 271 | */ |
| 272 | static inline u32 ufshcd_get_ufs_version(struct ufs_hba *hba) | 272 | static inline u32 ufshcd_get_ufs_version(struct ufs_hba *hba) |
| 273 | { | 273 | { |
| 274 | if (hba->quirks & UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION) { | 274 | if (hba->quirks & UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION) |
| 275 | if (hba->vops && hba->vops->get_ufs_hci_version) | 275 | return ufshcd_vops_get_ufs_hci_version(hba); |
| 276 | return hba->vops->get_ufs_hci_version(hba); | ||
| 277 | } | ||
| 278 | 276 | ||
| 279 | return ufshcd_readl(hba, REG_UFS_VERSION); | 277 | return ufshcd_readl(hba, REG_UFS_VERSION); |
| 280 | } | 278 | } |
| @@ -627,6 +625,7 @@ start: | |||
| 627 | out: | 625 | out: |
| 628 | return rc; | 626 | return rc; |
| 629 | } | 627 | } |
| 628 | EXPORT_SYMBOL_GPL(ufshcd_hold); | ||
| 630 | 629 | ||
| 631 | static void ufshcd_gate_work(struct work_struct *work) | 630 | static void ufshcd_gate_work(struct work_struct *work) |
| 632 | { | 631 | { |
| @@ -714,6 +713,7 @@ void ufshcd_release(struct ufs_hba *hba) | |||
| 714 | __ufshcd_release(hba); | 713 | __ufshcd_release(hba); |
| 715 | spin_unlock_irqrestore(hba->host->host_lock, flags); | 714 | spin_unlock_irqrestore(hba->host->host_lock, flags); |
| 716 | } | 715 | } |
| 716 | EXPORT_SYMBOL_GPL(ufshcd_release); | ||
| 717 | 717 | ||
| 718 | static ssize_t ufshcd_clkgate_delay_show(struct device *dev, | 718 | static ssize_t ufshcd_clkgate_delay_show(struct device *dev, |
| 719 | struct device_attribute *attr, char *buf) | 719 | struct device_attribute *attr, char *buf) |
| @@ -2473,9 +2473,8 @@ static int ufshcd_change_power_mode(struct ufs_hba *hba, | |||
| 2473 | dev_err(hba->dev, | 2473 | dev_err(hba->dev, |
| 2474 | "%s: power mode change failed %d\n", __func__, ret); | 2474 | "%s: power mode change failed %d\n", __func__, ret); |
| 2475 | } else { | 2475 | } else { |
| 2476 | if (hba->vops && hba->vops->pwr_change_notify) | 2476 | ufshcd_vops_pwr_change_notify(hba, POST_CHANGE, NULL, |
| 2477 | hba->vops->pwr_change_notify(hba, | 2477 | pwr_mode); |
| 2478 | POST_CHANGE, NULL, pwr_mode); | ||
| 2479 | 2478 | ||
| 2480 | memcpy(&hba->pwr_info, pwr_mode, | 2479 | memcpy(&hba->pwr_info, pwr_mode, |
| 2481 | sizeof(struct ufs_pa_layer_attr)); | 2480 | sizeof(struct ufs_pa_layer_attr)); |
| @@ -2495,10 +2494,10 @@ static int ufshcd_config_pwr_mode(struct ufs_hba *hba, | |||
| 2495 | struct ufs_pa_layer_attr final_params = { 0 }; | 2494 | struct ufs_pa_layer_attr final_params = { 0 }; |
| 2496 | int ret; | 2495 | int ret; |
| 2497 | 2496 | ||
| 2498 | if (hba->vops && hba->vops->pwr_change_notify) | 2497 | ret = ufshcd_vops_pwr_change_notify(hba, PRE_CHANGE, |
| 2499 | hba->vops->pwr_change_notify(hba, | 2498 | desired_pwr_mode, &final_params); |
| 2500 | PRE_CHANGE, desired_pwr_mode, &final_params); | 2499 | |
| 2501 | else | 2500 | if (ret) |
| 2502 | memcpy(&final_params, desired_pwr_mode, sizeof(final_params)); | 2501 | memcpy(&final_params, desired_pwr_mode, sizeof(final_params)); |
| 2503 | 2502 | ||
| 2504 | ret = ufshcd_change_power_mode(hba, &final_params); | 2503 | ret = ufshcd_change_power_mode(hba, &final_params); |
| @@ -2647,8 +2646,7 @@ static int ufshcd_hba_enable(struct ufs_hba *hba) | |||
| 2647 | /* UniPro link is disabled at this point */ | 2646 | /* UniPro link is disabled at this point */ |
| 2648 | ufshcd_set_link_off(hba); | 2647 | ufshcd_set_link_off(hba); |
| 2649 | 2648 | ||
| 2650 | if (hba->vops && hba->vops->hce_enable_notify) | 2649 | ufshcd_vops_hce_enable_notify(hba, PRE_CHANGE); |
| 2651 | hba->vops->hce_enable_notify(hba, PRE_CHANGE); | ||
| 2652 | 2650 | ||
| 2653 | /* start controller initialization sequence */ | 2651 | /* start controller initialization sequence */ |
| 2654 | ufshcd_hba_start(hba); | 2652 | ufshcd_hba_start(hba); |
| @@ -2681,8 +2679,7 @@ static int ufshcd_hba_enable(struct ufs_hba *hba) | |||
| 2681 | /* enable UIC related interrupts */ | 2679 | /* enable UIC related interrupts */ |
| 2682 | ufshcd_enable_intr(hba, UFSHCD_UIC_MASK); | 2680 | ufshcd_enable_intr(hba, UFSHCD_UIC_MASK); |
| 2683 | 2681 | ||
| 2684 | if (hba->vops && hba->vops->hce_enable_notify) | 2682 | ufshcd_vops_hce_enable_notify(hba, POST_CHANGE); |
| 2685 | hba->vops->hce_enable_notify(hba, POST_CHANGE); | ||
| 2686 | 2683 | ||
| 2687 | return 0; | 2684 | return 0; |
| 2688 | } | 2685 | } |
| @@ -2735,8 +2732,7 @@ static int ufshcd_link_startup(struct ufs_hba *hba) | |||
| 2735 | int retries = DME_LINKSTARTUP_RETRIES; | 2732 | int retries = DME_LINKSTARTUP_RETRIES; |
| 2736 | 2733 | ||
| 2737 | do { | 2734 | do { |
| 2738 | if (hba->vops && hba->vops->link_startup_notify) | 2735 | ufshcd_vops_link_startup_notify(hba, PRE_CHANGE); |
| 2739 | hba->vops->link_startup_notify(hba, PRE_CHANGE); | ||
| 2740 | 2736 | ||
| 2741 | ret = ufshcd_dme_link_startup(hba); | 2737 | ret = ufshcd_dme_link_startup(hba); |
| 2742 | 2738 | ||
| @@ -2767,11 +2763,9 @@ static int ufshcd_link_startup(struct ufs_hba *hba) | |||
| 2767 | } | 2763 | } |
| 2768 | 2764 | ||
| 2769 | /* Include any host controller configuration via UIC commands */ | 2765 | /* Include any host controller configuration via UIC commands */ |
| 2770 | if (hba->vops && hba->vops->link_startup_notify) { | 2766 | ret = ufshcd_vops_link_startup_notify(hba, POST_CHANGE); |
| 2771 | ret = hba->vops->link_startup_notify(hba, POST_CHANGE); | 2767 | if (ret) |
| 2772 | if (ret) | 2768 | goto out; |
| 2773 | goto out; | ||
| 2774 | } | ||
| 2775 | 2769 | ||
| 2776 | ret = ufshcd_make_hba_operational(hba); | 2770 | ret = ufshcd_make_hba_operational(hba); |
| 2777 | out: | 2771 | out: |
| @@ -4577,8 +4571,7 @@ static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on, | |||
| 4577 | } | 4571 | } |
| 4578 | } | 4572 | } |
| 4579 | 4573 | ||
| 4580 | if (hba->vops && hba->vops->setup_clocks) | 4574 | ret = ufshcd_vops_setup_clocks(hba, on); |
| 4581 | ret = hba->vops->setup_clocks(hba, on); | ||
| 4582 | out: | 4575 | out: |
| 4583 | if (ret) { | 4576 | if (ret) { |
| 4584 | list_for_each_entry(clki, head, list) { | 4577 | list_for_each_entry(clki, head, list) { |
| @@ -4644,27 +4637,22 @@ static int ufshcd_variant_hba_init(struct ufs_hba *hba) | |||
| 4644 | if (!hba->vops) | 4637 | if (!hba->vops) |
| 4645 | goto out; | 4638 | goto out; |
| 4646 | 4639 | ||
| 4647 | if (hba->vops->init) { | 4640 | err = ufshcd_vops_init(hba); |
| 4648 | err = hba->vops->init(hba); | 4641 | if (err) |
| 4649 | if (err) | 4642 | goto out; |
| 4650 | goto out; | ||
| 4651 | } | ||
| 4652 | 4643 | ||
| 4653 | if (hba->vops->setup_regulators) { | 4644 | err = ufshcd_vops_setup_regulators(hba, true); |
| 4654 | err = hba->vops->setup_regulators(hba, true); | 4645 | if (err) |
| 4655 | if (err) | 4646 | goto out_exit; |
| 4656 | goto out_exit; | ||
| 4657 | } | ||
| 4658 | 4647 | ||
| 4659 | goto out; | 4648 | goto out; |
| 4660 | 4649 | ||
| 4661 | out_exit: | 4650 | out_exit: |
| 4662 | if (hba->vops->exit) | 4651 | ufshcd_vops_exit(hba); |
| 4663 | hba->vops->exit(hba); | ||
| 4664 | out: | 4652 | out: |
| 4665 | if (err) | 4653 | if (err) |
| 4666 | dev_err(hba->dev, "%s: variant %s init failed err %d\n", | 4654 | dev_err(hba->dev, "%s: variant %s init failed err %d\n", |
| 4667 | __func__, hba->vops ? hba->vops->name : "", err); | 4655 | __func__, ufshcd_get_var_name(hba), err); |
| 4668 | return err; | 4656 | return err; |
| 4669 | } | 4657 | } |
| 4670 | 4658 | ||
| @@ -4673,14 +4661,11 @@ static void ufshcd_variant_hba_exit(struct ufs_hba *hba) | |||
| 4673 | if (!hba->vops) | 4661 | if (!hba->vops) |
| 4674 | return; | 4662 | return; |
| 4675 | 4663 | ||
| 4676 | if (hba->vops->setup_clocks) | 4664 | ufshcd_vops_setup_clocks(hba, false); |
| 4677 | hba->vops->setup_clocks(hba, false); | ||
| 4678 | 4665 | ||
| 4679 | if (hba->vops->setup_regulators) | 4666 | ufshcd_vops_setup_regulators(hba, false); |
| 4680 | hba->vops->setup_regulators(hba, false); | ||
| 4681 | 4667 | ||
| 4682 | if (hba->vops->exit) | 4668 | ufshcd_vops_exit(hba); |
| 4683 | hba->vops->exit(hba); | ||
| 4684 | } | 4669 | } |
| 4685 | 4670 | ||
| 4686 | static int ufshcd_hba_init(struct ufs_hba *hba) | 4671 | static int ufshcd_hba_init(struct ufs_hba *hba) |
| @@ -5057,17 +5042,13 @@ disable_clks: | |||
| 5057 | * vendor specific host controller register space call them before the | 5042 | * vendor specific host controller register space call them before the |
| 5058 | * host clocks are ON. | 5043 | * host clocks are ON. |
| 5059 | */ | 5044 | */ |
| 5060 | if (hba->vops && hba->vops->suspend) { | 5045 | ret = ufshcd_vops_suspend(hba, pm_op); |
| 5061 | ret = hba->vops->suspend(hba, pm_op); | 5046 | if (ret) |
| 5062 | if (ret) | 5047 | goto set_link_active; |
| 5063 | goto set_link_active; | ||
| 5064 | } | ||
| 5065 | 5048 | ||
| 5066 | if (hba->vops && hba->vops->setup_clocks) { | 5049 | ret = ufshcd_vops_setup_clocks(hba, false); |
| 5067 | ret = hba->vops->setup_clocks(hba, false); | 5050 | if (ret) |
| 5068 | if (ret) | 5051 | goto vops_resume; |
| 5069 | goto vops_resume; | ||
| 5070 | } | ||
| 5071 | 5052 | ||
| 5072 | if (!ufshcd_is_link_active(hba)) | 5053 | if (!ufshcd_is_link_active(hba)) |
| 5073 | ufshcd_setup_clocks(hba, false); | 5054 | ufshcd_setup_clocks(hba, false); |
| @@ -5078,7 +5059,7 @@ disable_clks: | |||
| 5078 | hba->clk_gating.state = CLKS_OFF; | 5059 | hba->clk_gating.state = CLKS_OFF; |
| 5079 | /* | 5060 | /* |
| 5080 | * Disable the host irq as host controller as there won't be any | 5061 | * Disable the host irq as host controller as there won't be any |
| 5081 | * host controller trasanction expected till resume. | 5062 | * host controller transaction expected till resume. |
| 5082 | */ | 5063 | */ |
| 5083 | ufshcd_disable_irq(hba); | 5064 | ufshcd_disable_irq(hba); |
| 5084 | /* Put the host controller in low power mode if possible */ | 5065 | /* Put the host controller in low power mode if possible */ |
| @@ -5086,8 +5067,7 @@ disable_clks: | |||
| 5086 | goto out; | 5067 | goto out; |
| 5087 | 5068 | ||
| 5088 | vops_resume: | 5069 | vops_resume: |
| 5089 | if (hba->vops && hba->vops->resume) | 5070 | ufshcd_vops_resume(hba, pm_op); |
| 5090 | hba->vops->resume(hba, pm_op); | ||
| 5091 | set_link_active: | 5071 | set_link_active: |
| 5092 | ufshcd_vreg_set_hpm(hba); | 5072 | ufshcd_vreg_set_hpm(hba); |
| 5093 | if (ufshcd_is_link_hibern8(hba) && !ufshcd_uic_hibern8_exit(hba)) | 5073 | if (ufshcd_is_link_hibern8(hba) && !ufshcd_uic_hibern8_exit(hba)) |
| @@ -5143,11 +5123,9 @@ static int ufshcd_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) | |||
| 5143 | * vendor specific host controller register space call them when the | 5123 | * vendor specific host controller register space call them when the |
| 5144 | * host clocks are ON. | 5124 | * host clocks are ON. |
| 5145 | */ | 5125 | */ |
| 5146 | if (hba->vops && hba->vops->resume) { | 5126 | ret = ufshcd_vops_resume(hba, pm_op); |
| 5147 | ret = hba->vops->resume(hba, pm_op); | 5127 | if (ret) |
| 5148 | if (ret) | 5128 | goto disable_vreg; |
| 5149 | goto disable_vreg; | ||
| 5150 | } | ||
| 5151 | 5129 | ||
| 5152 | if (ufshcd_is_link_hibern8(hba)) { | 5130 | if (ufshcd_is_link_hibern8(hba)) { |
| 5153 | ret = ufshcd_uic_hibern8_exit(hba); | 5131 | ret = ufshcd_uic_hibern8_exit(hba); |
| @@ -5188,8 +5166,7 @@ static int ufshcd_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) | |||
| 5188 | set_old_link_state: | 5166 | set_old_link_state: |
| 5189 | ufshcd_link_state_transition(hba, old_link_state, 0); | 5167 | ufshcd_link_state_transition(hba, old_link_state, 0); |
| 5190 | vendor_suspend: | 5168 | vendor_suspend: |
| 5191 | if (hba->vops && hba->vops->suspend) | 5169 | ufshcd_vops_suspend(hba, pm_op); |
| 5192 | hba->vops->suspend(hba, pm_op); | ||
| 5193 | disable_vreg: | 5170 | disable_vreg: |
| 5194 | ufshcd_vreg_set_lpm(hba); | 5171 | ufshcd_vreg_set_lpm(hba); |
| 5195 | disable_irq_and_vops_clks: | 5172 | disable_irq_and_vops_clks: |
| @@ -5372,6 +5349,16 @@ void ufshcd_remove(struct ufs_hba *hba) | |||
| 5372 | EXPORT_SYMBOL_GPL(ufshcd_remove); | 5349 | EXPORT_SYMBOL_GPL(ufshcd_remove); |
| 5373 | 5350 | ||
| 5374 | /** | 5351 | /** |
| 5352 | * ufshcd_dealloc_host - deallocate Host Bus Adapter (HBA) | ||
| 5353 | * @hba: pointer to Host Bus Adapter (HBA) | ||
| 5354 | */ | ||
| 5355 | void ufshcd_dealloc_host(struct ufs_hba *hba) | ||
| 5356 | { | ||
| 5357 | scsi_host_put(hba->host); | ||
| 5358 | } | ||
| 5359 | EXPORT_SYMBOL_GPL(ufshcd_dealloc_host); | ||
| 5360 | |||
| 5361 | /** | ||
| 5375 | * ufshcd_set_dma_mask - Set dma mask based on the controller | 5362 | * ufshcd_set_dma_mask - Set dma mask based on the controller |
| 5376 | * addressing capability | 5363 | * addressing capability |
| 5377 | * @hba: per adapter instance | 5364 | * @hba: per adapter instance |
| @@ -5432,6 +5419,10 @@ static int ufshcd_scale_clks(struct ufs_hba *hba, bool scale_up) | |||
| 5432 | if (!head || list_empty(head)) | 5419 | if (!head || list_empty(head)) |
| 5433 | goto out; | 5420 | goto out; |
| 5434 | 5421 | ||
| 5422 | ret = ufshcd_vops_clk_scale_notify(hba, scale_up, PRE_CHANGE); | ||
| 5423 | if (ret) | ||
| 5424 | return ret; | ||
| 5425 | |||
| 5435 | list_for_each_entry(clki, head, list) { | 5426 | list_for_each_entry(clki, head, list) { |
| 5436 | if (!IS_ERR_OR_NULL(clki->clk)) { | 5427 | if (!IS_ERR_OR_NULL(clki->clk)) { |
| 5437 | if (scale_up && clki->max_freq) { | 5428 | if (scale_up && clki->max_freq) { |
| @@ -5462,8 +5453,9 @@ static int ufshcd_scale_clks(struct ufs_hba *hba, bool scale_up) | |||
| 5462 | dev_dbg(hba->dev, "%s: clk: %s, rate: %lu\n", __func__, | 5453 | dev_dbg(hba->dev, "%s: clk: %s, rate: %lu\n", __func__, |
| 5463 | clki->name, clk_get_rate(clki->clk)); | 5454 | clki->name, clk_get_rate(clki->clk)); |
| 5464 | } | 5455 | } |
| 5465 | if (hba->vops->clk_scale_notify) | 5456 | |
| 5466 | hba->vops->clk_scale_notify(hba); | 5457 | ret = ufshcd_vops_clk_scale_notify(hba, scale_up, POST_CHANGE); |
| 5458 | |||
| 5467 | out: | 5459 | out: |
| 5468 | return ret; | 5460 | return ret; |
| 5469 | } | 5461 | } |
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index c40a0e78a6c4..2570d9477b37 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h | |||
| @@ -223,8 +223,10 @@ struct ufs_clk_info { | |||
| 223 | bool enabled; | 223 | bool enabled; |
| 224 | }; | 224 | }; |
| 225 | 225 | ||
| 226 | #define PRE_CHANGE 0 | 226 | enum ufs_notify_change_status { |
| 227 | #define POST_CHANGE 1 | 227 | PRE_CHANGE, |
| 228 | POST_CHANGE, | ||
| 229 | }; | ||
| 228 | 230 | ||
| 229 | struct ufs_pa_layer_attr { | 231 | struct ufs_pa_layer_attr { |
| 230 | u32 gear_rx; | 232 | u32 gear_rx; |
| @@ -259,22 +261,28 @@ struct ufs_pwr_mode_info { | |||
| 259 | * to be set. | 261 | * to be set. |
| 260 | * @suspend: called during host controller PM callback | 262 | * @suspend: called during host controller PM callback |
| 261 | * @resume: called during host controller PM callback | 263 | * @resume: called during host controller PM callback |
| 264 | * @dbg_register_dump: used to dump controller debug information | ||
| 262 | */ | 265 | */ |
| 263 | struct ufs_hba_variant_ops { | 266 | struct ufs_hba_variant_ops { |
| 264 | const char *name; | 267 | const char *name; |
| 265 | int (*init)(struct ufs_hba *); | 268 | int (*init)(struct ufs_hba *); |
| 266 | void (*exit)(struct ufs_hba *); | 269 | void (*exit)(struct ufs_hba *); |
| 267 | u32 (*get_ufs_hci_version)(struct ufs_hba *); | 270 | u32 (*get_ufs_hci_version)(struct ufs_hba *); |
| 268 | void (*clk_scale_notify)(struct ufs_hba *); | 271 | int (*clk_scale_notify)(struct ufs_hba *, bool, |
| 269 | int (*setup_clocks)(struct ufs_hba *, bool); | 272 | enum ufs_notify_change_status); |
| 273 | int (*setup_clocks)(struct ufs_hba *, bool); | ||
| 270 | int (*setup_regulators)(struct ufs_hba *, bool); | 274 | int (*setup_regulators)(struct ufs_hba *, bool); |
| 271 | int (*hce_enable_notify)(struct ufs_hba *, bool); | 275 | int (*hce_enable_notify)(struct ufs_hba *, |
| 272 | int (*link_startup_notify)(struct ufs_hba *, bool); | 276 | enum ufs_notify_change_status); |
| 277 | int (*link_startup_notify)(struct ufs_hba *, | ||
| 278 | enum ufs_notify_change_status); | ||
| 273 | int (*pwr_change_notify)(struct ufs_hba *, | 279 | int (*pwr_change_notify)(struct ufs_hba *, |
| 274 | bool, struct ufs_pa_layer_attr *, | 280 | enum ufs_notify_change_status status, |
| 281 | struct ufs_pa_layer_attr *, | ||
| 275 | struct ufs_pa_layer_attr *); | 282 | struct ufs_pa_layer_attr *); |
| 276 | int (*suspend)(struct ufs_hba *, enum ufs_pm_op); | 283 | int (*suspend)(struct ufs_hba *, enum ufs_pm_op); |
| 277 | int (*resume)(struct ufs_hba *, enum ufs_pm_op); | 284 | int (*resume)(struct ufs_hba *, enum ufs_pm_op); |
| 285 | void (*dbg_register_dump)(struct ufs_hba *hba); | ||
| 278 | }; | 286 | }; |
| 279 | 287 | ||
| 280 | /* clock gating state */ | 288 | /* clock gating state */ |
| @@ -576,6 +584,7 @@ static inline void ufshcd_rmwl(struct ufs_hba *hba, u32 mask, u32 val, u32 reg) | |||
| 576 | } | 584 | } |
| 577 | 585 | ||
| 578 | int ufshcd_alloc_host(struct device *, struct ufs_hba **); | 586 | int ufshcd_alloc_host(struct device *, struct ufs_hba **); |
| 587 | void ufshcd_dealloc_host(struct ufs_hba *); | ||
| 579 | int ufshcd_init(struct ufs_hba * , void __iomem * , unsigned int); | 588 | int ufshcd_init(struct ufs_hba * , void __iomem * , unsigned int); |
| 580 | void ufshcd_remove(struct ufs_hba *); | 589 | void ufshcd_remove(struct ufs_hba *); |
| 581 | 590 | ||
| @@ -594,6 +603,27 @@ static inline void check_upiu_size(void) | |||
| 594 | GENERAL_UPIU_REQUEST_SIZE + QUERY_DESC_MAX_SIZE); | 603 | GENERAL_UPIU_REQUEST_SIZE + QUERY_DESC_MAX_SIZE); |
| 595 | } | 604 | } |
| 596 | 605 | ||
| 606 | /** | ||
| 607 | * ufshcd_set_variant - set variant specific data to the hba | ||
| 608 | * @hba - per adapter instance | ||
| 609 | * @variant - pointer to variant specific data | ||
| 610 | */ | ||
| 611 | static inline void ufshcd_set_variant(struct ufs_hba *hba, void *variant) | ||
| 612 | { | ||
| 613 | BUG_ON(!hba); | ||
| 614 | hba->priv = variant; | ||
| 615 | } | ||
| 616 | |||
| 617 | /** | ||
| 618 | * ufshcd_get_variant - get variant specific data from the hba | ||
| 619 | * @hba - per adapter instance | ||
| 620 | */ | ||
| 621 | static inline void *ufshcd_get_variant(struct ufs_hba *hba) | ||
| 622 | { | ||
| 623 | BUG_ON(!hba); | ||
| 624 | return hba->priv; | ||
| 625 | } | ||
| 626 | |||
| 597 | extern int ufshcd_runtime_suspend(struct ufs_hba *hba); | 627 | extern int ufshcd_runtime_suspend(struct ufs_hba *hba); |
| 598 | extern int ufshcd_runtime_resume(struct ufs_hba *hba); | 628 | extern int ufshcd_runtime_resume(struct ufs_hba *hba); |
| 599 | extern int ufshcd_runtime_idle(struct ufs_hba *hba); | 629 | extern int ufshcd_runtime_idle(struct ufs_hba *hba); |
| @@ -653,4 +683,109 @@ static inline int ufshcd_dme_peer_get(struct ufs_hba *hba, | |||
| 653 | 683 | ||
| 654 | int ufshcd_hold(struct ufs_hba *hba, bool async); | 684 | int ufshcd_hold(struct ufs_hba *hba, bool async); |
| 655 | void ufshcd_release(struct ufs_hba *hba); | 685 | void ufshcd_release(struct ufs_hba *hba); |
| 686 | |||
| 687 | /* Wrapper functions for safely calling variant operations */ | ||
| 688 | static inline const char *ufshcd_get_var_name(struct ufs_hba *hba) | ||
| 689 | { | ||
| 690 | if (hba->vops) | ||
| 691 | return hba->vops->name; | ||
| 692 | return ""; | ||
| 693 | } | ||
| 694 | |||
| 695 | static inline int ufshcd_vops_init(struct ufs_hba *hba) | ||
| 696 | { | ||
| 697 | if (hba->vops && hba->vops->init) | ||
| 698 | return hba->vops->init(hba); | ||
| 699 | |||
| 700 | return 0; | ||
| 701 | } | ||
| 702 | |||
| 703 | static inline void ufshcd_vops_exit(struct ufs_hba *hba) | ||
| 704 | { | ||
| 705 | if (hba->vops && hba->vops->exit) | ||
| 706 | return hba->vops->exit(hba); | ||
| 707 | } | ||
| 708 | |||
| 709 | static inline u32 ufshcd_vops_get_ufs_hci_version(struct ufs_hba *hba) | ||
| 710 | { | ||
| 711 | if (hba->vops && hba->vops->get_ufs_hci_version) | ||
| 712 | return hba->vops->get_ufs_hci_version(hba); | ||
| 713 | |||
| 714 | return ufshcd_readl(hba, REG_UFS_VERSION); | ||
| 715 | } | ||
| 716 | |||
| 717 | static inline int ufshcd_vops_clk_scale_notify(struct ufs_hba *hba, | ||
| 718 | bool up, enum ufs_notify_change_status status) | ||
| 719 | { | ||
| 720 | if (hba->vops && hba->vops->clk_scale_notify) | ||
| 721 | return hba->vops->clk_scale_notify(hba, up, status); | ||
| 722 | return 0; | ||
| 723 | } | ||
| 724 | |||
| 725 | static inline int ufshcd_vops_setup_clocks(struct ufs_hba *hba, bool on) | ||
| 726 | { | ||
| 727 | if (hba->vops && hba->vops->setup_clocks) | ||
| 728 | return hba->vops->setup_clocks(hba, on); | ||
| 729 | return 0; | ||
| 730 | } | ||
| 731 | |||
| 732 | static inline int ufshcd_vops_setup_regulators(struct ufs_hba *hba, bool status) | ||
| 733 | { | ||
| 734 | if (hba->vops && hba->vops->setup_regulators) | ||
| 735 | return hba->vops->setup_regulators(hba, status); | ||
| 736 | |||
| 737 | return 0; | ||
| 738 | } | ||
| 739 | |||
| 740 | static inline int ufshcd_vops_hce_enable_notify(struct ufs_hba *hba, | ||
| 741 | bool status) | ||
| 742 | { | ||
| 743 | if (hba->vops && hba->vops->hce_enable_notify) | ||
| 744 | return hba->vops->hce_enable_notify(hba, status); | ||
| 745 | |||
| 746 | return 0; | ||
| 747 | } | ||
| 748 | static inline int ufshcd_vops_link_startup_notify(struct ufs_hba *hba, | ||
| 749 | bool status) | ||
| 750 | { | ||
| 751 | if (hba->vops && hba->vops->link_startup_notify) | ||
| 752 | return hba->vops->link_startup_notify(hba, status); | ||
| 753 | |||
| 754 | return 0; | ||
| 755 | } | ||
| 756 | |||
| 757 | static inline int ufshcd_vops_pwr_change_notify(struct ufs_hba *hba, | ||
| 758 | bool status, | ||
| 759 | struct ufs_pa_layer_attr *dev_max_params, | ||
| 760 | struct ufs_pa_layer_attr *dev_req_params) | ||
| 761 | { | ||
| 762 | if (hba->vops && hba->vops->pwr_change_notify) | ||
| 763 | return hba->vops->pwr_change_notify(hba, status, | ||
| 764 | dev_max_params, dev_req_params); | ||
| 765 | |||
| 766 | return -ENOTSUPP; | ||
| 767 | } | ||
| 768 | |||
| 769 | static inline int ufshcd_vops_suspend(struct ufs_hba *hba, enum ufs_pm_op op) | ||
| 770 | { | ||
| 771 | if (hba->vops && hba->vops->suspend) | ||
| 772 | return hba->vops->suspend(hba, op); | ||
| 773 | |||
| 774 | return 0; | ||
| 775 | } | ||
| 776 | |||
| 777 | static inline int ufshcd_vops_resume(struct ufs_hba *hba, enum ufs_pm_op op) | ||
| 778 | { | ||
| 779 | if (hba->vops && hba->vops->resume) | ||
| 780 | return hba->vops->resume(hba, op); | ||
| 781 | |||
| 782 | return 0; | ||
| 783 | } | ||
| 784 | |||
| 785 | static inline void ufshcd_vops_dbg_register_dump(struct ufs_hba *hba) | ||
| 786 | { | ||
| 787 | if (hba->vops && hba->vops->dbg_register_dump) | ||
| 788 | hba->vops->dbg_register_dump(hba); | ||
| 789 | } | ||
| 790 | |||
| 656 | #endif /* End of Header */ | 791 | #endif /* End of Header */ |
