diff options
author | Dan Williams <dan.j.williams@intel.com> | 2010-10-01 16:55:52 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-12-21 13:23:53 -0500 |
commit | 00f0254ed9b19164d416dc2e3c2e81eda55a6faf (patch) | |
tree | d33cb0b2c36ecd9ef4dbe32d9294dbd5c221f852 /drivers/scsi/libsas | |
parent | 3ff5588d3f8afad65ded52ac0e4191462fe034cb (diff) |
[SCSI] libsas: fix definition of wideport, include local sas address
To date libsas has only looked at the attached sas address when
determining the formation of wide ports. The specification and some
hardware expects that phys with different addresses will not form a wide
port unless the local peer phys also match each other. Introduce a flag
to select stricter behavior at sas_register_ha() time. The flag can be
dropped once it is known that all libsas users expect the same behavior.
Current drivers just initialize this field to zero and get the
traditional behavior.
Reported-by: Patrick Thomson <patrick.s.thomson@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/libsas')
-rw-r--r-- | drivers/scsi/libsas/sas_port.c | 18 |
1 files changed, 13 insertions, 5 deletions
diff --git a/drivers/scsi/libsas/sas_port.c b/drivers/scsi/libsas/sas_port.c index fe8b74c706d2..5257fdfe699a 100644 --- a/drivers/scsi/libsas/sas_port.c +++ b/drivers/scsi/libsas/sas_port.c | |||
@@ -28,6 +28,17 @@ | |||
28 | #include <scsi/scsi_transport_sas.h> | 28 | #include <scsi/scsi_transport_sas.h> |
29 | #include "../scsi_sas_internal.h" | 29 | #include "../scsi_sas_internal.h" |
30 | 30 | ||
31 | static bool phy_is_wideport_member(struct asd_sas_port *port, struct asd_sas_phy *phy) | ||
32 | { | ||
33 | struct sas_ha_struct *sas_ha = phy->ha; | ||
34 | |||
35 | if (memcmp(port->attached_sas_addr, phy->attached_sas_addr, | ||
36 | SAS_ADDR_SIZE) != 0 || (sas_ha->strict_wide_ports && | ||
37 | memcmp(port->sas_addr, phy->sas_addr, SAS_ADDR_SIZE) != 0)) | ||
38 | return false; | ||
39 | return true; | ||
40 | } | ||
41 | |||
31 | /** | 42 | /** |
32 | * sas_form_port -- add this phy to a port | 43 | * sas_form_port -- add this phy to a port |
33 | * @phy: the phy of interest | 44 | * @phy: the phy of interest |
@@ -45,8 +56,7 @@ static void sas_form_port(struct asd_sas_phy *phy) | |||
45 | unsigned long flags; | 56 | unsigned long flags; |
46 | 57 | ||
47 | if (port) { | 58 | if (port) { |
48 | if (memcmp(port->attached_sas_addr, phy->attached_sas_addr, | 59 | if (!phy_is_wideport_member(port, phy)) |
49 | SAS_ADDR_SIZE) != 0) | ||
50 | sas_deform_port(phy); | 60 | sas_deform_port(phy); |
51 | else { | 61 | else { |
52 | SAS_DPRINTK("%s: phy%d belongs to port%d already(%d)!\n", | 62 | SAS_DPRINTK("%s: phy%d belongs to port%d already(%d)!\n", |
@@ -62,9 +72,7 @@ static void sas_form_port(struct asd_sas_phy *phy) | |||
62 | port = sas_ha->sas_port[i]; | 72 | port = sas_ha->sas_port[i]; |
63 | spin_lock(&port->phy_list_lock); | 73 | spin_lock(&port->phy_list_lock); |
64 | if (*(u64 *) port->sas_addr && | 74 | if (*(u64 *) port->sas_addr && |
65 | memcmp(port->attached_sas_addr, | 75 | phy_is_wideport_member(port, phy) && port->num_phys > 0) { |
66 | phy->attached_sas_addr, SAS_ADDR_SIZE) == 0 && | ||
67 | port->num_phys > 0) { | ||
68 | /* wide port */ | 76 | /* wide port */ |
69 | SAS_DPRINTK("phy%d matched wide port%d\n", phy->id, | 77 | SAS_DPRINTK("phy%d matched wide port%d\n", phy->id, |
70 | port->id); | 78 | port->id); |