aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/isci
diff options
context:
space:
mode:
authorJeff Skirvin <jeffrey.d.skirvin@intel.com>2012-01-04 04:32:49 -0500
committerJames Bottomley <JBottomley@Parallels.com>2012-01-16 02:43:04 -0500
commit9fee607f0b29adabd72265a847b8e421dff10d66 (patch)
tree7442c82b8e363a7aa1e87955e9619cf8e949cf3a /drivers/scsi/isci
parent594e566ae5985e0cc3185ac21509a86e90aad577 (diff)
[SCSI] isci: oem parameter format v1.3 (cable select)
v1.3 allows the attenuation of the attached cables to be specified to the driver in terms of 'short', 'medium', and 'long' (see probe_roms.h). These settings (per phy) are retrieved from the platform oem-parameters (BIOS rom) or via a module parameter override. Reviewed-by: Jiangbi Liu <jiangbi.liu@intel.com> Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin@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/isci')
-rw-r--r--drivers/scsi/isci/host.c43
-rw-r--r--drivers/scsi/isci/host.h18
-rw-r--r--drivers/scsi/isci/init.c16
-rw-r--r--drivers/scsi/isci/isci.h1
-rw-r--r--drivers/scsi/isci/probe_roms.h38
5 files changed, 111 insertions, 5 deletions
diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c
index ed1441c89577..9a52b984620f 100644
--- a/drivers/scsi/isci/host.c
+++ b/drivers/scsi/isci/host.c
@@ -1666,6 +1666,9 @@ static void sci_controller_set_default_config_parameters(struct isci_host *ihost
1666 /* Default to no SSC operation. */ 1666 /* Default to no SSC operation. */
1667 ihost->oem_parameters.controller.do_enable_ssc = false; 1667 ihost->oem_parameters.controller.do_enable_ssc = false;
1668 1668
1669 /* Default to short cables on all phys. */
1670 ihost->oem_parameters.controller.cable_selection_mask = 0;
1671
1669 /* Initialize all of the port parameter information to narrow ports. */ 1672 /* Initialize all of the port parameter information to narrow ports. */
1670 for (index = 0; index < SCI_MAX_PORTS; index++) { 1673 for (index = 0; index < SCI_MAX_PORTS; index++) {
1671 ihost->oem_parameters.ports[index].phy_mask = 0; 1674 ihost->oem_parameters.ports[index].phy_mask = 0;
@@ -1953,12 +1956,46 @@ void sci_controller_power_control_queue_remove(struct isci_host *ihost,
1953 1956
1954static int is_long_cable(int phy, unsigned char selection_byte) 1957static int is_long_cable(int phy, unsigned char selection_byte)
1955{ 1958{
1956 return 0; 1959 return !!(selection_byte & (1 << phy));
1957} 1960}
1958 1961
1959static int is_medium_cable(int phy, unsigned char selection_byte) 1962static int is_medium_cable(int phy, unsigned char selection_byte)
1960{ 1963{
1961 return 0; 1964 return !!(selection_byte & (1 << (phy + 4)));
1965}
1966
1967static enum cable_selections decode_selection_byte(
1968 int phy,
1969 unsigned char selection_byte)
1970{
1971 return ((selection_byte & (1 << phy)) ? 1 : 0)
1972 + (selection_byte & (1 << (phy + 4)) ? 2 : 0);
1973}
1974
1975static unsigned char *to_cable_select(struct isci_host *ihost)
1976{
1977 if (is_cable_select_overridden())
1978 return ((unsigned char *)&cable_selection_override)
1979 + ihost->id;
1980 else
1981 return &ihost->oem_parameters.controller.cable_selection_mask;
1982}
1983
1984enum cable_selections decode_cable_selection(struct isci_host *ihost, int phy)
1985{
1986 return decode_selection_byte(phy, *to_cable_select(ihost));
1987}
1988
1989char *lookup_cable_names(enum cable_selections selection)
1990{
1991 static char *cable_names[] = {
1992 [short_cable] = "short",
1993 [long_cable] = "long",
1994 [medium_cable] = "medium",
1995 [undefined_cable] = "<undefined, assumed long>" /* bit 0==1 */
1996 };
1997 return (selection <= undefined_cable) ? cable_names[selection]
1998 : cable_names[undefined_cable];
1962} 1999}
1963 2000
1964#define AFE_REGISTER_WRITE_DELAY 10 2001#define AFE_REGISTER_WRITE_DELAY 10
@@ -1967,10 +2004,10 @@ static void sci_controller_afe_initialization(struct isci_host *ihost)
1967{ 2004{
1968 struct scu_afe_registers __iomem *afe = &ihost->scu_registers->afe; 2005 struct scu_afe_registers __iomem *afe = &ihost->scu_registers->afe;
1969 const struct sci_oem_params *oem = &ihost->oem_parameters; 2006 const struct sci_oem_params *oem = &ihost->oem_parameters;
1970 unsigned char cable_selection_mask = 0;
1971 struct pci_dev *pdev = ihost->pdev; 2007 struct pci_dev *pdev = ihost->pdev;
1972 u32 afe_status; 2008 u32 afe_status;
1973 u32 phy_id; 2009 u32 phy_id;
2010 unsigned char cable_selection_mask = *to_cable_select(ihost);
1974 2011
1975 /* Clear DFX Status registers */ 2012 /* Clear DFX Status registers */
1976 writel(0x0081000f, &afe->afe_dfx_master_control0); 2013 writel(0x0081000f, &afe->afe_dfx_master_control0);
diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h
index 4573075a6b97..5477f0fa8233 100644
--- a/drivers/scsi/isci/host.h
+++ b/drivers/scsi/isci/host.h
@@ -447,6 +447,24 @@ static inline bool is_c1(struct pci_dev *pdev)
447 return false; 447 return false;
448} 448}
449 449
450enum cable_selections {
451 short_cable = 0,
452 long_cable = 1,
453 medium_cable = 2,
454 undefined_cable = 3
455};
456
457#define CABLE_OVERRIDE_DISABLED (0x10000)
458
459static inline int is_cable_select_overridden(void)
460{
461 return cable_selection_override < CABLE_OVERRIDE_DISABLED;
462}
463
464enum cable_selections decode_cable_selection(struct isci_host *ihost, int phy);
465void validate_cable_selections(struct isci_host *ihost);
466char *lookup_cable_names(enum cable_selections);
467
450/* set hw control for 'activity', even though active enclosures seem to drive 468/* set hw control for 'activity', even though active enclosures seem to drive
451 * the activity led on their own. Skip setting FSENG control on 'status' due 469 * the activity led on their own. Skip setting FSENG control on 'status' due
452 * to unexpected operation and 'error' due to not being a supported automatic 470 * to unexpected operation and 'error' due to not being a supported automatic
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c
index 8a34fd92e42e..1047108ba4de 100644
--- a/drivers/scsi/isci/init.c
+++ b/drivers/scsi/isci/init.c
@@ -122,6 +122,14 @@ unsigned char max_concurr_spinup;
122module_param(max_concurr_spinup, byte, 0); 122module_param(max_concurr_spinup, byte, 0);
123MODULE_PARM_DESC(max_concurr_spinup, "Max concurrent device spinup"); 123MODULE_PARM_DESC(max_concurr_spinup, "Max concurrent device spinup");
124 124
125uint cable_selection_override = CABLE_OVERRIDE_DISABLED;
126module_param(cable_selection_override, uint, 0);
127
128MODULE_PARM_DESC(cable_selection_override,
129 "This field indicates length of the SAS/SATA cable between "
130 "host and device. If any bits > 15 are set (default) "
131 "indicates \"use platform defaults\"");
132
125static ssize_t isci_show_id(struct device *dev, struct device_attribute *attr, char *buf) 133static ssize_t isci_show_id(struct device *dev, struct device_attribute *attr, char *buf)
126{ 134{
127 struct Scsi_Host *shost = container_of(dev, typeof(*shost), shost_dev); 135 struct Scsi_Host *shost = container_of(dev, typeof(*shost), shost_dev);
@@ -412,6 +420,14 @@ static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id)
412 return NULL; 420 return NULL;
413 isci_host->shost = shost; 421 isci_host->shost = shost;
414 422
423 dev_info(&pdev->dev, "%sSCU controller %d: phy 3-0 cables: "
424 "{%s, %s, %s, %s}\n",
425 (is_cable_select_overridden() ? "* " : ""), isci_host->id,
426 lookup_cable_names(decode_cable_selection(isci_host, 3)),
427 lookup_cable_names(decode_cable_selection(isci_host, 2)),
428 lookup_cable_names(decode_cable_selection(isci_host, 1)),
429 lookup_cable_names(decode_cable_selection(isci_host, 0)));
430
415 err = isci_host_init(isci_host); 431 err = isci_host_init(isci_host);
416 if (err) 432 if (err)
417 goto err_shost; 433 goto err_shost;
diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h
index 8efeb6b08321..234ab46fce33 100644
--- a/drivers/scsi/isci/isci.h
+++ b/drivers/scsi/isci/isci.h
@@ -480,6 +480,7 @@ extern u16 ssp_inactive_to;
480extern u16 stp_inactive_to; 480extern u16 stp_inactive_to;
481extern unsigned char phy_gen; 481extern unsigned char phy_gen;
482extern unsigned char max_concurr_spinup; 482extern unsigned char max_concurr_spinup;
483extern uint cable_selection_override;
483 484
484irqreturn_t isci_msix_isr(int vec, void *data); 485irqreturn_t isci_msix_isr(int vec, void *data);
485irqreturn_t isci_intx_isr(int vec, void *data); 486irqreturn_t isci_intx_isr(int vec, void *data);
diff --git a/drivers/scsi/isci/probe_roms.h b/drivers/scsi/isci/probe_roms.h
index 42dd05414f3b..bb0e9d4d97c9 100644
--- a/drivers/scsi/isci/probe_roms.h
+++ b/drivers/scsi/isci/probe_roms.h
@@ -193,7 +193,8 @@ struct isci_oem_hdr {
193 193
194#define ISCI_ROM_VER_1_0 0x10 194#define ISCI_ROM_VER_1_0 0x10
195#define ISCI_ROM_VER_1_1 0x11 195#define ISCI_ROM_VER_1_1 0x11
196#define ISCI_ROM_VER_LATEST ISCI_ROM_VER_1_1 196#define ISCI_ROM_VER_1_3 0x13
197#define ISCI_ROM_VER_LATEST ISCI_ROM_VER_1_3
197 198
198/* Allowed PORT configuration modes APC Automatic PORT configuration mode is 199/* Allowed PORT configuration modes APC Automatic PORT configuration mode is
199 * defined by the OEM configuration parameters providing no PHY_MASK parameters 200 * defined by the OEM configuration parameters providing no PHY_MASK parameters
@@ -270,7 +271,40 @@ struct sci_oem_params {
270 }; 271 };
271 uint8_t do_enable_ssc; 272 uint8_t do_enable_ssc;
272 }; 273 };
273 uint8_t reserved; 274 /*
275 * This field indicates length of the SAS/SATA cable between
276 * host and device.
277 * This field is used make relationship between analog
278 * parameters of the phy in the silicon and length of the cable.
279 * Supported cable attenuation levels:
280 * "short"- up to 3m, "medium"-3m to 6m, and "long"- more than
281 * 6m.
282 *
283 * This is bit mask field:
284 *
285 * BIT: (MSB) 7 6 5 4
286 * ASSIGNMENT: <phy3><phy2><phy1><phy0> - Medium cable
287 * length assignment
288 * BIT: 3 2 1 0 (LSB)
289 * ASSIGNMENT: <phy3><phy2><phy1><phy0> - Long cable length
290 * assignment
291 *
292 * BITS 7-4 are set when the cable length is assigned to medium
293 * BITS 3-0 are set when the cable length is assigned to long
294 *
295 * The BIT positions are clear when the cable length is
296 * assigned to short.
297 *
298 * Setting the bits for both long and medium cable length is
299 * undefined.
300 *
301 * A value of 0x84 would assign
302 * phy3 - medium
303 * phy2 - long
304 * phy1 - short
305 * phy0 - short
306 */
307 uint8_t cable_selection_mask;
274 } controller; 308 } controller;
275 309
276 struct { 310 struct {