int i;
struct sas_ha_struct *sas_ha = phy->ha;
struct asd_sas_port *port = phy->port;
+ struct domain_device *port_dev;
struct sas_internal *si =
to_sas_internal(sas_ha->core.shost->transportt);
unsigned long flags;
}
/* add the phy to the port */
+ port_dev = port->port_dev;
list_add_tail(&phy->port_phy_el, &port->phy_list);
- sas_phy_set_target(phy, port->port_dev);
+ sas_phy_set_target(phy, port_dev);
phy->port = port;
port->num_phys++;
port->phy_mask |= (1U << phy->id);
port->phy_mask,
SAS_ADDR(port->attached_sas_addr));
- if (port->port_dev)
- port->port_dev->pathways = port->num_phys;
+ if (port_dev)
+ port_dev->pathways = port->num_phys;
/* Tell the LLDD about this port formation. */
if (si->dft->lldd_port_formed)
si->dft->lldd_port_formed(phy);
sas_discover_event(phy->port, DISCE_DISCOVER_DOMAIN);
+ /* Only insert a revalidate event after initial discovery */
+ if (port_dev && sas_dev_type_is_expander(port_dev->dev_type)) {
+ struct expander_device *ex_dev = &port_dev->ex_dev;
+
+ ex_dev->ex_change_count = -1;
+ sas_discover_event(port, DISCE_REVALIDATE_DOMAIN);
+ }
flush_workqueue(sas_ha->disco_q);
}
spin_unlock(&port->phy_list_lock);
spin_unlock_irqrestore(&sas_ha->phy_port_lock, flags);
+ /* Only insert revalidate event if the port still has members */
+ if (port->port && dev && sas_dev_type_is_expander(dev->dev_type)) {
+ struct expander_device *ex_dev = &dev->ex_dev;
+
+ ex_dev->ex_change_count = -1;
+ sas_discover_event(port, DISCE_REVALIDATE_DOMAIN);
+ }
+ flush_workqueue(sas_ha->disco_q);
+
return;
}
struct work_struct work;
};
+/* Lots of code duplicates this in the SCSI tree, which can be factored out */
+static inline bool sas_dev_type_is_expander(enum sas_device_type type)
+{
+ return type == SAS_EDGE_EXPANDER_DEVICE ||
+ type == SAS_FANOUT_EXPANDER_DEVICE;
+}
+
static inline void INIT_SAS_WORK(struct sas_work *sw, void (*fn)(struct work_struct *))
{
INIT_WORK(&sw->work, fn);