X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=net%2Fmac802154%2Fiface.c;h=f9ed608aa26034e965c9f26607e13ee8abf1eddd;hb=d5ae67bacd9654b0e26b9f248249e9ee1b6e338b;hp=e10fd786a11f31d1cf9d1dac81f66e255fb4bb24;hpb=0ea3da64fa602efa0a89502eefdb396be84d2eba;p=deliverable%2Flinux.git diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c index e10fd786a11f..f9ed608aa260 100644 --- a/net/mac802154/iface.c +++ b/net/mac802154/iface.c @@ -110,37 +110,21 @@ mac802154_wpan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) static int mac802154_wpan_mac_addr(struct net_device *dev, void *p) { + struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); struct sockaddr *addr = p; + __le64 extended_addr; if (netif_running(dev)) return -EBUSY; - /* FIXME: validate addr */ - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - mac802154_dev_set_ieee_addr(dev); - return mac802154_wpan_update_llsec(dev); -} - -int mac802154_set_mac_params(struct net_device *dev, - const struct ieee802154_mac_params *params) -{ - struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); - - mutex_lock(&sdata->local->iflist_mtx); - sdata->mac_params = *params; - mutex_unlock(&sdata->local->iflist_mtx); - - return 0; -} + extended_addr = ieee802154_netdev_to_extended_addr(addr->sa_data); + if (!ieee802154_is_valid_extended_addr(extended_addr)) + return -EINVAL; -void mac802154_get_mac_params(struct net_device *dev, - struct ieee802154_mac_params *params) -{ - struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); + sdata->extended_addr = extended_addr; - mutex_lock(&sdata->local->iflist_mtx); - *params = sdata->mac_params; - mutex_unlock(&sdata->local->iflist_mtx); + return mac802154_wpan_update_llsec(dev); } static int mac802154_slave_open(struct net_device *dev) @@ -166,19 +150,19 @@ static int mac802154_slave_open(struct net_device *dev) set_bit(SDATA_STATE_RUNNING, &sdata->state); - if (local->open_count++ == 0) { + if (!local->open_count) { res = drv_start(local); WARN_ON(res); if (res) goto err; } + local->open_count++; netif_start_queue(dev); return 0; err: /* might already be clear but that doesn't matter */ clear_bit(SDATA_STATE_RUNNING, &sdata->state); - sdata->local->open_count--; return res; } @@ -196,27 +180,28 @@ static int mac802154_wpan_open(struct net_device *dev) mutex_lock(&phy->pib_lock); - if (local->hw.flags & IEEE802154_HW_TXPOWER) { - rc = drv_set_tx_power(local, sdata->mac_params.transmit_power); + if (local->hw.flags & IEEE802154_HW_PROMISCUOUS) { + rc = drv_set_promiscuous_mode(local, sdata->promisuous_mode); if (rc < 0) goto out; } - if (local->hw.flags & IEEE802154_HW_LBT) { - rc = drv_set_lbt_mode(local, sdata->mac_params.lbt); + if (local->hw.flags & IEEE802154_HW_AFILT) { + rc = drv_set_pan_id(local, sdata->pan_id); + if (rc < 0) + goto out; + + rc = drv_set_extended_addr(local, sdata->extended_addr); if (rc < 0) goto out; - } - if (local->hw.flags & IEEE802154_HW_CCA_MODE) { - rc = drv_set_cca_mode(local, sdata->mac_params.cca_mode); + rc = drv_set_short_addr(local, sdata->short_addr); if (rc < 0) goto out; } - if (local->hw.flags & IEEE802154_HW_CCA_ED_LEVEL) { - rc = drv_set_cca_ed_level(local, - sdata->mac_params.cca_ed_level); + if (local->hw.flags & IEEE802154_HW_LBT) { + rc = drv_set_lbt_mode(local, sdata->mac_params.lbt); if (rc < 0) goto out; } @@ -252,10 +237,11 @@ static int mac802154_slave_close(struct net_device *dev) ASSERT_RTNL(); netif_stop_queue(dev); + local->open_count--; clear_bit(SDATA_STATE_RUNNING, &sdata->state); - if (!--local->open_count) + if (!local->open_count) drv_stop(local); return 0; @@ -381,7 +367,7 @@ static const struct net_device_ops mac802154_wpan_ops = { }; static const struct net_device_ops mac802154_monitor_ops = { - .ndo_open = mac802154_slave_open, + .ndo_open = mac802154_wpan_open, .ndo_stop = mac802154_slave_close, .ndo_start_xmit = ieee802154_monitor_start_xmit, }; @@ -395,34 +381,23 @@ static void mac802154_wpan_free(struct net_device *dev) free_netdev(dev); } -void mac802154_wpan_setup(struct net_device *dev) +static void ieee802154_if_setup(struct net_device *dev) { - struct ieee802154_sub_if_data *sdata; - dev->addr_len = IEEE802154_ADDR_LEN; memset(dev->broadcast, 0xff, IEEE802154_ADDR_LEN); dev->hard_header_len = MAC802154_FRAME_HARD_HEADER_LEN; - dev->header_ops = &mac802154_header_ops; dev->needed_tailroom = 2 + 16; /* FCS + MIC */ dev->mtu = IEEE802154_MTU; dev->tx_queue_len = 300; - dev->type = ARPHRD_IEEE802154; dev->flags = IFF_NOARP | IFF_BROADCAST; - dev->watchdog_timeo = 0; - - dev->destructor = mac802154_wpan_free; - dev->netdev_ops = &mac802154_wpan_ops; - dev->ml_priv = &mac802154_mlme_wpan; - - sdata = IEEE802154_DEV_TO_SUB_IF(dev); - sdata->type = IEEE802154_DEV_WPAN; - - sdata->chan = MAC802154_CHAN_NONE; - sdata->page = 0; +} - spin_lock_init(&sdata->mib_lock); - mutex_init(&sdata->sec_mtx); +static int +ieee802154_setup_sdata(struct ieee802154_sub_if_data *sdata, int type) +{ + /* set some type-dependent values */ + sdata->type = type; get_random_bytes(&sdata->bsn, 1); get_random_bytes(&sdata->dsn, 1); @@ -437,29 +412,107 @@ void mac802154_wpan_setup(struct net_device *dev) sdata->pan_id = cpu_to_le16(IEEE802154_PANID_BROADCAST); sdata->short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST); - mac802154_llsec_init(&sdata->sec); + switch (type) { + case IEEE802154_DEV_WPAN: + sdata->dev->header_ops = &mac802154_header_ops; + sdata->dev->destructor = mac802154_wpan_free; + sdata->dev->netdev_ops = &mac802154_wpan_ops; + sdata->dev->ml_priv = &mac802154_mlme_wpan; + sdata->promisuous_mode = false; + + spin_lock_init(&sdata->mib_lock); + mutex_init(&sdata->sec_mtx); + + mac802154_llsec_init(&sdata->sec); + break; + case IEEE802154_DEV_MONITOR: + sdata->dev->destructor = free_netdev; + sdata->dev->netdev_ops = &mac802154_monitor_ops; + sdata->dev->ml_priv = &mac802154_mlme_reduced; + sdata->promisuous_mode = true; + break; + default: + BUG(); + } + + return 0; } -void mac802154_monitor_setup(struct net_device *dev) +struct net_device * +ieee802154_if_add(struct ieee802154_local *local, const char *name, + struct wpan_dev **new_wpan_dev, int type) { - struct ieee802154_sub_if_data *sdata; + struct net_device *ndev = NULL; + struct ieee802154_sub_if_data *sdata = NULL; + int ret = -ENOMEM; - dev->addr_len = 0; - dev->hard_header_len = 0; - dev->needed_tailroom = 2; /* room for FCS */ - dev->mtu = IEEE802154_MTU; - dev->tx_queue_len = 10; - dev->type = ARPHRD_IEEE802154_MONITOR; - dev->flags = IFF_NOARP | IFF_BROADCAST; - dev->watchdog_timeo = 0; + ASSERT_RTNL(); - dev->destructor = free_netdev; - dev->netdev_ops = &mac802154_monitor_ops; - dev->ml_priv = &mac802154_mlme_reduced; + ndev = alloc_netdev(sizeof(*sdata), name, NET_NAME_UNKNOWN, + ieee802154_if_setup); + if (!ndev) + return ERR_PTR(-ENOMEM); - sdata = IEEE802154_DEV_TO_SUB_IF(dev); - sdata->type = IEEE802154_DEV_MONITOR; + ndev->needed_headroom = local->hw.extra_tx_headroom; + + ret = dev_alloc_name(ndev, ndev->name); + if (ret < 0) + goto err; + + switch (type) { + case IEEE802154_DEV_WPAN: + ndev->type = ARPHRD_IEEE802154; + break; + case IEEE802154_DEV_MONITOR: + ndev->type = ARPHRD_IEEE802154_MONITOR; + break; + default: + ret = -EINVAL; + goto err; + } + + /* TODO check this */ + SET_NETDEV_DEV(ndev, &local->phy->dev); + sdata = netdev_priv(ndev); + ndev->ieee802154_ptr = &sdata->wpan_dev; + memcpy(sdata->name, ndev->name, IFNAMSIZ); + sdata->dev = ndev; + sdata->wpan_dev.wpan_phy = local->hw.phy; + sdata->local = local; + + /* setup type-dependent data */ + ret = ieee802154_setup_sdata(sdata, type); + if (ret) + goto err; + + if (ndev) { + ret = register_netdevice(ndev); + if (ret < 0) + goto err; + } + + mutex_lock(&local->iflist_mtx); + list_add_tail_rcu(&sdata->list, &local->interfaces); + mutex_unlock(&local->iflist_mtx); + + if (new_wpan_dev) + *new_wpan_dev = &sdata->wpan_dev; + + return ndev; + +err: + free_netdev(ndev); + return ERR_PTR(ret); +} + +void ieee802154_if_remove(struct ieee802154_sub_if_data *sdata) +{ + ASSERT_RTNL(); + + mutex_lock(&sdata->local->iflist_mtx); + list_del_rcu(&sdata->list); + mutex_unlock(&sdata->local->iflist_mtx); - sdata->chan = MAC802154_CHAN_NONE; /* not initialized */ - sdata->page = 0; + synchronize_rcu(); + unregister_netdevice(sdata->dev); }