diff options
Diffstat (limited to 'drivers/scsi/libsas/sas_expander.c')
| -rw-r--r-- | drivers/scsi/libsas/sas_expander.c | 74 | 
1 files changed, 32 insertions, 42 deletions
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index caa0525d2523..efc6e72f09f3 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c @@ -51,14 +51,14 @@ static void smp_task_timedout(unsigned long _task)  		task->task_state_flags |= SAS_TASK_STATE_ABORTED;  	spin_unlock_irqrestore(&task->task_state_lock, flags); -	complete(&task->completion); +	complete(&task->slow_task->completion);  }  static void smp_task_done(struct sas_task *task)  { -	if (!del_timer(&task->timer)) +	if (!del_timer(&task->slow_task->timer))  		return; -	complete(&task->completion); +	complete(&task->slow_task->completion);  }  /* Give it some long enough timeout. In seconds. */ @@ -79,7 +79,7 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size,  			break;  		} -		task = sas_alloc_task(GFP_KERNEL); +		task = sas_alloc_slow_task(GFP_KERNEL);  		if (!task) {  			res = -ENOMEM;  			break; @@ -91,20 +91,20 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size,  		task->task_done = smp_task_done; -		task->timer.data = (unsigned long) task; -		task->timer.function = smp_task_timedout; -		task->timer.expires = jiffies + SMP_TIMEOUT*HZ; -		add_timer(&task->timer); +		task->slow_task->timer.data = (unsigned long) task; +		task->slow_task->timer.function = smp_task_timedout; +		task->slow_task->timer.expires = jiffies + SMP_TIMEOUT*HZ; +		add_timer(&task->slow_task->timer);  		res = i->dft->lldd_execute_task(task, 1, GFP_KERNEL);  		if (res) { -			del_timer(&task->timer); +			del_timer(&task->slow_task->timer);  			SAS_DPRINTK("executing SMP task failed:%d\n", res);  			break;  		} -		wait_for_completion(&task->completion); +		wait_for_completion(&task->slow_task->completion);  		res = -ECOMM;  		if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {  			SAS_DPRINTK("smp task timed out or aborted\n"); @@ -868,7 +868,7 @@ static struct domain_device *sas_ex_discover_end_dev(  }  /* See if this phy is part of a wide port */ -static int sas_ex_join_wide_port(struct domain_device *parent, int phy_id) +static bool sas_ex_join_wide_port(struct domain_device *parent, int phy_id)  {  	struct ex_phy *phy = &parent->ex_dev.ex_phy[phy_id];  	int i; @@ -884,11 +884,11 @@ static int sas_ex_join_wide_port(struct domain_device *parent, int phy_id)  			sas_port_add_phy(ephy->port, phy->phy);  			phy->port = ephy->port;  			phy->phy_state = PHY_DEVICE_DISCOVERED; -			return 0; +			return true;  		}  	} -	return -ENODEV; +	return false;  }  static struct domain_device *sas_ex_discover_expander( @@ -1030,8 +1030,7 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id)  		return res;  	} -	res = sas_ex_join_wide_port(dev, phy_id); -	if (!res) { +	if (sas_ex_join_wide_port(dev, phy_id)) {  		SAS_DPRINTK("Attaching ex phy%d to wide port %016llx\n",  			    phy_id, SAS_ADDR(ex_phy->attached_sas_addr));  		return res; @@ -1077,8 +1076,7 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id)  			if (SAS_ADDR(ex->ex_phy[i].attached_sas_addr) ==  			    SAS_ADDR(child->sas_addr)) {  				ex->ex_phy[i].phy_state= PHY_DEVICE_DISCOVERED; -				res = sas_ex_join_wide_port(dev, i); -				if (!res) +				if (sas_ex_join_wide_port(dev, i))  					SAS_DPRINTK("Attaching ex phy%d to wide port %016llx\n",  						    i, SAS_ADDR(ex->ex_phy[i].attached_sas_addr)); @@ -1943,32 +1941,20 @@ static int sas_discover_new(struct domain_device *dev, int phy_id)  {  	struct ex_phy *ex_phy = &dev->ex_dev.ex_phy[phy_id];  	struct domain_device *child; -	bool found = false; -	int res, i; +	int res;  	SAS_DPRINTK("ex %016llx phy%d new device attached\n",  		    SAS_ADDR(dev->sas_addr), phy_id);  	res = sas_ex_phy_discover(dev, phy_id);  	if (res) -		goto out; -	/* to support the wide port inserted */ -	for (i = 0; i < dev->ex_dev.num_phys; i++) { -		struct ex_phy *ex_phy_temp = &dev->ex_dev.ex_phy[i]; -		if (i == phy_id) -			continue; -		if (SAS_ADDR(ex_phy_temp->attached_sas_addr) == -		    SAS_ADDR(ex_phy->attached_sas_addr)) { -			found = true; -			break; -		} -	} -	if (found) { -		sas_ex_join_wide_port(dev, phy_id); +		return res; + +	if (sas_ex_join_wide_port(dev, phy_id))  		return 0; -	} +  	res = sas_ex_discover_devices(dev, phy_id); -	if (!res) -		goto out; +	if (res) +		return res;  	list_for_each_entry(child, &dev->ex_dev.children, siblings) {  		if (SAS_ADDR(child->sas_addr) ==  		    SAS_ADDR(ex_phy->attached_sas_addr)) { @@ -1978,7 +1964,6 @@ static int sas_discover_new(struct domain_device *dev, int phy_id)  			break;  		}  	} -out:  	return res;  } @@ -2005,6 +1990,7 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id, bool last)  	u8 sas_addr[8];  	int res; +	memset(sas_addr, 0, 8);  	res = sas_get_phy_attached_dev(dev, phy_id, sas_addr, &type);  	switch (res) {  	case SMP_RESP_NO_PHY: @@ -2017,9 +2003,13 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id, bool last)  		return res;  	case SMP_RESP_FUNC_ACC:  		break; +	case -ECOMM: +		break; +	default: +		return res;  	} -	if (SAS_ADDR(sas_addr) == 0) { +	if ((SAS_ADDR(sas_addr) == 0) || (res == -ECOMM)) {  		phy->phy_state = PHY_EMPTY;  		sas_unregister_devs_sas_addr(dev, phy_id, last);  		return res; @@ -2109,9 +2099,7 @@ int sas_ex_revalidate_domain(struct domain_device *port_dev)  	struct domain_device *dev = NULL;  	res = sas_find_bcast_dev(port_dev, &dev); -	if (res) -		goto out; -	if (dev) { +	while (res == 0 && dev) {  		struct expander_device *ex = &dev->ex_dev;  		int i = 0, phy_id; @@ -2123,8 +2111,10 @@ int sas_ex_revalidate_domain(struct domain_device *port_dev)  			res = sas_rediscover(dev, phy_id);  			i = phy_id + 1;  		} while (i < ex->num_phys); + +		dev = NULL; +		res = sas_find_bcast_dev(port_dev, &dev);  	} -out:  	return res;  }  | 
