Re: [RFC][PATCH v2] fix wide port hotplug issues

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, 2009-07-17 at 16:20 +0800, jack wang wrote:
> Hi, James
> As your comments ,we resend this patch again. All comments & style issue
> have fixed.
> Best regards!

This looks much better thanks.

It still could do with a description; I created one this time, but I
can't keep on doing that.

> Jack Wang
> >From 2b269e6d73fae3a7c83171e97d894fc84798c35a Mon Sep 17 00:00:00 2001
> From: Tom Peng <tom_peng@xxxxxxxxx>
> Date: Fri, 17 Jul 2009 16:02:04 +0800
> Subject: [PATCH] fix libsas wide port hotplug issue v2
> 
> Signed-off-by: Tom Peng <tom_peng@xxxxxxxxx>
> Signed-off-by: Jack Wang <jack_wang@xxxxxxxxx>
> Signed-off-by: Lindar Liu <lindar_liu@xxxxxxxxx>
> Signed-off-by: Kevin Ao <aoqingyun@xxxxxxxxx>
> ---
>  drivers/scsi/libsas/sas_expander.c |  149
> ++++++++++++++++++++++++++----------
>  1 files changed, 108 insertions(+), 41 deletions(-)
> 
> diff --git a/drivers/scsi/libsas/sas_expander.c
> b/drivers/scsi/libsas/sas_expander.c
> index 54fa1e4..24d108f 100644
> --- a/drivers/scsi/libsas/sas_expander.c
> +++ b/drivers/scsi/libsas/sas_expander.c
> @@ -766,6 +766,7 @@ static int sas_ex_join_wide_port(struct domain_device
> *parent, int phy_id)
>  		if (!memcmp(phy->attached_sas_addr, ephy->attached_sas_addr,
>  			    SAS_ADDR_SIZE) && ephy->port) {
>  			sas_port_add_phy(ephy->port, phy->phy);
> +			phy->port = ephy->port;
>  			phy->phy_state = PHY_DEVICE_DISCOVERED;
>  			return 0;
>  		}
> @@ -945,10 +946,17 @@ static int sas_ex_discover_dev(struct domain_device
> *dev, int phy_id)
>  			if (ex->ex_phy[i].phy_state == PHY_VACANT ||
>  			    ex->ex_phy[i].phy_state == PHY_NOT_PRESENT)
>  				continue;
> -
> +			/* in before discover process, it does not add the
> phy
> +			* to wide port, so we add the phy to the wide port
> here.
> +			*/
>  			if (SAS_ADDR(ex->ex_phy[i].attached_sas_addr) ==
> -			    SAS_ADDR(child->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)
> +					SAS_DPRINTK("Add ex phy %d to this "
> +						    "wide port.\n", i);

For consistency, I made this message the same as the prior one

> +			}

And added a missing res = 0 here.  Without this, we exit the loop with
res = -ENODEV and then return that to the caller, which is wrong.

>  		}
>  	}
>  
> @@ -1598,7 +1606,7 @@ static int sas_get_phy_attached_sas_addr(struct
> domain_device *dev,
>  }
>  
>  static int sas_find_bcast_phy(struct domain_device *dev, int *phy_id,
> -			      int from_phy)
> +			      int from_phy, bool update)
>  {
>  	struct expander_device *ex = &dev->ex_dev;
>  	int res = 0;
> @@ -1611,7 +1619,9 @@ static int sas_find_bcast_phy(struct domain_device
> *dev, int *phy_id,
>  		if (res)
>  			goto out;
>  		else if (phy_change_count != ex->ex_phy[i].phy_change_count)
> {
> -			ex->ex_phy[i].phy_change_count = phy_change_count;
> +			if (update)
> +				ex->ex_phy[i].phy_change_count =
> +					phy_change_count;
>  			*phy_id = i;
>  			return 0;
>  		}
> @@ -1653,31 +1663,52 @@ out:
>  	kfree(rg_req);
>  	return res;
>  }
> +/**
> + * sas_find_bcast_dev -  find the device issue BROADCAST(CHANGE).
> + * @dev:domain device to be detect.
> + * @src_dev: the device which originated BROADCAST(CHANGE).
> + *
> + * Add self-configuration expander suport. Suppose two expander cascading,
> + * when the first level expander is self-configuring, hotplug the disks in
> + * second level expander, BROADCAST(CHANGE) will not only be originated
> + * in the second level expander, but also be originated in the first level
> + * expander (see SAS protocol SAS 2r-14, 7.11 for detail), it is to say,
> + * expander changed count in two level expanders will all increment at
> least
> + * once, but the phy which chang count has changed is the source device
> which
> + * we concerned.
> + */
>  
>  static int sas_find_bcast_dev(struct domain_device *dev,
>  			      struct domain_device **src_dev)
>  {
>  	struct expander_device *ex = &dev->ex_dev;
>  	int ex_change_count = -1;
> -	int res;
> +	int phy_id = -1;
> +	int res, i = 0;

This i=0 is superfluous, you only use it to carry zero into
sas_find_bcast_phy()

> +	struct domain_device *ch;
>  
>  	res = sas_get_ex_change_count(dev, &ex_change_count);
>  	if (res)
>  		goto out;
> -	if (ex_change_count != -1 &&
> -	    ex_change_count != ex->ex_change_count) {
> -		*src_dev = dev;
> -		ex->ex_change_count = ex_change_count;
> -	} else {
> -		struct domain_device *ch;
> -
> -		list_for_each_entry(ch, &ex->children, siblings) {
> -			if (ch->dev_type == EDGE_DEV ||
> -			    ch->dev_type == FANOUT_DEV) {
> -				res = sas_find_bcast_dev(ch, src_dev);
> -				if (src_dev)
> -					return res;
> -			}
> +	if (ex_change_count != -1 && ex_change_count != ex->ex_change_count)
> {
> +		/* Just detect if this expander phys phy change count
> changed,
> +		* in order to determine if this expander originate
> BROADCAST,
> +		* and do not update phy change count field in our structure.
> +		*/
> +		res = sas_find_bcast_phy(dev, &phy_id, i, FALSE);
> +		if (phy_id != -1) {
> +			*src_dev = dev;
> +			ex->ex_change_count = ex_change_count;
> +			SAS_DPRINTK("Expander phy change count has changed
> \n");
> +			return res;
> +		} else
> +			SAS_DPRINTK("Expander phys DID NOT changed \n");
> +	}
> +	list_for_each_entry(ch, &ex->children, siblings) {
> +		if (ch->dev_type == EDGE_DEV || ch->dev_type == FANOUT_DEV)
> {
> +			res = sas_find_bcast_dev(ch, src_dev);
> +			if (src_dev)
> +				return res;
>  		}
>  	}
>  out:
> @@ -1700,24 +1731,26 @@ static void sas_unregister_ex_tree(struct
> domain_device *dev)
>  }
>  
>  static void sas_unregister_devs_sas_addr(struct domain_device *parent,
> -					 int phy_id)
> +					int phy_id, bool last)
>  {
>  	struct expander_device *ex_dev = &parent->ex_dev;
>  	struct ex_phy *phy = &ex_dev->ex_phy[phy_id];
>  	struct domain_device *child, *n;
> -
> -	list_for_each_entry_safe(child, n, &ex_dev->children, siblings) {
> -		if (SAS_ADDR(child->sas_addr) ==
> -		    SAS_ADDR(phy->attached_sas_addr)) {
> -			if (child->dev_type == EDGE_DEV ||
> -			    child->dev_type == FANOUT_DEV)
> -				sas_unregister_ex_tree(child);
> -			else
> -				sas_unregister_dev(child);
> -			break;
> +	if (last) {
> +		list_for_each_entry_safe(child, n,
> +			&ex_dev->children, siblings) {
> +			if (SAS_ADDR(child->sas_addr) ==
> +				SAS_ADDR(phy->attached_sas_addr)) {
> +				if (child->dev_type == EDGE_DEV ||
> +					child->dev_type == FANOUT_DEV)
> +					sas_unregister_ex_tree(child);
> +				else
> +					sas_unregister_dev(child);
> +				break;
> +			}
>  		}
> +		sas_disable_routing(parent, phy->attached_sas_addr);
>  	}
> -	sas_disable_routing(parent, phy->attached_sas_addr);
>  	memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE);
>  	sas_port_delete_phy(phy->port, phy->phy);
>  	if (phy->port->num_phys == 0)
> @@ -1770,15 +1803,31 @@ 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;
> -	int res;
> +	bool found = FALSE;
> +	int res, i = 0;

No need to zero initialise i ... it's only used in a for loop where it
gets initialised.

>  
>  	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 == TRUE) {
> +		sas_ex_join_wide_port(dev, phy_id);
> +		return 0;
> +	}
>  	res = sas_ex_discover_devices(dev, phy_id);
> -	if (res)
> +	if (!res)
>  		goto out;
>  	list_for_each_entry(child, &dev->ex_dev.children, siblings) {
>  		if (SAS_ADDR(child->sas_addr) ==
> @@ -1793,7 +1842,8 @@ out:
>  	return res;
>  }
>  
> -static int sas_rediscover_dev(struct domain_device *dev, int phy_id)
> +static int sas_rediscover_dev(struct domain_device *dev, int phy_id,
> +				bool last)

Should be lined up under the first arg, but actually it will fit on one
line without going over 80 characters.

>  {
>  	struct expander_device *ex = &dev->ex_dev;
>  	struct ex_phy *phy = &ex->ex_phy[phy_id];
> @@ -1804,11 +1854,11 @@ static int sas_rediscover_dev(struct domain_device
> *dev, int phy_id)
>  	switch (res) {
>  	case SMP_RESP_NO_PHY:
>  		phy->phy_state = PHY_NOT_PRESENT;
> -		sas_unregister_devs_sas_addr(dev, phy_id);
> +		sas_unregister_devs_sas_addr(dev, phy_id, last);
>  		goto out; break;
>  	case SMP_RESP_PHY_VACANT:
>  		phy->phy_state = PHY_VACANT;
> -		sas_unregister_devs_sas_addr(dev, phy_id);
> +		sas_unregister_devs_sas_addr(dev, phy_id, last);
>  		goto out; break;
>  	case SMP_RESP_FUNC_ACC:
>  		break;
> @@ -1816,7 +1866,7 @@ static int sas_rediscover_dev(struct domain_device
> *dev, int phy_id)
>  
>  	if (SAS_ADDR(attached_sas_addr) == 0) {
>  		phy->phy_state = PHY_EMPTY;
> -		sas_unregister_devs_sas_addr(dev, phy_id);
> +		sas_unregister_devs_sas_addr(dev, phy_id, last);
>  	} else if (SAS_ADDR(attached_sas_addr) ==
>  		   SAS_ADDR(phy->attached_sas_addr)) {
>  		SAS_DPRINTK("ex %016llx phy 0x%x broadcast flutter\n",
> @@ -1828,12 +1878,28 @@ out:
>  	return res;
>  }
>  
> +/**
> + * sas_rediscover -- revalidate the domain.

single - for docbook, not double.

> + * @dev:domain device to be detect.
> + * @phy_id: the phy id will be detected.
> + * NOTE: this process _must_ quit (return) as soon as any connection
> + * errors are encountered.  Connection recovery is done elsewhere.
> + * Discover process only interrogates devices in order to discover the
> + * domain.For plugging out, we un-register the device only when it is
> + * the last phy in the port, for other phys in this port, we just delete it
> + * from the port.For inserting, we do discovery when it is the
> + * first phy,for other phys in this port, we add it to the port to
> + * forming the wide-port.
> + */
>  static int sas_rediscover(struct domain_device *dev, const int phy_id)
>  {
>  	struct expander_device *ex = &dev->ex_dev;
>  	struct ex_phy *changed_phy = &ex->ex_phy[phy_id];
>  	int res = 0;
>  	int i;
> +	/* To check whether the last phy of a port determining whether or
> not
> +	delete devices*/
> +	bool last = TRUE;
>  
>  	SAS_DPRINTK("ex %016llx phy%d originated BROADCAST(CHANGE)\n",
>  		    SAS_ADDR(dev->sas_addr), phy_id);
> @@ -1848,13 +1914,13 @@ static int sas_rediscover(struct domain_device *dev,
> const int phy_id)
>  			    SAS_ADDR(changed_phy->attached_sas_addr)) {
>  				SAS_DPRINTK("phy%d part of wide port with "
>  					    "phy%d\n", phy_id, i);
> -				goto out;
> +				last = FALSE;
> +				break;
>  			}
>  		}
> -		res = sas_rediscover_dev(dev, phy_id);
> +		res = sas_rediscover_dev(dev, phy_id, last);
>  	} else
>  		res = sas_discover_new(dev, phy_id);
> -out:
>  	return res;
>  }
>  
> @@ -1881,7 +1947,7 @@ int sas_ex_revalidate_domain(struct domain_device
> *port_dev)
>  
>  		do {
>  			phy_id = -1;
> -			res = sas_find_bcast_phy(dev, &phy_id, i);
> +			res = sas_find_bcast_phy(dev, &phy_id, i, TRUE);
>  			if (phy_id == -1)
>  				break;
>  			res = sas_rediscover(dev, phy_id);
> @@ -1946,3 +2012,4 @@ int sas_smp_handler(struct Scsi_Host *shost, struct
> sas_rphy *rphy,
>  
>  	return ret;
>  }
> +

This is a spurious newline at the end of the file.

James


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux