diff options
Diffstat (limited to 'drivers/scsi/scsi_transport_sas.c')
| -rw-r--r-- | drivers/scsi/scsi_transport_sas.c | 80 | 
1 files changed, 67 insertions, 13 deletions
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index 927e99cb722..c341f855fad 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -151,6 +151,7 @@ static struct {  	{ SAS_LINK_RATE_1_5_GBPS,	"1.5 Gbit" },  	{ SAS_LINK_RATE_3_0_GBPS,	"3.0 Gbit" },  	{ SAS_LINK_RATE_6_0_GBPS,	"6.0 Gbit" }, +	{ SAS_LINK_RATE_12_0_GBPS,	"12.0 Gbit" },  };  sas_bitfield_name_search(linkspeed, sas_linkspeed_names)  sas_bitfield_name_set(linkspeed, sas_linkspeed_names) @@ -173,11 +174,7 @@ static void sas_smp_request(struct request_queue *q, struct Scsi_Host *shost,  	int ret;  	int (*handler)(struct Scsi_Host *, struct sas_rphy *, struct request *); -	while (!blk_queue_plugged(q)) { -		req = blk_fetch_request(q); -		if (!req) -			break; - +	while ((req = blk_fetch_request(q)) != NULL) {  		spin_unlock_irq(q->queue_lock);  		handler = to_sas_internal(shost->transportt)->f->smp_handler; @@ -619,6 +616,7 @@ do_sas_phy_reset(struct device *dev, size_t count, int hard_reset)  	error = i->f->phy_reset(phy, hard_reset);  	if (error)  		return error; +	phy->enabled = 1;  	return count;  }; @@ -656,9 +654,21 @@ sas_phy_linkerror_attr(running_disparity_error_count);  sas_phy_linkerror_attr(loss_of_dword_sync_count);  sas_phy_linkerror_attr(phy_reset_problem_count); +static int sas_phy_setup(struct transport_container *tc, struct device *dev, +			 struct device *cdev) +{ +	struct sas_phy *phy = dev_to_phy(dev); +	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); +	struct sas_internal *i = to_sas_internal(shost->transportt); + +	if (i->f->phy_setup) +		i->f->phy_setup(phy); + +	return 0; +}  static DECLARE_TRANSPORT_CLASS(sas_phy_class, -		"sas_phy", NULL, NULL, NULL); +		"sas_phy", sas_phy_setup, NULL, NULL);  static int sas_phy_match(struct attribute_container *cont, struct device *dev)  { @@ -682,7 +692,11 @@ static int sas_phy_match(struct attribute_container *cont, struct device *dev)  static void sas_phy_release(struct device *dev)  {  	struct sas_phy *phy = dev_to_phy(dev); +	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); +	struct sas_internal *i = to_sas_internal(shost->transportt); +	if (i->f->phy_release) +		i->f->phy_release(phy);  	put_device(dev->parent);  	kfree(phy);  } @@ -1048,6 +1062,29 @@ int scsi_is_sas_port(const struct device *dev)  EXPORT_SYMBOL(scsi_is_sas_port);  /** + * sas_port_get_phy - try to take a reference on a port member + * @port: port to check + */ +struct sas_phy *sas_port_get_phy(struct sas_port *port) +{ +	struct sas_phy *phy; + +	mutex_lock(&port->phy_list_mutex); +	if (list_empty(&port->phy_list)) +		phy = NULL; +	else { +		struct list_head *ent = port->phy_list.next; + +		phy = list_entry(ent, typeof(*phy), port_siblings); +		get_device(&phy->dev); +	} +	mutex_unlock(&port->phy_list_mutex); + +	return phy; +} +EXPORT_SYMBOL(sas_port_get_phy); + +/**   * sas_port_add_phy - add another phy to a port to form a wide port   * @port:	port to add the phy to   * @phy:	phy to add @@ -1549,8 +1586,14 @@ int sas_rphy_add(struct sas_rphy *rphy)  	if (identify->device_type == SAS_END_DEVICE &&  	    rphy->scsi_target_id != -1) { -		scsi_scan_target(&rphy->dev, 0, -				rphy->scsi_target_id, SCAN_WILD_CARD, 0); +		int lun; + +		if (identify->target_port_protocols & SAS_PROTOCOL_SSP) +			lun = SCAN_WILD_CARD; +		else +			lun = 0; + +		scsi_scan_target(&rphy->dev, 0, rphy->scsi_target_id, lun, 0);  	}  	return 0; @@ -1578,8 +1621,6 @@ void sas_rphy_free(struct sas_rphy *rphy)  	list_del(&rphy->list);  	mutex_unlock(&sas_host->lock); -	sas_bsg_remove(shost, rphy); -  	transport_destroy_device(dev);  	put_device(dev); @@ -1601,6 +1642,20 @@ sas_rphy_delete(struct sas_rphy *rphy)  EXPORT_SYMBOL(sas_rphy_delete);  /** + * sas_rphy_unlink  -  unlink SAS remote PHY + * @rphy:	SAS remote phy to unlink from its parent port + * + * Removes port reference to an rphy + */ +void sas_rphy_unlink(struct sas_rphy *rphy) +{ +	struct sas_port *parent = dev_to_sas_port(rphy->dev.parent); + +	parent->rphy = NULL; +} +EXPORT_SYMBOL(sas_rphy_unlink); + +/**   * sas_rphy_remove  -  remove SAS remote PHY   * @rphy:	SAS remote phy to remove   * @@ -1610,7 +1665,6 @@ void  sas_rphy_remove(struct sas_rphy *rphy)  {  	struct device *dev = &rphy->dev; -	struct sas_port *parent = dev_to_sas_port(dev->parent);  	switch (rphy->identify.device_type) {  	case SAS_END_DEVICE: @@ -1624,10 +1678,10 @@ sas_rphy_remove(struct sas_rphy *rphy)  		break;  	} +	sas_rphy_unlink(rphy); +	sas_bsg_remove(NULL, rphy);  	transport_remove_device(dev);  	device_del(dev); - -	parent->rphy = NULL;  }  EXPORT_SYMBOL(sas_rphy_remove);  | 
