diff options
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 */ |