[PATCH] libertas: new mesh control knobs

Dan Williams dcbw at redhat.com
Wed May 30 11:43:26 EDT 2007


On Tue, 2007-05-08 at 01:30 +0000, luisca at cozybit.com wrote:
> Support for new mesh control knobs on firmware 5.220.11.p4:
> 
> 	mesh_{set,get}_bcastr rate
> 		Sets/gets tx rate for mesh broadcast and multicast data frames.
> 
> 	{set,get}_rreq_delay cs
> 		Sets/gets delay for RREQ forwarding, in 1/100 s.
> 
> 	{set,get}_route_exp s
> 		Sets/gets route expiration time, in s.
> 
> 	{set_get)_link_costs cost54 cost36 cost11 cost1
> 		Sets/gets link cost for each available rate.
> 		Rates with cost 0 will be disabled.

So adding new private ioctls means we _MUST_ be comfortable that they
will not change in the foreseeable future.  Once they hit upstream, they
are kernel API/ABI and must not change.  So, will these be unchanged for
the next few years?

Otherwise we can just stuff this patch into a libertas-dev branch that
we don't push upstream, but requires periodic manual merges from
libertas-2.6.

> ---
>  drivers/net/wireless/libertas/README  |   65 +++++++++++++++
>  drivers/net/wireless/libertas/host.h  |    8 ++
>  drivers/net/wireless/libertas/ioctl.c |  138 ++++++++++++++++++++++-----------
>  drivers/net/wireless/libertas/wext.c  |   40 ++++++++++
>  drivers/net/wireless/libertas/wext.h  |   10 +++
>  5 files changed, 216 insertions(+), 45 deletions(-)
> 
> diff --git a/drivers/net/wireless/libertas/README b/drivers/net/wireless/libertas/README
> index 7de8c8f..64f7b6c 100644
> --- a/drivers/net/wireless/libertas/README
> +++ b/drivers/net/wireless/libertas/README
> @@ -146,6 +146,14 @@ MESH Commands:
>  
>  	iwpriv ethX mesh_get_ttl
>  	iwpriv ethX mesh_set_ttl ttl
> +	iwpriv ethX mesh_get_bcastr rate
> +	iwpriv ethX mesh_set_bcastr rate
> +	iwpriv ethX get_rreq_delay
> +	iwpriv ethX set_rreq_delay delay
> +	iwpriv ethX get_route_exp
> +	iwpriv ethX set_route_exp time
> +	iwpriv ethX get_link_costs
> +	iwpriv ethX set_link_costs "cost54 cost36 cost11 cost1"
>  
>  DESCRIPTION
>  	Those commands are used to send additional commands to the Marvell WLAN
> @@ -819,6 +827,63 @@ mesh_set_ttl ttl
>  
>  	iwpriv ethX mesh_set_ttl <ttl>
>  
> +mesh_get_bcastr
> +	
> +	Shows the rate index used for mesh broadcast and multicast packets. The
> +	mapping to actual rates is the same as for rateadapt command.
> +
> +	iwpriv ethX mesh_get_bcastr rate
> +
> +mesh_set_bcastr rate
> +
> +	Sets the rate index for mesh broadcast and muticast packets. The mapping
> +	to actual rates is the same as for rateadapt command.
> +
> +	iwpriv ethX mesh_set_bcastr rate
> +
> +get_rreq_delay
> +	
> +	Shows the delay to forward a RREQ frame. This delay allows the node to
> +	forward just the best route in case the same RREQ arrives to the node
> +	through different routes. The argument is shown in 1/100 seconds.
> +
> +	iwpriv ethX get_rreq_delay
> +
> +set_rreq_delay delay
> +
> +	Sets the RREQ forward delay. The delay is interpreted as 1/100 seconds. 
> +
> +	iwpriv ethX set_rreq_delay delay
> +
> +get_route_exp
> +
> +	Shows the mesh route expiration time, in seconds.
> +
> +	iwpriv ethX get_route_exp
> +
> +set_route_exp time
> +
> +	Gets the mesh route, expiration time, in seconds.

^^^ should probably be "Sets"

> +	iwpriv ethX set_route_exp time
> +
> +get_link_costs
> +
> +	Gets the mesh hop base cost for each used rate. The output gives us the
> +	base cost for hops at 54Mbps, 36Mbps, 11Mbps and 1Mbps, in that order.
> +	The base cost gets divided by a battery state factor to get the actual
> +	cost. A cost of 0 means that rate is deactivated.
> +
> +	iwpriv ethX get_link_costs
> +
> +set_link_costs "cost54 cost36 cost11 cost1"
> +
> +	Sets the mesh hop base cost for the used speeds. The input parameter
> +	will specify the cost for hops at 54Mbps, 36Mbps, 11Mbps and 1Mbps, in
> +	that order. A cost of 0 will disable a specific rate.
> +
> +	iwpriv ethX set_link_costs "cost54 cost36 cost11 cost1"
> +
>  =========================
>  ETHTOOL
>  =========================
> diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h
> index 0b54232..ec54c92 100644
> --- a/drivers/net/wireless/libertas/host.h
> +++ b/drivers/net/wireless/libertas/host.h
> @@ -312,6 +312,14 @@ enum cmd_mesh_access_opts {
>  	cmd_act_mesh_get_stats,
>  	cmd_act_mesh_get_mpp,
>  	cmd_act_mesh_set_mpp,
> +	cmd_act_mesh_set_link_costs,
> +	cmd_act_mesh_get_link_costs,
> +	cmd_act_mesh_set_bcast_rate,
> +	cmd_act_mesh_get_bcast_rate,
> +	cmd_act_mesh_set_rreq_delay,
> +	cmd_act_mesh_get_rreq_delay,
> +	cmd_act_mesh_set_route_exp,
> +	cmd_act_mesh_get_route_exp,
>  };
>  
>  /** Card Event definition */
> diff --git a/drivers/net/wireless/libertas/ioctl.c b/drivers/net/wireless/libertas/ioctl.c
> index d64ef7a..cb9cf69 100644
> --- a/drivers/net/wireless/libertas/ioctl.c
> +++ b/drivers/net/wireless/libertas/ioctl.c
> @@ -1766,63 +1766,72 @@ static int wlan_fwt_time_ioctl(wlan_private * priv, struct ifreq *req)
>  }
>  
>  /**
> - *  @brief          Gets mesh ttl from firmware
> - *  @param priv     A pointer to wlan_private structure
> - *  @param req      A pointer to ifreq structure
> - *  @return         0 --success, otherwise fail
> + *  @brief              Manages all mesh related ioctls
> + *  @param priv         A pointer to wlan_private structure
> + *  @param req          A pointer to ifreq structure
> + *  @param cmd		The command type
> + *  @param host_subcmd  The device code for the subcommand
> + *                          0: sets a value in the firmware
> + *                          1: retrieves an int from the firmware
> + *  @return             0 --success, otherwise fail
>   */
> -static int wlan_mesh_get_ttl_ioctl(wlan_private * priv, struct ifreq *req)
> +static int wlan_mesh_ioctl(wlan_private * priv, struct ifreq *req, 
> +		int cmd, int subcmd)
>  {
> +	struct iwreq *wrq = (struct iwreq *)req ;
>  	struct cmd_ds_mesh_access mesh_access;
> -	int ret;
> -
> +	int parameter ;
> +	char str[128];
> +	char *ptr = str  ;
> +	int ret, i;
> +	
>  	lbs_deb_enter(LBS_DEB_IOCTL);
>  
>  	memset(&mesh_access, 0, sizeof(mesh_access));
>  
> -	ret = libertas_prepare_and_send_command(priv, cmd_mesh_access,
> -				    cmd_act_mesh_get_ttl,
> +	if ( cmd == WLAN_SETONEINT_GETNONE ) {
> +		parameter = SUBCMD_DATA(wrq);
> +		if ( parameter < 0 )
> +			return -EINVAL ;
> +		mesh_access.data[0] = parameter ;
> +	}
> +
> +	else if ( subcmd == cmd_act_mesh_set_link_costs ) {
> +		if (copy_from_user( str, wrq->u.data.pointer, sizeof(str)))
> +			return -EFAULT ;
> +
> +		for (i = 0 ; i < COSTS_LIST_SIZE  ; i++) {
> +			mesh_access.data[i] = cpu_to_le32(simple_strtoul(ptr, &ptr, 10)) ;
> +			if (!(ptr = next_param(ptr)) && i!= (COSTS_LIST_SIZE - 1))
> +				return -EINVAL ;
> +		}
> +	}
> +			
> +	ret = libertas_prepare_and_send_command(priv, cmd_mesh_access, subcmd,
>  				    cmd_option_waitforrsp, 0,
>  				    (void *)&mesh_access);
> +	
> +	if (ret != 0)
> +		return -EFAULT ;
>  
> -	if (ret == 0)
> +	if ( cmd == WLAN_SETNONE_GETONEINT ) {
>  		req->ifr_data = (char *)(le32_to_cpu(mesh_access.data[0]));

This breaks with sparse.  We should be doing stuff like this instead.
At least, that's how I _think_ it should be done :)

	struct iwreq *wrq = (struct iwreq *)req;

	...

	if (ret == 0)
		wrq->u.param.value = le32_to_cpu(param.id);

Dan

> -	else
> -		return -EFAULT;
> +	}
>  
> -	lbs_deb_leave(LBS_DEB_IOCTL);
> -	return 0;
> -}
> +	else if ( subcmd == cmd_act_mesh_get_link_costs ) {
> +		for (i = 0 ; i < COSTS_LIST_SIZE ; i++)
> +			ptr += sprintf (ptr, " %u", le32_to_cpu(mesh_access.data[i])) ;
> +		wrq->u.data.length = strlen(str);
>  
> -/**
> - *  @brief          Gets mesh ttl from firmware
> - *  @param priv     A pointer to wlan_private structure
> - *  @param ttl      New ttl value
> - *  @return         0 --success, otherwise fail
> - */
> -static int wlan_mesh_set_ttl_ioctl(wlan_private * priv, int ttl)
> -{
> -	struct cmd_ds_mesh_access mesh_access;
> -	int ret;
> -
> -	lbs_deb_enter(LBS_DEB_IOCTL);
> +		if (copy_to_user(wrq->u.data.pointer, (char *)str,
> +				 wrq->u.data.length)) {
> +			lbs_deb_ioctl("MESH_IOCTL: Copy to user failed!\n");
> +			ret = -EFAULT;
> +		}
> +	}
>  
> -	if( (ttl > 0xff) || (ttl < 0) )
> -		return -EINVAL;
> -	
> -	memset(&mesh_access, 0, sizeof(mesh_access));
> -	mesh_access.data[0] = ttl;
> -	
> -	ret = libertas_prepare_and_send_command(priv, cmd_mesh_access,
> -						cmd_act_mesh_set_ttl,
> -						cmd_option_waitforrsp, 0,
> -						(void *)&mesh_access);
> -	
> -	if (ret != 0)
> -		ret = -EFAULT;
> -	
>  	lbs_deb_leave(LBS_DEB_IOCTL);
> -	return ret;
> +	return ret ;
>  }
>  
>  /**
> @@ -2028,8 +2037,23 @@ int libertas_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
>  			break;
>  
>  		case WLAN_SUBCMD_MESH_SET_TTL:
> -			idata = SUBCMD_DATA(wrq);
> -			ret = wlan_mesh_set_ttl_ioctl(priv, idata);
> +			ret = wlan_mesh_ioctl(priv, req, cmd,
> +					cmd_act_mesh_set_ttl);
> +			break;
> +
> +		case WLAN_SUBCMD_MESH_SET_BCAST_RATE:
> +			ret = wlan_mesh_ioctl(priv, req, cmd,
> +					cmd_act_mesh_set_bcast_rate);
> +			break;
> +
> +		case WLAN_SUBCMD_MESH_SET_RREQ_DELAY:
> +			ret = wlan_mesh_ioctl(priv, req, cmd,
> +					cmd_act_mesh_set_rreq_delay) ;
> +			break;
> +
> +		case WLAN_SUBCMD_MESH_SET_ROUTE_EXP:
> +			ret = wlan_mesh_ioctl(priv, req, cmd,
> +					cmd_act_mesh_set_route_exp) ;
>  			break;
>  
>  		case WLAN_SUBCMD_BT_SET_INVERT:
> @@ -2102,6 +2126,14 @@ int libertas_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
>  		case WLAN_SUBCMD_FWT_LIST_ROUTE:
>  			ret = wlan_fwt_list_route_ioctl(priv, req);
>  			break;
> +		case WLAN_SUBCMD_MESH_SET_LINK_COSTS:
> +			ret = wlan_mesh_ioctl(priv, req, cmd,
> +					cmd_act_mesh_set_link_costs) ;
> +			break ;
> +		case WLAN_SUBCMD_MESH_GET_LINK_COSTS:
> +			ret = wlan_mesh_ioctl(priv, req, cmd,
> +					cmd_act_mesh_get_link_costs) ;
> +			break;
>  		}
>  		break;
>  
> @@ -2150,7 +2182,23 @@ int libertas_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
>  			break;
>  
>  		case WLAN_SUBCMD_MESH_GET_TTL:
> -			ret = wlan_mesh_get_ttl_ioctl(priv, req);
> +			ret = wlan_mesh_ioctl(priv, req, cmd,
> +					cmd_act_mesh_get_ttl) ;
> +			break;
> +
> +		case WLAN_SUBCMD_MESH_GET_BCAST_RATE:
> +			ret = wlan_mesh_ioctl(priv, req, cmd,
> +					cmd_act_mesh_get_bcast_rate) ;
> +			break;
> +
> +		case WLAN_SUBCMD_MESH_GET_RREQ_DELAY:
> +			ret = wlan_mesh_ioctl(priv, req, cmd,
> +					cmd_act_mesh_get_rreq_delay) ;
> +			break;
> +
> +		case WLAN_SUBCMD_MESH_GET_ROUTE_EXP:
> +			ret = wlan_mesh_ioctl(priv, req, cmd,
> +					cmd_act_mesh_get_route_exp) ;
>  			break;
>  
>  		case WLAN_SUBCMD_BT_GET_INVERT:
> diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
> index d48b211..b1b855b 100644
> --- a/drivers/net/wireless/libertas/wext.c
> +++ b/drivers/net/wireless/libertas/wext.c
> @@ -1062,6 +1062,21 @@ static const struct iw_priv_args wlan_private_args[] = {
>  	 IW_PRIV_TYPE_NONE,
>  	 "mesh_set_ttl"},
>  	{
> +	 WLAN_SUBCMD_MESH_SET_BCAST_RATE,
> +	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
> +	 IW_PRIV_TYPE_NONE,
> +	 "mesh_set_bcastr"},
> +	{
> +	 WLAN_SUBCMD_MESH_SET_RREQ_DELAY,
> +	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
> +	 IW_PRIV_TYPE_NONE,
> +	 "set_rreq_delay"},
> +	{
> +	 WLAN_SUBCMD_MESH_SET_ROUTE_EXP,
> +	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
> +	 IW_PRIV_TYPE_NONE,
> +	 "set_route_exp"},
> +	{
>  	 WLAN_SETNONE_GETONEINT,
>  	 IW_PRIV_TYPE_NONE,
>  	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
> @@ -1122,6 +1137,21 @@ static const struct iw_priv_args wlan_private_args[] = {
>  	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
>  	 "mesh_get_ttl"},
>  	{
> +	 WLAN_SUBCMD_MESH_GET_BCAST_RATE,
> +	 IW_PRIV_TYPE_NONE,
> +	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
> +	 "mesh_get_bcastr"},
> +	{
> +	 WLAN_SUBCMD_MESH_GET_RREQ_DELAY,
> +	 IW_PRIV_TYPE_NONE,
> +	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
> +	 "get_rreq_delay"},
> +	{
> +	 WLAN_SUBCMD_MESH_GET_ROUTE_EXP,
> +	 IW_PRIV_TYPE_NONE,
> +	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
> +	 "get_route_exp"},
> +	{
>  	 WLAN_SETNONE_GETTWELVE_CHAR,
>  	 IW_PRIV_TYPE_NONE,
>  	 IW_PRIV_TYPE_CHAR | 12,
> @@ -1142,6 +1172,16 @@ static const struct iw_priv_args wlan_private_args[] = {
>  	 IW_PRIV_TYPE_CHAR | 12,
>  	 "gettsf"},
>  	{
> +	 WLAN_SUBCMD_MESH_SET_LINK_COSTS,
> +	 IW_PRIV_TYPE_CHAR | 128,
> +	 IW_PRIV_TYPE_CHAR | 128,
> +	 "set_link_costs"},
> +	{
> +	 WLAN_SUBCMD_MESH_GET_LINK_COSTS,
> +	 IW_PRIV_TYPE_CHAR | 128,
> +	 IW_PRIV_TYPE_CHAR | 128,
> +	 "get_link_costs"},
> +	{
>  	 WLAN_SETNONE_GETNONE,
>  	 IW_PRIV_TYPE_NONE,
>  	 IW_PRIV_TYPE_NONE,
> diff --git a/drivers/net/wireless/libertas/wext.h b/drivers/net/wireless/libertas/wext.h
> index fdac44a..0f361ec 100644
> --- a/drivers/net/wireless/libertas/wext.h
> +++ b/drivers/net/wireless/libertas/wext.h
> @@ -4,6 +4,8 @@
>  #ifndef	_WLAN_WEXT_H_
>  #define	_WLAN_WEXT_H_
>  
> +#define COSTS_LIST_SIZE			4
> +
>  #define SUBCMD_OFFSET			4
>  #define SUBCMD_DATA(x)			*((int *)(x->u.name + SUBCMD_OFFSET))
>  
> @@ -52,6 +54,9 @@
>  #define WLAN_SUBCMD_FWT_TIME			16
>  #define WLAN_SUBCMD_MESH_GET_TTL		17
>  #define WLAN_SUBCMD_BT_GET_INVERT		18
> +#define WLAN_SUBCMD_MESH_GET_BCAST_RATE		19
> +#define WLAN_SUBCMD_MESH_GET_RREQ_DELAY		20
> +#define WLAN_SUBCMD_MESH_GET_ROUTE_EXP		21
>  
>  #define WLANREGCFRDWR			(WLANIOCTL + 18)
>  
> @@ -88,6 +93,9 @@
>  #define WLAN_SET_DEBUGMODE			17
>  #define WLAN_SUBCMD_MESH_SET_TTL		18
>  #define WLAN_SUBCMD_BT_SET_INVERT		19
> +#define WLAN_SUBCMD_MESH_SET_BCAST_RATE		20
> +#define WLAN_SUBCMD_MESH_SET_RREQ_DELAY		21
> +#define WLAN_SUBCMD_MESH_SET_ROUTE_EXP		22
>  
>  #define WLAN_SET128CHAR_GET128CHAR	(WLANIOCTL + 25)
>  #define WLANSCAN_MODE				6
> @@ -103,6 +111,8 @@
>  #define WLAN_SUBCMD_FWT_LIST_NEIGHBOR		24
>  #define WLAN_SUBCMD_FWT_LIST			25
>  #define WLAN_SUBCMD_FWT_LIST_ROUTE		26
> +#define WLAN_SUBCMD_MESH_SET_LINK_COSTS		27
> +#define WLAN_SUBCMD_MESH_GET_LINK_COSTS		28
>  
>  #define WLAN_SET_GET_SIXTEEN_INT       (WLANIOCTL + 29)
>  #define WLAN_TPCCFG                             1
> _______________________________________________
> libertas-dev mailing list
> libertas-dev at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/libertas-dev




More information about the libertas-dev mailing list