diff options
author | Dave Jiang <dave.jiang@intel.com> | 2012-01-04 04:32:44 -0500 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-01-16 02:42:00 -0500 |
commit | 594e566ae5985e0cc3185ac21509a86e90aad577 (patch) | |
tree | f53db9f48084fea7c553077e60e03e7cd130c21a /drivers/scsi | |
parent | afd13a1f2b05157c7621d87dfe89ea6ea9061bd8 (diff) |
[SCSI] isci: oem parameter format v1.1 (ssc select)
v1.1 allows finer grained tuning of the SSC (spread-spectrum-clocking)
settings for SAS and SATA. See notes in probe_roms.h
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/isci/host.c | 47 | ||||
-rw-r--r-- | drivers/scsi/isci/init.c | 3 | ||||
-rw-r--r-- | drivers/scsi/isci/phy.c | 51 | ||||
-rw-r--r-- | drivers/scsi/isci/probe_roms.h | 53 |
4 files changed, 148 insertions, 6 deletions
diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 383bb6913087..ed1441c89577 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c | |||
@@ -1759,7 +1759,7 @@ static enum sci_status sci_controller_construct(struct isci_host *ihost, | |||
1759 | return sci_controller_reset(ihost); | 1759 | return sci_controller_reset(ihost); |
1760 | } | 1760 | } |
1761 | 1761 | ||
1762 | int sci_oem_parameters_validate(struct sci_oem_params *oem) | 1762 | int sci_oem_parameters_validate(struct sci_oem_params *oem, u8 version) |
1763 | { | 1763 | { |
1764 | int i; | 1764 | int i; |
1765 | 1765 | ||
@@ -1791,18 +1791,61 @@ int sci_oem_parameters_validate(struct sci_oem_params *oem) | |||
1791 | oem->controller.max_concurr_spin_up < 1) | 1791 | oem->controller.max_concurr_spin_up < 1) |
1792 | return -EINVAL; | 1792 | return -EINVAL; |
1793 | 1793 | ||
1794 | if (oem->controller.do_enable_ssc) { | ||
1795 | if (version < ISCI_ROM_VER_1_1 && oem->controller.do_enable_ssc != 1) | ||
1796 | return -EINVAL; | ||
1797 | |||
1798 | if (version >= ISCI_ROM_VER_1_1) { | ||
1799 | u8 test = oem->controller.ssc_sata_tx_spread_level; | ||
1800 | |||
1801 | switch (test) { | ||
1802 | case 0: | ||
1803 | case 2: | ||
1804 | case 3: | ||
1805 | case 6: | ||
1806 | case 7: | ||
1807 | break; | ||
1808 | default: | ||
1809 | return -EINVAL; | ||
1810 | } | ||
1811 | |||
1812 | test = oem->controller.ssc_sas_tx_spread_level; | ||
1813 | if (oem->controller.ssc_sas_tx_type == 0) { | ||
1814 | switch (test) { | ||
1815 | case 0: | ||
1816 | case 2: | ||
1817 | case 3: | ||
1818 | break; | ||
1819 | default: | ||
1820 | return -EINVAL; | ||
1821 | } | ||
1822 | } else if (oem->controller.ssc_sas_tx_type == 1) { | ||
1823 | switch (test) { | ||
1824 | case 0: | ||
1825 | case 3: | ||
1826 | case 6: | ||
1827 | break; | ||
1828 | default: | ||
1829 | return -EINVAL; | ||
1830 | } | ||
1831 | } | ||
1832 | } | ||
1833 | } | ||
1834 | |||
1794 | return 0; | 1835 | return 0; |
1795 | } | 1836 | } |
1796 | 1837 | ||
1797 | static enum sci_status sci_oem_parameters_set(struct isci_host *ihost) | 1838 | static enum sci_status sci_oem_parameters_set(struct isci_host *ihost) |
1798 | { | 1839 | { |
1799 | u32 state = ihost->sm.current_state_id; | 1840 | u32 state = ihost->sm.current_state_id; |
1841 | struct isci_pci_info *pci_info = to_pci_info(ihost->pdev); | ||
1800 | 1842 | ||
1801 | if (state == SCIC_RESET || | 1843 | if (state == SCIC_RESET || |
1802 | state == SCIC_INITIALIZING || | 1844 | state == SCIC_INITIALIZING || |
1803 | state == SCIC_INITIALIZED) { | 1845 | state == SCIC_INITIALIZED) { |
1804 | 1846 | ||
1805 | if (sci_oem_parameters_validate(&ihost->oem_parameters)) | 1847 | if (sci_oem_parameters_validate(&ihost->oem_parameters, |
1848 | pci_info->orom->hdr.version)) | ||
1806 | return SCI_FAILURE_INVALID_PARAMETER_VALUE; | 1849 | return SCI_FAILURE_INVALID_PARAMETER_VALUE; |
1807 | 1850 | ||
1808 | return SCI_SUCCESS; | 1851 | return SCI_SUCCESS; |
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index a97edabcb85a..8a34fd92e42e 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c | |||
@@ -466,7 +466,8 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic | |||
466 | orom = isci_request_oprom(pdev); | 466 | orom = isci_request_oprom(pdev); |
467 | 467 | ||
468 | for (i = 0; orom && i < ARRAY_SIZE(orom->ctrl); i++) { | 468 | for (i = 0; orom && i < ARRAY_SIZE(orom->ctrl); i++) { |
469 | if (sci_oem_parameters_validate(&orom->ctrl[i])) { | 469 | if (sci_oem_parameters_validate(&orom->ctrl[i], |
470 | orom->hdr.version)) { | ||
470 | dev_warn(&pdev->dev, | 471 | dev_warn(&pdev->dev, |
471 | "[%d]: invalid oem parameters detected, falling back to firmware\n", i); | 472 | "[%d]: invalid oem parameters detected, falling back to firmware\n", i); |
472 | devm_kfree(&pdev->dev, orom); | 473 | devm_kfree(&pdev->dev, orom); |
diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index c650d3003c22..61000cde84c7 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c | |||
@@ -144,10 +144,59 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy, | |||
144 | phy_cap.gen3_no_ssc = 1; | 144 | phy_cap.gen3_no_ssc = 1; |
145 | phy_cap.gen2_no_ssc = 1; | 145 | phy_cap.gen2_no_ssc = 1; |
146 | phy_cap.gen1_no_ssc = 1; | 146 | phy_cap.gen1_no_ssc = 1; |
147 | if (ihost->oem_parameters.controller.do_enable_ssc == true) { | 147 | if (ihost->oem_parameters.controller.do_enable_ssc) { |
148 | struct scu_afe_registers __iomem *afe = &ihost->scu_registers->afe; | ||
149 | struct scu_afe_transceiver *xcvr = &afe->scu_afe_xcvr[phy_idx]; | ||
150 | struct isci_pci_info *pci_info = to_pci_info(ihost->pdev); | ||
151 | bool en_sas = false; | ||
152 | bool en_sata = false; | ||
153 | u32 sas_type = 0; | ||
154 | u32 sata_spread = 0x2; | ||
155 | u32 sas_spread = 0x2; | ||
156 | |||
148 | phy_cap.gen3_ssc = 1; | 157 | phy_cap.gen3_ssc = 1; |
149 | phy_cap.gen2_ssc = 1; | 158 | phy_cap.gen2_ssc = 1; |
150 | phy_cap.gen1_ssc = 1; | 159 | phy_cap.gen1_ssc = 1; |
160 | |||
161 | if (pci_info->orom->hdr.version < ISCI_ROM_VER_1_1) | ||
162 | en_sas = en_sata = true; | ||
163 | else { | ||
164 | sata_spread = ihost->oem_parameters.controller.ssc_sata_tx_spread_level; | ||
165 | sas_spread = ihost->oem_parameters.controller.ssc_sas_tx_spread_level; | ||
166 | |||
167 | if (sata_spread) | ||
168 | en_sata = true; | ||
169 | |||
170 | if (sas_spread) { | ||
171 | en_sas = true; | ||
172 | sas_type = ihost->oem_parameters.controller.ssc_sas_tx_type; | ||
173 | } | ||
174 | |||
175 | } | ||
176 | |||
177 | if (en_sas) { | ||
178 | u32 reg; | ||
179 | |||
180 | reg = readl(&xcvr->afe_xcvr_control0); | ||
181 | reg |= (0x00100000 | (sas_type << 19)); | ||
182 | writel(reg, &xcvr->afe_xcvr_control0); | ||
183 | |||
184 | reg = readl(&xcvr->afe_tx_ssc_control); | ||
185 | reg |= sas_spread << 8; | ||
186 | writel(reg, &xcvr->afe_tx_ssc_control); | ||
187 | } | ||
188 | |||
189 | if (en_sata) { | ||
190 | u32 reg; | ||
191 | |||
192 | reg = readl(&xcvr->afe_tx_ssc_control); | ||
193 | reg |= sata_spread; | ||
194 | writel(reg, &xcvr->afe_tx_ssc_control); | ||
195 | |||
196 | reg = readl(&llr->stp_control); | ||
197 | reg |= 1 << 12; | ||
198 | writel(reg, &llr->stp_control); | ||
199 | } | ||
151 | } | 200 | } |
152 | 201 | ||
153 | /* The SAS specification indicates that the phy_capabilities that | 202 | /* The SAS specification indicates that the phy_capabilities that |
diff --git a/drivers/scsi/isci/probe_roms.h b/drivers/scsi/isci/probe_roms.h index 2c75248ca326..42dd05414f3b 100644 --- a/drivers/scsi/isci/probe_roms.h +++ b/drivers/scsi/isci/probe_roms.h | |||
@@ -152,7 +152,7 @@ struct sci_user_parameters { | |||
152 | #define MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT 4 | 152 | #define MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT 4 |
153 | 153 | ||
154 | struct sci_oem_params; | 154 | struct sci_oem_params; |
155 | int sci_oem_parameters_validate(struct sci_oem_params *oem); | 155 | int sci_oem_parameters_validate(struct sci_oem_params *oem, u8 version); |
156 | 156 | ||
157 | struct isci_orom; | 157 | struct isci_orom; |
158 | struct isci_orom *isci_request_oprom(struct pci_dev *pdev); | 158 | struct isci_orom *isci_request_oprom(struct pci_dev *pdev); |
@@ -191,6 +191,10 @@ struct isci_oem_hdr { | |||
191 | 0x1a, 0x04, 0xc6) | 191 | 0x1a, 0x04, 0xc6) |
192 | #define ISCI_EFI_VAR_NAME "RstScuO" | 192 | #define ISCI_EFI_VAR_NAME "RstScuO" |
193 | 193 | ||
194 | #define ISCI_ROM_VER_1_0 0x10 | ||
195 | #define ISCI_ROM_VER_1_1 0x11 | ||
196 | #define ISCI_ROM_VER_LATEST ISCI_ROM_VER_1_1 | ||
197 | |||
194 | /* Allowed PORT configuration modes APC Automatic PORT configuration mode is | 198 | /* Allowed PORT configuration modes APC Automatic PORT configuration mode is |
195 | * defined by the OEM configuration parameters providing no PHY_MASK parameters | 199 | * defined by the OEM configuration parameters providing no PHY_MASK parameters |
196 | * for any PORT. i.e. There are no phys assigned to any of the ports at start. | 200 | * for any PORT. i.e. There are no phys assigned to any of the ports at start. |
@@ -220,7 +224,52 @@ struct sci_oem_params { | |||
220 | struct { | 224 | struct { |
221 | uint8_t mode_type; | 225 | uint8_t mode_type; |
222 | uint8_t max_concurr_spin_up; | 226 | uint8_t max_concurr_spin_up; |
223 | uint8_t do_enable_ssc; | 227 | /* |
228 | * This bitfield indicates the OEM's desired default Tx | ||
229 | * Spread Spectrum Clocking (SSC) settings for SATA and SAS. | ||
230 | * NOTE: Default SSC Modulation Frequency is 31.5KHz. | ||
231 | */ | ||
232 | union { | ||
233 | struct { | ||
234 | /* | ||
235 | * NOTE: Max spread for SATA is +0 / -5000 PPM. | ||
236 | * Down-spreading SSC (only method allowed for SATA): | ||
237 | * SATA SSC Tx Disabled = 0x0 | ||
238 | * SATA SSC Tx at +0 / -1419 PPM Spread = 0x2 | ||
239 | * SATA SSC Tx at +0 / -2129 PPM Spread = 0x3 | ||
240 | * SATA SSC Tx at +0 / -4257 PPM Spread = 0x6 | ||
241 | * SATA SSC Tx at +0 / -4967 PPM Spread = 0x7 | ||
242 | */ | ||
243 | uint8_t ssc_sata_tx_spread_level:4; | ||
244 | /* | ||
245 | * SAS SSC Tx Disabled = 0x0 | ||
246 | * | ||
247 | * NOTE: Max spread for SAS down-spreading +0 / | ||
248 | * -2300 PPM | ||
249 | * Down-spreading SSC: | ||
250 | * SAS SSC Tx at +0 / -1419 PPM Spread = 0x2 | ||
251 | * SAS SSC Tx at +0 / -2129 PPM Spread = 0x3 | ||
252 | * | ||
253 | * NOTE: Max spread for SAS center-spreading +2300 / | ||
254 | * -2300 PPM | ||
255 | * Center-spreading SSC: | ||
256 | * SAS SSC Tx at +1064 / -1064 PPM Spread = 0x3 | ||
257 | * SAS SSC Tx at +2129 / -2129 PPM Spread = 0x6 | ||
258 | */ | ||
259 | uint8_t ssc_sas_tx_spread_level:3; | ||
260 | /* | ||
261 | * NOTE: Refer to the SSC section of the SAS 2.x | ||
262 | * Specification for proper setting of this field. | ||
263 | * For standard SAS Initiator SAS PHY operation it | ||
264 | * should be 0 for Down-spreading. | ||
265 | * SAS SSC Tx spread type: | ||
266 | * Down-spreading SSC = 0 | ||
267 | * Center-spreading SSC = 1 | ||
268 | */ | ||
269 | uint8_t ssc_sas_tx_type:1; | ||
270 | }; | ||
271 | uint8_t do_enable_ssc; | ||
272 | }; | ||
224 | uint8_t reserved; | 273 | uint8_t reserved; |
225 | } controller; | 274 | } controller; |
226 | 275 | ||