aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorDave Jiang <dave.jiang@intel.com>2012-01-04 04:32:44 -0500
committerJames Bottomley <JBottomley@Parallels.com>2012-01-16 02:42:00 -0500
commit594e566ae5985e0cc3185ac21509a86e90aad577 (patch)
treef53db9f48084fea7c553077e60e03e7cd130c21a /drivers/scsi
parentafd13a1f2b05157c7621d87dfe89ea6ea9061bd8 (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.c47
-rw-r--r--drivers/scsi/isci/init.c3
-rw-r--r--drivers/scsi/isci/phy.c51
-rw-r--r--drivers/scsi/isci/probe_roms.h53
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
1762int sci_oem_parameters_validate(struct sci_oem_params *oem) 1762int 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
1797static enum sci_status sci_oem_parameters_set(struct isci_host *ihost) 1838static 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
154struct sci_oem_params; 154struct sci_oem_params;
155int sci_oem_parameters_validate(struct sci_oem_params *oem); 155int sci_oem_parameters_validate(struct sci_oem_params *oem, u8 version);
156 156
157struct isci_orom; 157struct isci_orom;
158struct isci_orom *isci_request_oprom(struct pci_dev *pdev); 158struct 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