[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