aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2010-10-01 16:55:52 -0400
committerJames Bottomley <James.Bottomley@suse.de>2010-12-21 13:23:53 -0500
commit00f0254ed9b19164d416dc2e3c2e81eda55a6faf (patch)
treed33cb0b2c36ecd9ef4dbe32d9294dbd5c221f852
parent3ff5588d3f8afad65ded52ac0e4191462fe034cb (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>
-rw-r--r--drivers/scsi/libsas/sas_port.c18
-rw-r--r--include/scsi/libsas.h2
2 files changed, 15 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
31static 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);
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h
index 90ce527ecf3d..8f6bb9c7f3eb 100644
--- a/include/scsi/libsas.h
+++ b/include/scsi/libsas.h
@@ -361,6 +361,8 @@ struct sas_ha_struct {
361 /* The class calls this to send a task for execution. */ 361 /* The class calls this to send a task for execution. */
362 int lldd_max_execute_num; 362 int lldd_max_execute_num;
363 int lldd_queue_size; 363 int lldd_queue_size;
364 int strict_wide_ports; /* both sas_addr and attached_sas_addr must match
365 * their siblings when forming wide ports */
364 366
365 /* LLDD calls these to notify the class of an event. */ 367 /* LLDD calls these to notify the class of an event. */
366 void (*notify_ha_event)(struct sas_ha_struct *, enum ha_event); 368 void (*notify_ha_event)(struct sas_ha_struct *, enum ha_event);