Linux SCSI subsystem development
 help / color / mirror / Atom feed
From: James Bottomley <James.Bottomley@HansenPartnership.com>
To: jack wang <jack_wang@usish.com>
Cc: linux-scsi@vger.kernel.org, jeff@garzik.org,
	lindar_liu@usish.com, tom_peng@usish.com, aoqingyun@usish.com
Subject: Re: [RFC][PATCH 4/5] fix wide port hotplug issues
Date: Thu, 16 Jul 2009 15:34:06 -0500	[thread overview]
Message-ID: <1247776446.6606.393.camel@mulgrave.site> (raw)
In-Reply-To: <BB8426D8117A437F9C3D44C89A5E6534@usish.com.cn>

On Wed, 2009-07-01 at 20:41 +0800, jack wang wrote:
> The sas layer does not support wide port hotplug, we modified it. 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.
> 					Jack
> >From d683c649d0ed8de69b1ffda1b87383ae13fed164 Mon Sep 17 00:00:00 2001
> From: Tom Peng <tom_peng@usish.com>
> Date: Wed, 1 Jul 2009 19:11:03 +0800
> Subject: [PATCH 4/5] fix wide port hotplug issues
> 
> Signed-off-by: Tom Peng <tom_peng@usish.com>
> Signed-off-by: Jack Wang <jack_wang@usish.com>
> Signed-off-by: Lindar Liu <lindar_liu@usish.com>
> ---
>  drivers/scsi/libsas/sas_expander.c |  190
> ++++++++++++++++++++++++------------
>  1 files changed, 126 insertions(+), 64 deletions(-)
> 
> diff --git a/drivers/scsi/libsas/sas_expander.c
> b/drivers/scsi/libsas/sas_expander.c
> index 54fa1e4..20fa5e4 100644
> --- a/drivers/scsi/libsas/sas_expander.c
> +++ b/drivers/scsi/libsas/sas_expander.c
> @@ -764,8 +764,9 @@ static int sas_ex_join_wide_port(struct domain_device
> *parent, int phy_id)
>  			continue;
>  
>  		if (!memcmp(phy->attached_sas_addr, ephy->attached_sas_addr,
> -			    SAS_ADDR_SIZE) && ephy->port) {
> +			SAS_ADDR_SIZE) && ephy->port) {

It would be really nice if you could fix up your patches to avoid
spurious white space changes like this (particularly when they're not
correct: we do line up the arguments to a split line function call under
the first arg).

>  			sas_port_add_phy(ephy->port, phy->phy);
> +			phy->port = ephy->port;

So this is an actual bug in the wide port handling routines, isn't it?
without this, an unplug of a port not the original one will do a NULL
deref on phy->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);
> +			}

So this doesn't look right.  There's already a check for wide ports at
the top of this function.  That should pick up any port because we call
this routine for any discoverable device (regardless of phy).

>  		}
>  	}
>  
> @@ -1589,16 +1597,14 @@ static int sas_get_phy_attached_sas_addr(struct
> domain_device *dev,
>  
>  	res = sas_get_phy_discover(dev, phy_id, disc_resp);
>  	if (!res) {
> -
> memcpy(attached_sas_addr,disc_resp->disc.attached_sas_addr,8);
> -		if (dr->attached_dev_type == 0)
> -			memset(attached_sas_addr, 0, 8);
> +		memcpy(attached_sas_addr, disc_resp->disc.attached_sas_addr,
> 8);

So what the removed code is doing is trying to stop scanning of
initiators ... they appear with a routing address but no actual device
attached.

>  	}
>  	kfree(disc_resp);
>  	return res;
>  }
>  
>  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 +1617,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 +1661,50 @@ out:
>  	kfree(rg_req);
>  	return res;
>  }
> -
> +/**
> + * sas_find_bcast_dev -  in before version, it does not consider
> + * SAS self-configuration expander. Suppose two expander cascading,
> + * while 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.
> + * @dev:domain device to be detect.
> + * @src_dev: the device which originated BROADCAST(CHANGE).

This isn't actually DocBook; it needs to be

/**
* function - one line summary
* @arg: argument descriptions
* ...
*
* Body
*/

> + */
>  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;
> +	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 +1727,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,21 +1799,37 @@ 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;
>  
>  	SAS_DPRINTK("ex %016llx phy%d new device attached\n",
> -		    SAS_ADDR(dev->sas_addr), phy_id);
> +		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;


Why did this logic get inverted here?

James



  reply	other threads:[~2009-07-16 20:34 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-07-01 12:41 [RFC][PATCH 4/5] fix wide port hotplug issues jack wang
2009-07-16 20:34 ` James Bottomley [this message]
2009-07-17  8:20   ` [RFC][PATCH v2] " jack wang
2009-07-29 15:54     ` James Bottomley

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1247776446.6606.393.camel@mulgrave.site \
    --to=james.bottomley@hansenpartnership.com \
    --cc=aoqingyun@usish.com \
    --cc=jack_wang@usish.com \
    --cc=jeff@garzik.org \
    --cc=lindar_liu@usish.com \
    --cc=linux-scsi@vger.kernel.org \
    --cc=tom_peng@usish.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox