Commit 6164c202 authored by John W. Linville's avatar John W. Linville

Merge branch 'for-upstream' of...

Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
parents bf515fb1 56b2c3ee
...@@ -4699,7 +4699,6 @@ F: net/mac802154/ ...@@ -4699,7 +4699,6 @@ F: net/mac802154/
F: drivers/net/ieee802154/ F: drivers/net/ieee802154/
F: include/linux/nl802154.h F: include/linux/nl802154.h
F: include/linux/ieee802154.h F: include/linux/ieee802154.h
F: include/net/nl802154.h
F: include/net/mac802154.h F: include/net/mac802154.h
F: include/net/af_ieee802154.h F: include/net/af_ieee802154.h
F: include/net/cfg802154.h F: include/net/cfg802154.h
......
...@@ -299,6 +299,8 @@ struct btusb_data { ...@@ -299,6 +299,8 @@ struct btusb_data {
unsigned int sco_num; unsigned int sco_num;
int isoc_altsetting; int isoc_altsetting;
int suspend_count; int suspend_count;
int (*recv_bulk)(struct btusb_data *data, void *buffer, int count);
}; };
static inline void btusb_free_frags(struct btusb_data *data) static inline void btusb_free_frags(struct btusb_data *data)
...@@ -590,7 +592,7 @@ static void btusb_bulk_complete(struct urb *urb) ...@@ -590,7 +592,7 @@ static void btusb_bulk_complete(struct urb *urb)
if (urb->status == 0) { if (urb->status == 0) {
hdev->stat.byte_rx += urb->actual_length; hdev->stat.byte_rx += urb->actual_length;
if (btusb_recv_bulk(data, urb->transfer_buffer, if (data->recv_bulk(data, urb->transfer_buffer,
urb->actual_length) < 0) { urb->actual_length) < 0) {
BT_ERR("%s corrupted ACL packet", hdev->name); BT_ERR("%s corrupted ACL packet", hdev->name);
hdev->stat.err_rx++; hdev->stat.err_rx++;
...@@ -2012,6 +2014,8 @@ static int btusb_probe(struct usb_interface *intf, ...@@ -2012,6 +2014,8 @@ static int btusb_probe(struct usb_interface *intf,
init_usb_anchor(&data->isoc_anchor); init_usb_anchor(&data->isoc_anchor);
spin_lock_init(&data->rxlock); spin_lock_init(&data->rxlock);
data->recv_bulk = btusb_recv_bulk;
hdev = hci_alloc_dev(); hdev = hci_alloc_dev();
if (!hdev) if (!hdev)
return -ENOMEM; return -ENOMEM;
...@@ -2035,6 +2039,7 @@ static int btusb_probe(struct usb_interface *intf, ...@@ -2035,6 +2039,7 @@ static int btusb_probe(struct usb_interface *intf,
if (id->driver_info & BTUSB_BCM_PATCHRAM) { if (id->driver_info & BTUSB_BCM_PATCHRAM) {
hdev->setup = btusb_setup_bcm_patchram; hdev->setup = btusb_setup_bcm_patchram;
hdev->set_bdaddr = btusb_set_bdaddr_bcm; hdev->set_bdaddr = btusb_set_bdaddr_bcm;
set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks);
} }
if (id->driver_info & BTUSB_INTEL) { if (id->driver_info & BTUSB_INTEL) {
......
...@@ -171,8 +171,6 @@ static void h5_timed_event(unsigned long arg) ...@@ -171,8 +171,6 @@ static void h5_timed_event(unsigned long arg)
static void h5_peer_reset(struct hci_uart *hu) static void h5_peer_reset(struct hci_uart *hu)
{ {
struct h5 *h5 = hu->priv; struct h5 *h5 = hu->priv;
struct sk_buff *skb;
const unsigned char hard_err[] = { 0x10, 0x01, 0x00 };
BT_ERR("Peer device has reset"); BT_ERR("Peer device has reset");
...@@ -187,15 +185,8 @@ static void h5_peer_reset(struct hci_uart *hu) ...@@ -187,15 +185,8 @@ static void h5_peer_reset(struct hci_uart *hu)
h5->tx_seq = 0; h5->tx_seq = 0;
h5->tx_ack = 0; h5->tx_ack = 0;
skb = bt_skb_alloc(3, GFP_ATOMIC); /* Send reset request to upper stack */
if (!skb) hci_reset_dev(hu->hdev);
return;
bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
memcpy(skb_put(skb, 3), hard_err, 3);
/* Send Hardware Error to upper stack */
hci_recv_frame(hu->hdev, skb);
} }
static int h5_open(struct hci_uart *hu) static int h5_open(struct hci_uart *hu)
......
...@@ -1047,7 +1047,7 @@ at86rf230_channel(struct ieee802154_hw *hw, u8 page, u8 channel) ...@@ -1047,7 +1047,7 @@ at86rf230_channel(struct ieee802154_hw *hw, u8 page, u8 channel)
struct at86rf230_local *lp = hw->priv; struct at86rf230_local *lp = hw->priv;
int rc; int rc;
if (page < 0 || page > 31 || if (page > 31 ||
!(lp->hw->phy->channels_supported[page] & BIT(channel))) { !(lp->hw->phy->channels_supported[page] & BIT(channel))) {
WARN_ON(1); WARN_ON(1);
return -EINVAL; return -EINVAL;
...@@ -1358,7 +1358,11 @@ static int at86rf230_hw_init(struct at86rf230_local *lp) ...@@ -1358,7 +1358,11 @@ static int at86rf230_hw_init(struct at86rf230_local *lp)
return -EINVAL; return -EINVAL;
} }
return 0; /* Force setting slotted operation bit to 0. Sometimes the atben
* sets this bit and I don't know why. We set this always force
* to zero while probing.
*/
return at86rf230_write_subreg(lp, SR_SLOTTED_OPERATION, 0);
} }
static struct at86rf230_platform_data * static struct at86rf230_platform_data *
...@@ -1427,6 +1431,7 @@ at86rf230_detect_device(struct at86rf230_local *lp) ...@@ -1427,6 +1431,7 @@ at86rf230_detect_device(struct at86rf230_local *lp)
chip = "at86rf231"; chip = "at86rf231";
lp->data = &at86rf231_data; lp->data = &at86rf231_data;
lp->hw->phy->channels_supported[0] = 0x7FFF800; lp->hw->phy->channels_supported[0] = 0x7FFF800;
lp->hw->phy->current_channel = 11;
break; break;
case 7: case 7:
chip = "at86rf212"; chip = "at86rf212";
...@@ -1435,6 +1440,7 @@ at86rf230_detect_device(struct at86rf230_local *lp) ...@@ -1435,6 +1440,7 @@ at86rf230_detect_device(struct at86rf230_local *lp)
lp->hw->flags |= IEEE802154_HW_LBT; lp->hw->flags |= IEEE802154_HW_LBT;
lp->hw->phy->channels_supported[0] = 0x00007FF; lp->hw->phy->channels_supported[0] = 0x00007FF;
lp->hw->phy->channels_supported[2] = 0x00007FF; lp->hw->phy->channels_supported[2] = 0x00007FF;
lp->hw->phy->current_channel = 5;
} else { } else {
rc = -ENOTSUPP; rc = -ENOTSUPP;
} }
...@@ -1443,6 +1449,7 @@ at86rf230_detect_device(struct at86rf230_local *lp) ...@@ -1443,6 +1449,7 @@ at86rf230_detect_device(struct at86rf230_local *lp)
chip = "at86rf233"; chip = "at86rf233";
lp->data = &at86rf233_data; lp->data = &at86rf233_data;
lp->hw->phy->channels_supported[0] = 0x7FFF800; lp->hw->phy->channels_supported[0] = 0x7FFF800;
lp->hw->phy->current_channel = 13;
break; break;
default: default:
chip = "unkown"; chip = "unkown";
...@@ -1530,6 +1537,8 @@ static int at86rf230_probe(struct spi_device *spi) ...@@ -1530,6 +1537,8 @@ static int at86rf230_probe(struct spi_device *spi)
lp->hw = hw; lp->hw = hw;
lp->spi = spi; lp->spi = spi;
hw->parent = &spi->dev; hw->parent = &spi->dev;
hw->vif_data_size = sizeof(*lp);
ieee802154_random_extended_addr(&hw->phy->perm_extended_addr);
lp->regmap = devm_regmap_init_spi(spi, &at86rf230_regmap_spi_config); lp->regmap = devm_regmap_init_spi(spi, &at86rf230_regmap_spi_config);
if (IS_ERR(lp->regmap)) { if (IS_ERR(lp->regmap)) {
......
...@@ -651,6 +651,7 @@ static int cc2520_register(struct cc2520_private *priv) ...@@ -651,6 +651,7 @@ static int cc2520_register(struct cc2520_private *priv)
priv->hw->priv = priv; priv->hw->priv = priv;
priv->hw->parent = &priv->spi->dev; priv->hw->parent = &priv->spi->dev;
priv->hw->extra_tx_headroom = 0; priv->hw->extra_tx_headroom = 0;
priv->hw->vif_data_size = sizeof(*priv);
/* We do support only 2.4 Ghz */ /* We do support only 2.4 Ghz */
priv->hw->phy->channels_supported[0] = 0x7FFF800; priv->hw->phy->channels_supported[0] = 0x7FFF800;
......
...@@ -24,10 +24,14 @@ ...@@ -24,10 +24,14 @@
#define LINUX_IEEE802154_H #define LINUX_IEEE802154_H
#include <linux/types.h> #include <linux/types.h>
#include <linux/random.h>
#include <asm/byteorder.h>
#define IEEE802154_MTU 127 #define IEEE802154_MTU 127
#define IEEE802154_MIN_PSDU_LEN 5 #define IEEE802154_MIN_PSDU_LEN 5
#define IEEE802154_EXTENDED_ADDR_LEN 8
#define IEEE802154_FC_TYPE_BEACON 0x0 /* Frame is beacon */ #define IEEE802154_FC_TYPE_BEACON 0x0 /* Frame is beacon */
#define IEEE802154_FC_TYPE_DATA 0x1 /* Frame is data */ #define IEEE802154_FC_TYPE_DATA 0x1 /* Frame is data */
#define IEEE802154_FC_TYPE_ACK 0x2 /* Frame is acknowledgment */ #define IEEE802154_FC_TYPE_ACK 0x2 /* Frame is acknowledgment */
...@@ -197,4 +201,32 @@ static inline bool ieee802154_is_valid_psdu_len(const u8 len) ...@@ -197,4 +201,32 @@ static inline bool ieee802154_is_valid_psdu_len(const u8 len)
return (len >= IEEE802154_MIN_PSDU_LEN && len <= IEEE802154_MTU); return (len >= IEEE802154_MIN_PSDU_LEN && len <= IEEE802154_MTU);
} }
/**
* ieee802154_is_valid_psdu_len - check if extended addr is valid
* @addr: extended addr to check
*/
static inline bool ieee802154_is_valid_extended_addr(const __le64 addr)
{
/* These EUI-64 addresses are reserved by IEEE. 0xffffffffffffffff
* is used internally as extended to short address broadcast mapping.
* This is currently a workaround because neighbor discovery can't
* deal with short addresses types right now.
*/
return ((addr != cpu_to_le64(0x0000000000000000ULL)) &&
(addr != cpu_to_le64(0xffffffffffffffffULL)));
}
/**
* ieee802154_random_extended_addr - generates a random extended address
* @addr: extended addr pointer to place the random address
*/
static inline void ieee802154_random_extended_addr(__le64 *addr)
{
get_random_bytes(addr, IEEE802154_EXTENDED_ADDR_LEN);
/* toggle some bit if we hit an invalid extended addr */
if (!ieee802154_is_valid_extended_addr(*addr))
((u8 *)addr)[IEEE802154_EXTENDED_ADDR_LEN - 1] ^= 0x01;
}
#endif /* LINUX_IEEE802154_H */ #endif /* LINUX_IEEE802154_H */
...@@ -57,6 +57,8 @@ struct device; ...@@ -57,6 +57,8 @@ struct device;
struct phy_device; struct phy_device;
/* 802.11 specific */ /* 802.11 specific */
struct wireless_dev; struct wireless_dev;
/* 802.15.4 specific */
struct wpan_dev;
void netdev_set_default_ethtool_ops(struct net_device *dev, void netdev_set_default_ethtool_ops(struct net_device *dev,
const struct ethtool_ops *ops); const struct ethtool_ops *ops);
...@@ -1572,6 +1574,7 @@ struct net_device { ...@@ -1572,6 +1574,7 @@ struct net_device {
struct inet6_dev __rcu *ip6_ptr; struct inet6_dev __rcu *ip6_ptr;
void *ax25_ptr; void *ax25_ptr;
struct wireless_dev *ieee80211_ptr; struct wireless_dev *ieee80211_ptr;
struct wpan_dev *ieee802154_ptr;
/* /*
* Cache lines mostly used on receive path (including eth_type_trans()) * Cache lines mostly used on receive path (including eth_type_trans())
......
...@@ -129,6 +129,15 @@ enum { ...@@ -129,6 +129,15 @@ enum {
* during the hdev->setup vendor callback. * during the hdev->setup vendor callback.
*/ */
HCI_QUIRK_INVALID_BDADDR, HCI_QUIRK_INVALID_BDADDR,
/* When this quirk is set, the duplicate filtering during
* scanning is based on Bluetooth devices addresses. To allow
* RSSI based updates, restart scanning if needed.
*
* This quirk can be set before hci_register_dev is called or
* during the hdev->setup vendor callback.
*/
HCI_QUIRK_STRICT_DUPLICATE_FILTER,
}; };
/* HCI device flags */ /* HCI device flags */
...@@ -265,6 +274,7 @@ enum { ...@@ -265,6 +274,7 @@ enum {
/* Low Energy links do not have defined link type. Use invented one */ /* Low Energy links do not have defined link type. Use invented one */
#define LE_LINK 0x80 #define LE_LINK 0x80
#define AMP_LINK 0x81 #define AMP_LINK 0x81
#define INVALID_LINK 0xff
/* LMP features */ /* LMP features */
#define LMP_3SLOT 0x01 #define LMP_3SLOT 0x01
...@@ -1463,6 +1473,11 @@ struct hci_ev_cmd_status { ...@@ -1463,6 +1473,11 @@ struct hci_ev_cmd_status {
__le16 opcode; __le16 opcode;
} __packed; } __packed;
#define HCI_EV_HARDWARE_ERROR 0x10
struct hci_ev_hardware_error {
__u8 code;
} __packed;
#define HCI_EV_ROLE_CHANGE 0x12 #define HCI_EV_ROLE_CHANGE 0x12
struct hci_ev_role_change { struct hci_ev_role_change {
__u8 status; __u8 status;
......
...@@ -646,6 +646,26 @@ static inline unsigned int hci_conn_count(struct hci_dev *hdev) ...@@ -646,6 +646,26 @@ static inline unsigned int hci_conn_count(struct hci_dev *hdev)
return c->acl_num + c->amp_num + c->sco_num + c->le_num; return c->acl_num + c->amp_num + c->sco_num + c->le_num;
} }
static inline __u8 hci_conn_lookup_type(struct hci_dev *hdev, __u16 handle)
{
struct hci_conn_hash *h = &hdev->conn_hash;
struct hci_conn *c;
__u8 type = INVALID_LINK;
rcu_read_lock();
list_for_each_entry_rcu(c, &h->list, list) {
if (c->handle == handle) {
type = c->type;
break;
}
}
rcu_read_unlock();
return type;
}
static inline struct hci_conn *hci_conn_hash_lookup_handle(struct hci_dev *hdev, static inline struct hci_conn *hci_conn_hash_lookup_handle(struct hci_dev *hdev,
__u16 handle) __u16 handle)
{ {
...@@ -856,6 +876,7 @@ int hci_register_dev(struct hci_dev *hdev); ...@@ -856,6 +876,7 @@ int hci_register_dev(struct hci_dev *hdev);
void hci_unregister_dev(struct hci_dev *hdev); void hci_unregister_dev(struct hci_dev *hdev);
int hci_suspend_dev(struct hci_dev *hdev); int hci_suspend_dev(struct hci_dev *hdev);
int hci_resume_dev(struct hci_dev *hdev); int hci_resume_dev(struct hci_dev *hdev);
int hci_reset_dev(struct hci_dev *hdev);
int hci_dev_open(__u16 dev); int hci_dev_open(__u16 dev);
int hci_dev_close(__u16 dev); int hci_dev_close(__u16 dev);
int hci_dev_reset(__u16 dev); int hci_dev_reset(__u16 dev);
......
...@@ -29,6 +29,16 @@ ...@@ -29,6 +29,16 @@
#define WPAN_NUM_CHANNELS 27 #define WPAN_NUM_CHANNELS 27
#define WPAN_NUM_PAGES 32 #define WPAN_NUM_PAGES 32
struct wpan_phy;
struct cfg802154_ops {
struct net_device * (*add_virtual_intf_deprecated)(struct wpan_phy *wpan_phy,
const char *name,
int type);
void (*del_virtual_intf_deprecated)(struct wpan_phy *wpan_phy,
struct net_device *dev);
};
struct wpan_phy { struct wpan_phy {
struct mutex pib_lock; struct mutex pib_lock;
...@@ -47,22 +57,24 @@ struct wpan_phy { ...@@ -47,22 +57,24 @@ struct wpan_phy {
u8 csma_retries; u8 csma_retries;
s8 frame_retries; s8 frame_retries;
__le64 perm_extended_addr;
bool lbt; bool lbt;
s32 cca_ed_level; s32 cca_ed_level;
struct device dev; struct device dev;
int idx;
struct net_device *(*add_iface)(struct wpan_phy *phy,
const char *name, int type);
void (*del_iface)(struct wpan_phy *phy, struct net_device *dev);
char priv[0] __aligned(NETDEV_ALIGN); char priv[0] __aligned(NETDEV_ALIGN);
}; };
struct wpan_dev {
struct wpan_phy *wpan_phy;
};
#define to_phy(_dev) container_of(_dev, struct wpan_phy, dev) #define to_phy(_dev) container_of(_dev, struct wpan_phy, dev)
struct wpan_phy *wpan_phy_alloc(size_t priv_size); struct wpan_phy *
wpan_phy_alloc(const struct cfg802154_ops *ops, size_t priv_size);
static inline void wpan_phy_set_dev(struct wpan_phy *phy, struct device *dev) static inline void wpan_phy_set_dev(struct wpan_phy *phy, struct device *dev)
{ {
phy->dev.parent = dev; phy->dev.parent = dev;
......
...@@ -423,8 +423,6 @@ struct ieee802154_mlme_ops { ...@@ -423,8 +423,6 @@ struct ieee802154_mlme_ops {
/* The fields below are required. */ /* The fields below are required. */
struct wpan_phy *(*get_phy)(const struct net_device *dev);
/* /*
* FIXME: these should become the part of PIB/MIB interface. * FIXME: these should become the part of PIB/MIB interface.
* However we still don't have IB interface of any kind * However we still don't have IB interface of any kind
...@@ -434,16 +432,6 @@ struct ieee802154_mlme_ops { ...@@ -434,16 +432,6 @@ struct ieee802154_mlme_ops {
u8 (*get_dsn)(const struct net_device *dev); u8 (*get_dsn)(const struct net_device *dev);
}; };
/* The IEEE 802.15.4 standard defines 2 type of the devices:
* - FFD - full functionality device
* - RFD - reduce functionality device
*
* So 2 sets of mlme operations are needed
*/
struct ieee802154_reduced_mlme_ops {
struct wpan_phy *(*get_phy)(const struct net_device *dev);
};
static inline struct ieee802154_mlme_ops * static inline struct ieee802154_mlme_ops *
ieee802154_mlme_ops(const struct net_device *dev) ieee802154_mlme_ops(const struct net_device *dev)
{ {
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#define NET_MAC802154_H #define NET_MAC802154_H
#include <net/af_ieee802154.h> #include <net/af_ieee802154.h>
#include <linux/ieee802154.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
/* General MAC frame format: /* General MAC frame format:
...@@ -52,6 +53,13 @@ struct ieee802154_hw_addr_filt { ...@@ -52,6 +53,13 @@ struct ieee802154_hw_addr_filt {
u8 pan_coord; u8 pan_coord;
}; };
struct ieee802154_vif {
int type;
/* must be last */
u8 drv_priv[0] __aligned(sizeof(void *));
};
struct ieee802154_hw { struct ieee802154_hw {
/* filled by the driver */ /* filled by the driver */
int extra_tx_headroom; int extra_tx_headroom;
...@@ -62,6 +70,7 @@ struct ieee802154_hw { ...@@ -62,6 +70,7 @@ struct ieee802154_hw {
struct ieee802154_hw_addr_filt hw_filt; struct ieee802154_hw_addr_filt hw_filt;
void *priv; void *priv;
struct wpan_phy *phy; struct wpan_phy *phy;
size_t vif_data_size;
}; };
/* Checksum is in hardware and is omitted from a packet /* Checksum is in hardware and is omitted from a packet
...@@ -214,6 +223,30 @@ struct ieee802154_ops { ...@@ -214,6 +223,30 @@ struct ieee802154_ops {
const bool on); const bool on);
}; };
/**
* ieee802154_be64_to_le64 - copies and convert be64 to le64
* @le64_dst: le64 destination pointer
* @be64_src: be64 source pointer
*/
static inline void ieee802154_be64_to_le64(void *le64_dst, const void *be64_src)
{
__le64 tmp = (__force __le64)swab64p(be64_src);
memcpy(le64_dst, &tmp, IEEE802154_EXTENDED_ADDR_LEN);
}
/**
* ieee802154_le64_to_be64 - copies and convert le64 to be64
* @be64_dst: be64 destination pointer
* @le64_src: le64 source pointer
*/
static inline void ieee802154_le64_to_be64(void *be64_dst, const void *le64_src)
{
__be64 tmp = (__force __be64)swab64p(le64_src);
memcpy(be64_dst, &tmp, IEEE802154_EXTENDED_ADDR_LEN);
}
/* Basic interface to register ieee802154 hwice */ /* Basic interface to register ieee802154 hwice */
struct ieee802154_hw * struct ieee802154_hw *
ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops); ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops);
......
/*
* nl802154.h
*
* Copyright (C) 2007, 2008, 2009 Siemens AG
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef IEEE802154_NL_H
#define IEEE802154_NL_H
struct net_device;
struct ieee802154_addr;
/**
* ieee802154_nl_assoc_indic - Notify userland of an association request.
* @dev: The network device on which this association request was
* received.
* @addr: The address of the device requesting association.
* @cap: The capability information field from the device.
*
* This informs a userland coordinator of a device requesting to
* associate with the PAN controlled by the coordinator.
*
* Note: This is in section 7.3.1 of the IEEE 802.15.4-2006 document.
*/
int ieee802154_nl_assoc_indic(struct net_device *dev,
struct ieee802154_addr *addr, u8 cap);
/**
* ieee802154_nl_assoc_confirm - Notify userland of association.
* @dev: The device which has completed association.
* @short_addr: The short address assigned to the device.
* @status: The status of the association.
*
* Inform userland of the result of an association request. If the
* association request included asking the coordinator to allocate
* a short address then it is returned in @short_addr.
*
* Note: This is in section 7.3.2 of the IEEE 802.15.4 document.
*/
int ieee802154_nl_assoc_confirm(struct net_device *dev,
__le16 short_addr, u8 status);
/**
* ieee802154_nl_disassoc_indic - Notify userland of disassociation.
* @dev: The device on which disassociation was indicated.
* @addr: The device which is disassociating.
* @reason: The reason for the disassociation.
*
* Inform userland that a device has disassociated from the network.
*
* Note: This is in section 7.3.3 of the IEEE 802.15.4 document.
*/
int ieee802154_nl_disassoc_indic(struct net_device *dev,
struct ieee802154_addr *addr, u8 reason);
/**
* ieee802154_nl_disassoc_confirm - Notify userland of disassociation
* completion.
* @dev: The device on which disassociation was ordered.
* @status: The result of the disassociation.
*
* Inform userland of the result of requesting that a device
* disassociate, or the result of requesting that we disassociate from
* a PAN managed by another coordinator.
*
* Note: This is in section 7.1.4.3 of the IEEE 802.15.4 document.
*/
int ieee802154_nl_disassoc_confirm(struct net_device *dev,
u8 status);
/**
* ieee802154_nl_scan_confirm - Notify userland of completion of scan.
* @dev: The device which was instructed to scan.
* @status: The status of the scan operation.
* @scan_type: What type of scan was performed.
* @unscanned: Any channels that the device was unable to scan.
* @edl: The energy levels (if a passive scan).
*
*
* Note: This is in section 7.1.11 of the IEEE 802.15.4 document.
* Note: This API does not permit the return of an active scan result.
*/
int ieee802154_nl_scan_confirm(struct net_device *dev,
u8 status, u8 scan_type, u32 unscanned, u8 page,
u8 *edl/*, struct list_head *pan_desc_list */);
/**
* ieee802154_nl_beacon_indic - Notify userland of a received beacon.
* @dev: The device on which a beacon was received.
* @panid: The PAN of the coordinator.
* @coord_addr: The short address of the coordinator on that PAN.
*
* Note: This is in section 7.1.5 of the IEEE 802.15.4 document.
* Note: This API does not provide extended information such as what
* channel the PAN is on or what the LQI of the beacon frame was on
* receipt.
* Note: This API cannot indicate a beacon frame for a coordinator
* operating in long addressing mode.
*/
int ieee802154_nl_beacon_indic(struct net_device *dev, __le16 panid,
__le16 coord_addr);
/**
* ieee802154_nl_start_confirm - Notify userland of completion of start.
* @dev: The device which was instructed to scan.
* @status: The status of the scan operation.
*
* Note: This is in section 7.1.14 of the IEEE 802.15.4 document.
*/
int ieee802154_nl_start_confirm(struct net_device *dev, u8 status);
#endif
...@@ -319,7 +319,7 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, ...@@ -319,7 +319,7 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev,
if (iphc1 & LOWPAN_IPHC_CID) { if (iphc1 & LOWPAN_IPHC_CID) {
pr_debug("CID flag is set, increase header with one\n"); pr_debug("CID flag is set, increase header with one\n");
if (lowpan_fetch_skb(skb, &num_context, sizeof(num_context))) if (lowpan_fetch_skb(skb, &num_context, sizeof(num_context)))
goto drop; return -EINVAL;
} }
hdr.version = 6; hdr.version = 6;
...@@ -331,7 +331,7 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, ...@@ -331,7 +331,7 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev,
*/ */
case 0: /* 00b */ case 0: /* 00b */
if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp))) if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp)))
goto drop; return -EINVAL;
memcpy(&hdr.flow_lbl, &skb->data[0], 3); memcpy(&hdr.flow_lbl, &skb->data[0], 3);
skb_pull(skb, 3); skb_pull(skb, 3);
...@@ -344,7 +344,7 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, ...@@ -344,7 +344,7 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev,
*/ */
case 2: /* 10b */ case 2: /* 10b */
if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp))) if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp)))
goto drop; return -EINVAL;
hdr.priority = ((tmp >> 2) & 0x0f); hdr.priority = ((tmp >> 2) & 0x0f);
hdr.flow_lbl[0] = ((tmp << 6) & 0xC0) | ((tmp >> 2) & 0x30); hdr.flow_lbl[0] = ((tmp << 6) & 0xC0) | ((tmp >> 2) & 0x30);
...@@ -354,7 +354,7 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, ...@@ -354,7 +354,7 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev,
*/ */
case 1: /* 01b */ case 1: /* 01b */
if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp))) if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp)))
goto drop; return -EINVAL;
hdr.flow_lbl[0] = (skb->data[0] & 0x0F) | ((tmp >> 2) & 0x30); hdr.flow_lbl[0] = (skb->data[0] & 0x0F) | ((tmp >> 2) & 0x30);
memcpy(&hdr.flow_lbl[1], &skb->data[0], 2); memcpy(&hdr.flow_lbl[1], &skb->data[0], 2);
...@@ -371,7 +371,7 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, ...@@ -371,7 +371,7 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev,
if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) { if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) {
/* Next header is carried inline */ /* Next header is carried inline */
if (lowpan_fetch_skb(skb, &hdr.nexthdr, sizeof(hdr.nexthdr))) if (lowpan_fetch_skb(skb, &hdr.nexthdr, sizeof(hdr.nexthdr)))
goto drop; return -EINVAL;
pr_debug("NH flag is set, next header carried inline: %02x\n", pr_debug("NH flag is set, next header carried inline: %02x\n",
hdr.nexthdr); hdr.nexthdr);
...@@ -383,7 +383,7 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, ...@@ -383,7 +383,7 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev,
} else { } else {
if (lowpan_fetch_skb(skb, &hdr.hop_limit, if (lowpan_fetch_skb(skb, &hdr.hop_limit,
sizeof(hdr.hop_limit))) sizeof(hdr.hop_limit)))
goto drop; return -EINVAL;
} }
/* Extract SAM to the tmp variable */ /* Extract SAM to the tmp variable */
...@@ -402,7 +402,7 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, ...@@ -402,7 +402,7 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev,
/* Check on error of previous branch */ /* Check on error of previous branch */
if (err) if (err)
goto drop; return -EINVAL;
/* Extract DAM to the tmp variable */ /* Extract DAM to the tmp variable */
tmp = ((iphc1 & LOWPAN_IPHC_DAM_11) >> LOWPAN_IPHC_DAM_BIT) & 0x03; tmp = ((iphc1 & LOWPAN_IPHC_DAM_11) >> LOWPAN_IPHC_DAM_BIT) & 0x03;
...@@ -417,7 +417,7 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, ...@@ -417,7 +417,7 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev,
tmp); tmp);
if (err) if (err)
goto drop; return -EINVAL;
} }
} else { } else {
err = uncompress_addr(skb, &hdr.daddr, tmp, daddr, err = uncompress_addr(skb, &hdr.daddr, tmp, daddr,
...@@ -425,7 +425,7 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, ...@@ -425,7 +425,7 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev,
pr_debug("dest: stateless compression mode %d dest %pI6c\n", pr_debug("dest: stateless compression mode %d dest %pI6c\n",
tmp, &hdr.daddr); tmp, &hdr.daddr);
if (err) if (err)
goto drop; return -EINVAL;
} }
/* UDP data uncompression */ /* UDP data uncompression */
...@@ -434,16 +434,14 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, ...@@ -434,16 +434,14 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev,
const int needed = sizeof(struct udphdr) + sizeof(hdr); const int needed = sizeof(struct udphdr) + sizeof(hdr);
if (uncompress_udp_header(skb, &uh)) if (uncompress_udp_header(skb, &uh))
goto drop; return -EINVAL;
/* replace the compressed UDP head by the uncompressed UDP /* replace the compressed UDP head by the uncompressed UDP
* header * header
*/ */
err = skb_cow(skb, needed); err = skb_cow(skb, needed);
if (unlikely(err)) { if (unlikely(err))
kfree_skb(skb);
return err; return err;
}
skb_push(skb, sizeof(struct udphdr)); skb_push(skb, sizeof(struct udphdr));
skb_reset_transport_header(skb); skb_reset_transport_header(skb);
...@@ -455,10 +453,8 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, ...@@ -455,10 +453,8 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev,
hdr.nexthdr = UIP_PROTO_UDP; hdr.nexthdr = UIP_PROTO_UDP;
} else { } else {
err = skb_cow(skb, sizeof(hdr)); err = skb_cow(skb, sizeof(hdr));
if (unlikely(err)) { if (unlikely(err))
kfree_skb(skb);
return err; return err;
}
} }
hdr.payload_len = htons(skb->len); hdr.payload_len = htons(skb->len);
...@@ -478,9 +474,6 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, ...@@ -478,9 +474,6 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev,
raw_dump_table(__func__, "raw header dump", (u8 *)&hdr, sizeof(hdr)); raw_dump_table(__func__, "raw header dump", (u8 *)&hdr, sizeof(hdr));
return 0; return 0;
drop:
kfree_skb(skb);
return -EINVAL;
} }
EXPORT_SYMBOL_GPL(lowpan_header_decompress); EXPORT_SYMBOL_GPL(lowpan_header_decompress);
...@@ -512,9 +505,17 @@ static u8 lowpan_compress_addr_64(u8 **hc_ptr, u8 shift, ...@@ -512,9 +505,17 @@ static u8 lowpan_compress_addr_64(u8 **hc_ptr, u8 shift,
static void compress_udp_header(u8 **hc_ptr, struct sk_buff *skb) static void compress_udp_header(u8 **hc_ptr, struct sk_buff *skb)
{ {
struct udphdr *uh = udp_hdr(skb); struct udphdr *uh;
u8 tmp; u8 tmp;
/* In the case of RAW sockets the transport header is not set by
* the ip6 stack so we must set it ourselves
*/
if (skb->transport_header == skb->network_header)
skb_set_transport_header(skb, sizeof(struct ipv6hdr));
uh = udp_hdr(skb);
if (((ntohs(uh->source) & LOWPAN_NHC_UDP_4BIT_MASK) == if (((ntohs(uh->source) & LOWPAN_NHC_UDP_4BIT_MASK) ==
LOWPAN_NHC_UDP_4BIT_PORT) && LOWPAN_NHC_UDP_4BIT_PORT) &&
((ntohs(uh->dest) & LOWPAN_NHC_UDP_4BIT_MASK) == ((ntohs(uh->dest) & LOWPAN_NHC_UDP_4BIT_MASK) ==
......
...@@ -294,20 +294,20 @@ static int iphc_decompress(struct sk_buff *skb, struct net_device *netdev, ...@@ -294,20 +294,20 @@ static int iphc_decompress(struct sk_buff *skb, struct net_device *netdev,
peer = __peer_lookup_chan(dev, chan); peer = __peer_lookup_chan(dev, chan);
rcu_read_unlock(); rcu_read_unlock();
if (!peer) if (!peer)
goto drop; return -EINVAL;
saddr = peer->eui64_addr; saddr = peer->eui64_addr;
daddr = dev->netdev->dev_addr; daddr = dev->netdev->dev_addr;
/* at least two bytes will be used for the encoding */ /* at least two bytes will be used for the encoding */
if (skb->len < 2) if (skb->len < 2)
goto drop; return -EINVAL;
if (lowpan_fetch_skb_u8(skb, &iphc0)) if (lowpan_fetch_skb_u8(skb, &iphc0))
goto drop; return -EINVAL;
if (lowpan_fetch_skb_u8(skb, &iphc1)) if (lowpan_fetch_skb_u8(skb, &iphc1))
goto drop; return -EINVAL;
return lowpan_header_decompress(skb, netdev, return lowpan_header_decompress(skb, netdev,
saddr, IEEE802154_ADDR_LONG, saddr, IEEE802154_ADDR_LONG,
...@@ -315,9 +315,6 @@ static int iphc_decompress(struct sk_buff *skb, struct net_device *netdev, ...@@ -315,9 +315,6 @@ static int iphc_decompress(struct sk_buff *skb, struct net_device *netdev,
IEEE802154_ADDR_LONG, EUI64_ADDR_LEN, IEEE802154_ADDR_LONG, EUI64_ADDR_LEN,
iphc0, iphc1); iphc0, iphc1);
drop:
kfree_skb(skb);
return -EINVAL;
} }
static int recv_pkt(struct sk_buff *skb, struct net_device *dev, static int recv_pkt(struct sk_buff *skb, struct net_device *dev,
...@@ -370,8 +367,10 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev, ...@@ -370,8 +367,10 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev,
goto drop; goto drop;
ret = iphc_decompress(local_skb, dev, chan); ret = iphc_decompress(local_skb, dev, chan);
if (ret < 0) if (ret < 0) {
kfree_skb(local_skb);
goto drop; goto drop;
}
local_skb->protocol = htons(ETH_P_IPV6); local_skb->protocol = htons(ETH_P_IPV6);
local_skb->pkt_type = PACKET_HOST; local_skb->pkt_type = PACKET_HOST;
......
...@@ -39,11 +39,10 @@ menuconfig BT ...@@ -39,11 +39,10 @@ menuconfig BT
to Bluetooth kernel modules are provided in the BlueZ packages. For to Bluetooth kernel modules are provided in the BlueZ packages. For
more information, see <http://www.bluez.org/>. more information, see <http://www.bluez.org/>.
config BT_6LOWPAN config BT_BREDR
tristate "Bluetooth 6LoWPAN support" bool "Bluetooth Classic (BR/EDR) features"
depends on BT && 6LOWPAN depends on BT
help default y
IPv6 compression over Bluetooth Low Energy.
source "net/bluetooth/rfcomm/Kconfig" source "net/bluetooth/rfcomm/Kconfig"
...@@ -53,4 +52,15 @@ source "net/bluetooth/cmtp/Kconfig" ...@@ -53,4 +52,15 @@ source "net/bluetooth/cmtp/Kconfig"
source "net/bluetooth/hidp/Kconfig" source "net/bluetooth/hidp/Kconfig"
config BT_LE
bool "Bluetooth Low Energy (LE) features"
depends on BT
default y
config BT_6LOWPAN
tristate "Bluetooth 6LoWPAN support"
depends on BT_LE && 6LOWPAN
help
IPv6 compression over Bluetooth Low Energy.
source "drivers/bluetooth/Kconfig" source "drivers/bluetooth/Kconfig"
config BT_BNEP config BT_BNEP
tristate "BNEP protocol support" tristate "BNEP protocol support"
depends on BT depends on BT_BREDR
select CRC32 select CRC32
help help
BNEP (Bluetooth Network Encapsulation Protocol) is Ethernet BNEP (Bluetooth Network Encapsulation Protocol) is Ethernet
......
config BT_CMTP config BT_CMTP
tristate "CMTP protocol support" tristate "CMTP protocol support"
depends on BT && ISDN_CAPI depends on BT_BREDR && ISDN_CAPI
help help
CMTP (CAPI Message Transport Protocol) is a transport layer CMTP (CAPI Message Transport Protocol) is a transport layer
for CAPI messages. CMTP is required for the Bluetooth Common for CAPI messages. CMTP is required for the Bluetooth Common
......
...@@ -200,31 +200,6 @@ static const struct file_operations blacklist_fops = { ...@@ -200,31 +200,6 @@ static const struct file_operations blacklist_fops = {
.release = single_release, .release = single_release,
}; };
static int whitelist_show(struct seq_file *f, void *p)
{
struct hci_dev *hdev = f->private;
struct bdaddr_list *b;
hci_dev_lock(hdev);
list_for_each_entry(b, &hdev->whitelist, list)
seq_printf(f, "%pMR (type %u)\n", &b->bdaddr, b->bdaddr_type);
hci_dev_unlock(hdev);
return 0;
}
static int whitelist_open(struct inode *inode, struct file *file)
{
return single_open(file, whitelist_show, inode->i_private);
}
static const struct file_operations whitelist_fops = {
.open = whitelist_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int uuids_show(struct seq_file *f, void *p) static int uuids_show(struct seq_file *f, void *p)
{ {
struct hci_dev *hdev = f->private; struct hci_dev *hdev = f->private;
...@@ -1030,10 +1005,13 @@ static int device_list_show(struct seq_file *f, void *ptr) ...@@ -1030,10 +1005,13 @@ static int device_list_show(struct seq_file *f, void *ptr)
{ {
struct hci_dev *hdev = f->private; struct hci_dev *hdev = f->private;
struct hci_conn_params *p; struct hci_conn_params *p;
struct bdaddr_list *b;
hci_dev_lock(hdev); hci_dev_lock(hdev);
list_for_each_entry(b, &hdev->whitelist, list)
seq_printf(f, "%pMR (type %u)\n", &b->bdaddr, b->bdaddr_type);
list_for_each_entry(p, &hdev->le_conn_params, list) { list_for_each_entry(p, &hdev->le_conn_params, list) {
seq_printf(f, "%pMR %u %u\n", &p->addr, p->addr_type, seq_printf(f, "%pMR (type %u) %u\n", &p->addr, p->addr_type,
p->auto_connect); p->auto_connect);
} }
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
...@@ -1147,13 +1125,15 @@ struct sk_buff *__hci_cmd_sync_ev(struct hci_dev *hdev, u16 opcode, u32 plen, ...@@ -1147,13 +1125,15 @@ struct sk_buff *__hci_cmd_sync_ev(struct hci_dev *hdev, u16 opcode, u32 plen,
hdev->req_status = HCI_REQ_PEND; hdev->req_status = HCI_REQ_PEND;
err = hci_req_run(&req, hci_req_sync_complete);
if (err < 0)
return ERR_PTR(err);
add_wait_queue(&hdev->req_wait_q, &wait); add_wait_queue(&hdev->req_wait_q, &wait);
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
err = hci_req_run(&req, hci_req_sync_complete);
if (err < 0) {
remove_wait_queue(&hdev->req_wait_q, &wait);
return ERR_PTR(err);
}
schedule_timeout(timeout); schedule_timeout(timeout);
remove_wait_queue(&hdev->req_wait_q, &wait); remove_wait_queue(&hdev->req_wait_q, &wait);
...@@ -1211,10 +1191,15 @@ static int __hci_req_sync(struct hci_dev *hdev, ...@@ -1211,10 +1191,15 @@ static int __hci_req_sync(struct hci_dev *hdev,
func(&req, opt); func(&req, opt);
add_wait_queue(&hdev->req_wait_q, &wait);
set_current_state(TASK_INTERRUPTIBLE);
err = hci_req_run(&req, hci_req_sync_complete); err = hci_req_run(&req, hci_req_sync_complete);
if (err < 0) { if (err < 0) {
hdev->req_status = 0; hdev->req_status = 0;
remove_wait_queue(&hdev->req_wait_q, &wait);
/* ENODATA means the HCI request command queue is empty. /* ENODATA means the HCI request command queue is empty.
* This can happen when a request with conditionals doesn't * This can happen when a request with conditionals doesn't
* trigger any commands to be sent. This is normal behavior * trigger any commands to be sent. This is normal behavior
...@@ -1226,9 +1211,6 @@ static int __hci_req_sync(struct hci_dev *hdev, ...@@ -1226,9 +1211,6 @@ static int __hci_req_sync(struct hci_dev *hdev,
return err; return err;
} }
add_wait_queue(&hdev->req_wait_q, &wait);
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(timeout); schedule_timeout(timeout);
remove_wait_queue(&hdev->req_wait_q, &wait); remove_wait_queue(&hdev->req_wait_q, &wait);
...@@ -1811,10 +1793,10 @@ static int __hci_init(struct hci_dev *hdev) ...@@ -1811,10 +1793,10 @@ static int __hci_init(struct hci_dev *hdev)
&hdev->manufacturer); &hdev->manufacturer);
debugfs_create_u8("hci_version", 0444, hdev->debugfs, &hdev->hci_ver); debugfs_create_u8("hci_version", 0444, hdev->debugfs, &hdev->hci_ver);
debugfs_create_u16("hci_revision", 0444, hdev->debugfs, &hdev->hci_rev); debugfs_create_u16("hci_revision", 0444, hdev->debugfs, &hdev->hci_rev);
debugfs_create_file("device_list", 0444, hdev->debugfs, hdev,
&device_list_fops);
debugfs_create_file("blacklist", 0444, hdev->debugfs, hdev, debugfs_create_file("blacklist", 0444, hdev->debugfs, hdev,
&blacklist_fops); &blacklist_fops);
debugfs_create_file("whitelist", 0444, hdev->debugfs, hdev,
&whitelist_fops);
debugfs_create_file("uuids", 0444, hdev->debugfs, hdev, &uuids_fops); debugfs_create_file("uuids", 0444, hdev->debugfs, hdev, &uuids_fops);
debugfs_create_file("conn_info_min_age", 0644, hdev->debugfs, hdev, debugfs_create_file("conn_info_min_age", 0644, hdev->debugfs, hdev,
...@@ -1893,8 +1875,6 @@ static int __hci_init(struct hci_dev *hdev) ...@@ -1893,8 +1875,6 @@ static int __hci_init(struct hci_dev *hdev)
hdev, &adv_min_interval_fops); hdev, &adv_min_interval_fops);
debugfs_create_file("adv_max_interval", 0644, hdev->debugfs, debugfs_create_file("adv_max_interval", 0644, hdev->debugfs,
hdev, &adv_max_interval_fops); hdev, &adv_max_interval_fops);
debugfs_create_file("device_list", 0444, hdev->debugfs, hdev,
&device_list_fops);
debugfs_create_u16("discov_interleaved_timeout", 0644, debugfs_create_u16("discov_interleaved_timeout", 0644,
hdev->debugfs, hdev->debugfs,
&hdev->discov_interleaved_timeout); &hdev->discov_interleaved_timeout);
...@@ -4244,6 +4224,24 @@ int hci_resume_dev(struct hci_dev *hdev) ...@@ -4244,6 +4224,24 @@ int hci_resume_dev(struct hci_dev *hdev)
} }
EXPORT_SYMBOL(hci_resume_dev); EXPORT_SYMBOL(hci_resume_dev);
/* Reset HCI device */
int hci_reset_dev(struct hci_dev *hdev)
{
const u8 hw_err[] = { HCI_EV_HARDWARE_ERROR, 0x01, 0x00 };
struct sk_buff *skb;
skb = bt_skb_alloc(3, GFP_ATOMIC);
if (!skb)
return -ENOMEM;
bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
memcpy(skb_put(skb, 3), hw_err, 3);
/* Send Hardware Error to upper stack */
return hci_recv_frame(hdev, skb);
}
EXPORT_SYMBOL(hci_reset_dev);
/* Receive frame from HCI drivers */ /* Receive frame from HCI drivers */
int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb) int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb)
{ {
......
...@@ -189,6 +189,9 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -189,6 +189,9 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
clear_bit(HCI_RESET, &hdev->flags); clear_bit(HCI_RESET, &hdev->flags);
if (status)
return;
/* Reset all non-persistent flags */ /* Reset all non-persistent flags */
hdev->dev_flags &= ~HCI_PERSISTENT_MASK; hdev->dev_flags &= ~HCI_PERSISTENT_MASK;
...@@ -1944,6 +1947,29 @@ static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) ...@@ -1944,6 +1947,29 @@ static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
} }
static void hci_cs_switch_role(struct hci_dev *hdev, u8 status)
{
struct hci_cp_switch_role *cp;
struct hci_conn *conn;
BT_DBG("%s status 0x%2.2x", hdev->name, status);
if (!status)
return;
cp = hci_sent_cmd_data(hdev, HCI_OP_SWITCH_ROLE);
if (!cp)
return;
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
if (conn)
clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
hci_dev_unlock(hdev);
}
static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{ {
__u8 status = *((__u8 *) skb->data); __u8 status = *((__u8 *) skb->data);
...@@ -2847,6 +2873,10 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -2847,6 +2873,10 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_cs_create_conn(hdev, ev->status); hci_cs_create_conn(hdev, ev->status);
break; break;
case HCI_OP_DISCONNECT:
hci_cs_disconnect(hdev, ev->status);
break;
case HCI_OP_ADD_SCO: case HCI_OP_ADD_SCO:
hci_cs_add_sco(hdev, ev->status); hci_cs_add_sco(hdev, ev->status);
break; break;
...@@ -2875,24 +2905,24 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -2875,24 +2905,24 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_cs_setup_sync_conn(hdev, ev->status); hci_cs_setup_sync_conn(hdev, ev->status);
break; break;
case HCI_OP_SNIFF_MODE: case HCI_OP_CREATE_PHY_LINK:
hci_cs_sniff_mode(hdev, ev->status); hci_cs_create_phylink(hdev, ev->status);
break; break;
case HCI_OP_EXIT_SNIFF_MODE: case HCI_OP_ACCEPT_PHY_LINK:
hci_cs_exit_sniff_mode(hdev, ev->status); hci_cs_accept_phylink(hdev, ev->status);
break; break;
case HCI_OP_DISCONNECT: case HCI_OP_SNIFF_MODE:
hci_cs_disconnect(hdev, ev->status); hci_cs_sniff_mode(hdev, ev->status);
break; break;
case HCI_OP_CREATE_PHY_LINK: case HCI_OP_EXIT_SNIFF_MODE:
hci_cs_create_phylink(hdev, ev->status); hci_cs_exit_sniff_mode(hdev, ev->status);
break; break;
case HCI_OP_ACCEPT_PHY_LINK: case HCI_OP_SWITCH_ROLE:
hci_cs_accept_phylink(hdev, ev->status); hci_cs_switch_role(hdev, ev->status);
break; break;
case HCI_OP_LE_CREATE_CONN: case HCI_OP_LE_CREATE_CONN:
...@@ -2922,6 +2952,13 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -2922,6 +2952,13 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
} }
} }
static void hci_hardware_error_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_hardware_error *ev = (void *) skb->data;
BT_ERR("%s hardware error 0x%2.2x", hdev->name, ev->code);
}
static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
{ {
struct hci_ev_role_change *ev = (void *) skb->data; struct hci_ev_role_change *ev = (void *) skb->data;
...@@ -4743,6 +4780,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -4743,6 +4780,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
hci_cmd_status_evt(hdev, skb); hci_cmd_status_evt(hdev, skb);
break; break;
case HCI_EV_HARDWARE_ERROR:
hci_hardware_error_evt(hdev, skb);
break;
case HCI_EV_ROLE_CHANGE: case HCI_EV_ROLE_CHANGE:
hci_role_change_evt(hdev, skb); hci_role_change_evt(hdev, skb);
break; break;
......
config BT_HIDP config BT_HIDP
tristate "HIDP protocol support" tristate "HIDP protocol support"
depends on BT && INPUT depends on BT_BREDR && INPUT
select HID select HID
help help
HIDP (Human Interface Device Protocol) is a transport layer HIDP (Human Interface Device Protocol) is a transport layer
......
...@@ -3727,20 +3727,23 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, ...@@ -3727,20 +3727,23 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (!hdev_is_powered(hdev)) { if (!hdev_is_powered(hdev)) {
err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
MGMT_STATUS_NOT_POWERED); MGMT_STATUS_NOT_POWERED,
&cp->type, sizeof(cp->type));
goto failed; goto failed;
} }
if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) { if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
MGMT_STATUS_BUSY); MGMT_STATUS_BUSY, &cp->type,
sizeof(cp->type));
goto failed; goto failed;
} }
if (hdev->discovery.state != DISCOVERY_STOPPED) { if (hdev->discovery.state != DISCOVERY_STOPPED) {
err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
MGMT_STATUS_BUSY); MGMT_STATUS_BUSY, &cp->type,
sizeof(cp->type));
goto failed; goto failed;
} }
...@@ -3758,15 +3761,18 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, ...@@ -3758,15 +3761,18 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
case DISCOV_TYPE_BREDR: case DISCOV_TYPE_BREDR:
status = mgmt_bredr_support(hdev); status = mgmt_bredr_support(hdev);
if (status) { if (status) {
err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, err = cmd_complete(sk, hdev->id,
status); MGMT_OP_START_DISCOVERY, status,
&cp->type, sizeof(cp->type));
mgmt_pending_remove(cmd); mgmt_pending_remove(cmd);
goto failed; goto failed;
} }
if (test_bit(HCI_INQUIRY, &hdev->flags)) { if (test_bit(HCI_INQUIRY, &hdev->flags)) {
err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, err = cmd_complete(sk, hdev->id,
MGMT_STATUS_BUSY); MGMT_OP_START_DISCOVERY,
MGMT_STATUS_BUSY, &cp->type,
sizeof(cp->type));
mgmt_pending_remove(cmd); mgmt_pending_remove(cmd);
goto failed; goto failed;
} }
...@@ -3783,16 +3789,19 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, ...@@ -3783,16 +3789,19 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
case DISCOV_TYPE_INTERLEAVED: case DISCOV_TYPE_INTERLEAVED:
status = mgmt_le_support(hdev); status = mgmt_le_support(hdev);
if (status) { if (status) {
err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, err = cmd_complete(sk, hdev->id,
status); MGMT_OP_START_DISCOVERY, status,
&cp->type, sizeof(cp->type));
mgmt_pending_remove(cmd); mgmt_pending_remove(cmd);
goto failed; goto failed;
} }
if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED && if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) { !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, err = cmd_complete(sk, hdev->id,
MGMT_STATUS_NOT_SUPPORTED); MGMT_OP_START_DISCOVERY,
MGMT_STATUS_NOT_SUPPORTED,
&cp->type, sizeof(cp->type));
mgmt_pending_remove(cmd); mgmt_pending_remove(cmd);
goto failed; goto failed;
} }
...@@ -3804,9 +3813,11 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, ...@@ -3804,9 +3813,11 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
*/ */
if (hci_conn_hash_lookup_state(hdev, LE_LINK, if (hci_conn_hash_lookup_state(hdev, LE_LINK,
BT_CONNECT)) { BT_CONNECT)) {
err = cmd_status(sk, hdev->id, err = cmd_complete(sk, hdev->id,
MGMT_OP_START_DISCOVERY, MGMT_OP_START_DISCOVERY,
MGMT_STATUS_REJECTED); MGMT_STATUS_REJECTED,
&cp->type,
sizeof(cp->type));
mgmt_pending_remove(cmd); mgmt_pending_remove(cmd);
goto failed; goto failed;
} }
...@@ -3829,8 +3840,10 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, ...@@ -3829,8 +3840,10 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
*/ */
err = hci_update_random_address(&req, true, &own_addr_type); err = hci_update_random_address(&req, true, &own_addr_type);
if (err < 0) { if (err < 0) {
err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, err = cmd_complete(sk, hdev->id,
MGMT_STATUS_FAILED); MGMT_OP_START_DISCOVERY,
MGMT_STATUS_FAILED,
&cp->type, sizeof(cp->type));
mgmt_pending_remove(cmd); mgmt_pending_remove(cmd);
goto failed; goto failed;
} }
...@@ -3850,8 +3863,9 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, ...@@ -3850,8 +3863,9 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
break; break;
default: default:
err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS,
&cp->type, sizeof(cp->type));
mgmt_pending_remove(cmd); mgmt_pending_remove(cmd);
goto failed; goto failed;
} }
......
config BT_RFCOMM config BT_RFCOMM
tristate "RFCOMM protocol support" tristate "RFCOMM protocol support"
depends on BT depends on BT_BREDR
help help
RFCOMM provides connection oriented stream transport. RFCOMM RFCOMM provides connection oriented stream transport. RFCOMM
support is required for Dialup Networking, OBEX and other Bluetooth support is required for Dialup Networking, OBEX and other Bluetooth
......
...@@ -81,6 +81,8 @@ static struct rfcomm_session *rfcomm_session_del(struct rfcomm_session *s); ...@@ -81,6 +81,8 @@ static struct rfcomm_session *rfcomm_session_del(struct rfcomm_session *s);
#define __test_cr(b) (!!(b & 0x02)) #define __test_cr(b) (!!(b & 0x02))
#define __test_pf(b) (!!(b & 0x10)) #define __test_pf(b) (!!(b & 0x10))
#define __session_dir(s) ((s)->initiator ? 0x00 : 0x01)
#define __addr(cr, dlci) (((dlci & 0x3f) << 2) | (cr << 1) | 0x01) #define __addr(cr, dlci) (((dlci & 0x3f) << 2) | (cr << 1) | 0x01)
#define __ctrl(type, pf) (((type & 0xef) | (pf << 4))) #define __ctrl(type, pf) (((type & 0xef) | (pf << 4)))
#define __dlci(dir, chn) (((chn & 0x1f) << 1) | dir) #define __dlci(dir, chn) (((chn & 0x1f) << 1) | dir)
...@@ -388,7 +390,7 @@ static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, ...@@ -388,7 +390,7 @@ static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst,
return err; return err;
} }
dlci = __dlci(!s->initiator, channel); dlci = __dlci(__session_dir(s), channel);
/* Check if DLCI already exists */ /* Check if DLCI already exists */
if (rfcomm_dlc_get(s, dlci)) if (rfcomm_dlc_get(s, dlci))
...@@ -543,7 +545,7 @@ struct rfcomm_dlc *rfcomm_dlc_exists(bdaddr_t *src, bdaddr_t *dst, u8 channel) ...@@ -543,7 +545,7 @@ struct rfcomm_dlc *rfcomm_dlc_exists(bdaddr_t *src, bdaddr_t *dst, u8 channel)
rfcomm_lock(); rfcomm_lock();
s = rfcomm_session_get(src, dst); s = rfcomm_session_get(src, dst);
if (s) { if (s) {
dlci = __dlci(!s->initiator, channel); dlci = __dlci(__session_dir(s), channel);
dlc = rfcomm_dlc_get(s, dlci); dlc = rfcomm_dlc_get(s, dlci);
} }
rfcomm_unlock(); rfcomm_unlock();
......
...@@ -176,13 +176,13 @@ iphc_decompress(struct sk_buff *skb, const struct ieee802154_hdr *hdr) ...@@ -176,13 +176,13 @@ iphc_decompress(struct sk_buff *skb, const struct ieee802154_hdr *hdr)
raw_dump_table(__func__, "raw skb data dump", skb->data, skb->len); raw_dump_table(__func__, "raw skb data dump", skb->data, skb->len);
/* at least two bytes will be used for the encoding */ /* at least two bytes will be used for the encoding */
if (skb->len < 2) if (skb->len < 2)
goto drop; return -EINVAL;
if (lowpan_fetch_skb_u8(skb, &iphc0)) if (lowpan_fetch_skb_u8(skb, &iphc0))
goto drop; return -EINVAL;
if (lowpan_fetch_skb_u8(skb, &iphc1)) if (lowpan_fetch_skb_u8(skb, &iphc1))
goto drop; return -EINVAL;
ieee802154_addr_to_sa(&sa, &hdr->source); ieee802154_addr_to_sa(&sa, &hdr->source);
ieee802154_addr_to_sa(&da, &hdr->dest); ieee802154_addr_to_sa(&da, &hdr->dest);
...@@ -200,23 +200,6 @@ iphc_decompress(struct sk_buff *skb, const struct ieee802154_hdr *hdr) ...@@ -200,23 +200,6 @@ iphc_decompress(struct sk_buff *skb, const struct ieee802154_hdr *hdr)
return lowpan_header_decompress(skb, skb->dev, sap, sa.addr_type, return lowpan_header_decompress(skb, skb->dev, sap, sa.addr_type,
IEEE802154_ADDR_LEN, dap, da.addr_type, IEEE802154_ADDR_LEN, dap, da.addr_type,
IEEE802154_ADDR_LEN, iphc0, iphc1); IEEE802154_ADDR_LEN, iphc0, iphc1);
drop:
kfree_skb(skb);
return -EINVAL;
}
static int lowpan_set_address(struct net_device *dev, void *p)
{
struct sockaddr *sa = p;
if (netif_running(dev))
return -EBUSY;
/* TODO: validate addr */
memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
return 0;
} }
static struct sk_buff* static struct sk_buff*
...@@ -420,13 +403,6 @@ static netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -420,13 +403,6 @@ static netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *dev)
} }
} }
static struct wpan_phy *lowpan_get_phy(const struct net_device *dev)
{
struct net_device *real_dev = lowpan_dev_info(dev)->real_dev;
return ieee802154_mlme_ops(real_dev)->get_phy(real_dev);
}
static __le16 lowpan_get_pan_id(const struct net_device *dev) static __le16 lowpan_get_pan_id(const struct net_device *dev)
{ {
struct net_device *real_dev = lowpan_dev_info(dev)->real_dev; struct net_device *real_dev = lowpan_dev_info(dev)->real_dev;
...@@ -474,12 +450,10 @@ static int lowpan_dev_init(struct net_device *dev) ...@@ -474,12 +450,10 @@ static int lowpan_dev_init(struct net_device *dev)
static const struct net_device_ops lowpan_netdev_ops = { static const struct net_device_ops lowpan_netdev_ops = {
.ndo_init = lowpan_dev_init, .ndo_init = lowpan_dev_init,
.ndo_start_xmit = lowpan_xmit, .ndo_start_xmit = lowpan_xmit,
.ndo_set_mac_address = lowpan_set_address,
}; };
static struct ieee802154_mlme_ops lowpan_mlme = { static struct ieee802154_mlme_ops lowpan_mlme = {
.get_pan_id = lowpan_get_pan_id, .get_pan_id = lowpan_get_pan_id,
.get_phy = lowpan_get_phy,
.get_short_addr = lowpan_get_short_addr, .get_short_addr = lowpan_get_short_addr,
.get_dsn = lowpan_get_dsn, .get_dsn = lowpan_get_dsn,
}; };
...@@ -544,7 +518,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev, ...@@ -544,7 +518,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
case LOWPAN_DISPATCH_IPHC: /* ipv6 datagram */ case LOWPAN_DISPATCH_IPHC: /* ipv6 datagram */
ret = iphc_decompress(skb, &hdr); ret = iphc_decompress(skb, &hdr);
if (ret < 0) if (ret < 0)
goto drop; goto drop_skb;
return lowpan_give_skb_to_devices(skb, NULL); return lowpan_give_skb_to_devices(skb, NULL);
case LOWPAN_DISPATCH_FRAG1: /* first fragment header */ case LOWPAN_DISPATCH_FRAG1: /* first fragment header */
...@@ -552,7 +526,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev, ...@@ -552,7 +526,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
if (ret == 1) { if (ret == 1) {
ret = iphc_decompress(skb, &hdr); ret = iphc_decompress(skb, &hdr);
if (ret < 0) if (ret < 0)
goto drop; goto drop_skb;
return lowpan_give_skb_to_devices(skb, NULL); return lowpan_give_skb_to_devices(skb, NULL);
} else if (ret == -1) { } else if (ret == -1) {
...@@ -565,7 +539,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev, ...@@ -565,7 +539,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
if (ret == 1) { if (ret == 1) {
ret = iphc_decompress(skb, &hdr); ret = iphc_decompress(skb, &hdr);
if (ret < 0) if (ret < 0)
goto drop; goto drop_skb;
return lowpan_give_skb_to_devices(skb, NULL); return lowpan_give_skb_to_devices(skb, NULL);
} else if (ret == -1) { } else if (ret == -1) {
......
...@@ -21,9 +21,7 @@ ...@@ -21,9 +21,7 @@
#include "ieee802154.h" #include "ieee802154.h"
#include "sysfs.h" #include "sysfs.h"
#include "core.h"
static DEFINE_MUTEX(wpan_phy_mutex);
static int wpan_phy_idx;
static int wpan_phy_match(struct device *dev, const void *data) static int wpan_phy_match(struct device *dev, const void *data)
{ {
...@@ -71,42 +69,41 @@ int wpan_phy_for_each(int (*fn)(struct wpan_phy *phy, void *data), ...@@ -71,42 +69,41 @@ int wpan_phy_for_each(int (*fn)(struct wpan_phy *phy, void *data),
} }
EXPORT_SYMBOL(wpan_phy_for_each); EXPORT_SYMBOL(wpan_phy_for_each);
static int wpan_phy_idx_valid(int idx) struct wpan_phy *
wpan_phy_alloc(const struct cfg802154_ops *ops, size_t priv_size)
{ {
return idx >= 0; static atomic_t wpan_phy_counter = ATOMIC_INIT(0);
} struct cfg802154_registered_device *rdev;
size_t alloc_size;
struct wpan_phy *wpan_phy_alloc(size_t priv_size) alloc_size = sizeof(*rdev) + priv_size;
{ rdev = kzalloc(alloc_size, GFP_KERNEL);
struct wpan_phy *phy = kzalloc(sizeof(*phy) + priv_size, if (!rdev)
GFP_KERNEL); return NULL;
if (!phy) rdev->ops = ops;
goto out;
mutex_lock(&wpan_phy_mutex);
phy->idx = wpan_phy_idx++;
if (unlikely(!wpan_phy_idx_valid(phy->idx))) {
wpan_phy_idx--;
mutex_unlock(&wpan_phy_mutex);
kfree(phy);
goto out;
}
mutex_unlock(&wpan_phy_mutex);
mutex_init(&phy->pib_lock); rdev->wpan_phy_idx = atomic_inc_return(&wpan_phy_counter);
device_initialize(&phy->dev); if (unlikely(rdev->wpan_phy_idx < 0)) {
dev_set_name(&phy->dev, "wpan-phy%d", phy->idx); /* ugh, wrapped! */
atomic_dec(&wpan_phy_counter);
kfree(rdev);
return NULL;
}
/* atomic_inc_return makes it start at 1, make it start at 0 */
rdev->wpan_phy_idx--;
phy->dev.class = &wpan_phy_class; mutex_init(&rdev->wpan_phy.pib_lock);
phy->current_channel = -1; /* not initialised */ device_initialize(&rdev->wpan_phy.dev);
phy->current_page = 0; /* for compatibility */ dev_set_name(&rdev->wpan_phy.dev, "wpan-phy%d", rdev->wpan_phy_idx);
return phy; rdev->wpan_phy.dev.class = &wpan_phy_class;
rdev->wpan_phy.dev.platform_data = rdev;
out: return &rdev->wpan_phy;
return NULL;
} }
EXPORT_SYMBOL(wpan_phy_alloc); EXPORT_SYMBOL(wpan_phy_alloc);
...@@ -128,6 +125,11 @@ void wpan_phy_free(struct wpan_phy *phy) ...@@ -128,6 +125,11 @@ void wpan_phy_free(struct wpan_phy *phy)
} }
EXPORT_SYMBOL(wpan_phy_free); EXPORT_SYMBOL(wpan_phy_free);
void cfg802154_dev_free(struct cfg802154_registered_device *rdev)
{
kfree(rdev);
}
static int __init wpan_phy_class_init(void) static int __init wpan_phy_class_init(void)
{ {
int rc; int rc;
......
#ifndef __IEEE802154_CORE_H
#define __IEEE802154_CORE_H
#include <net/cfg802154.h>
struct cfg802154_registered_device {
const struct cfg802154_ops *ops;
/* wpan_phy index, internal only */
int wpan_phy_idx;
/* must be last because of the way we do wpan_phy_priv(),
* and it should at least be aligned to NETDEV_ALIGN
*/
struct wpan_phy wpan_phy __aligned(NETDEV_ALIGN);
};
static inline struct cfg802154_registered_device *
wpan_phy_to_rdev(struct wpan_phy *wpan_phy)
{
BUG_ON(!wpan_phy);
return container_of(wpan_phy, struct cfg802154_registered_device,
wpan_phy);
}
/* free object */
void cfg802154_dev_free(struct cfg802154_registered_device *rdev);
#endif /* __IEEE802154_CORE_H */
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
#include <linux/nl802154.h> #include <linux/nl802154.h>
#include <linux/export.h> #include <linux/export.h>
#include <net/af_ieee802154.h> #include <net/af_ieee802154.h>
#include <net/nl802154.h>
#include <net/ieee802154_netdev.h> #include <net/ieee802154_netdev.h>
#include <net/cfg802154.h> #include <net/cfg802154.h>
...@@ -55,186 +54,7 @@ static __le16 nla_get_shortaddr(const struct nlattr *nla) ...@@ -55,186 +54,7 @@ static __le16 nla_get_shortaddr(const struct nlattr *nla)
return cpu_to_le16(nla_get_u16(nla)); return cpu_to_le16(nla_get_u16(nla));
} }
int ieee802154_nl_assoc_indic(struct net_device *dev, static int ieee802154_nl_start_confirm(struct net_device *dev, u8 status)
struct ieee802154_addr *addr,
u8 cap)
{
struct sk_buff *msg;
pr_debug("%s\n", __func__);
if (addr->mode != IEEE802154_ADDR_LONG) {
pr_err("%s: received non-long source address!\n", __func__);
return -EINVAL;
}
msg = ieee802154_nl_create(0, IEEE802154_ASSOCIATE_INDIC);
if (!msg)
return -ENOBUFS;
if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
dev->dev_addr) ||
nla_put_hwaddr(msg, IEEE802154_ATTR_SRC_HW_ADDR,
addr->extended_addr) ||
nla_put_u8(msg, IEEE802154_ATTR_CAPABILITY, cap))
goto nla_put_failure;
return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
nla_put_failure:
nlmsg_free(msg);
return -ENOBUFS;
}
EXPORT_SYMBOL(ieee802154_nl_assoc_indic);
int ieee802154_nl_assoc_confirm(struct net_device *dev, __le16 short_addr,
u8 status)
{
struct sk_buff *msg;
pr_debug("%s\n", __func__);
msg = ieee802154_nl_create(0, IEEE802154_ASSOCIATE_CONF);
if (!msg)
return -ENOBUFS;
if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
dev->dev_addr) ||
nla_put_shortaddr(msg, IEEE802154_ATTR_SHORT_ADDR, short_addr) ||
nla_put_u8(msg, IEEE802154_ATTR_STATUS, status))
goto nla_put_failure;
return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
nla_put_failure:
nlmsg_free(msg);
return -ENOBUFS;
}
EXPORT_SYMBOL(ieee802154_nl_assoc_confirm);
int ieee802154_nl_disassoc_indic(struct net_device *dev,
struct ieee802154_addr *addr,
u8 reason)
{
struct sk_buff *msg;
pr_debug("%s\n", __func__);
msg = ieee802154_nl_create(0, IEEE802154_DISASSOCIATE_INDIC);
if (!msg)
return -ENOBUFS;
if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
dev->dev_addr))
goto nla_put_failure;
if (addr->mode == IEEE802154_ADDR_LONG) {
if (nla_put_hwaddr(msg, IEEE802154_ATTR_SRC_HW_ADDR,
addr->extended_addr))
goto nla_put_failure;
} else {
if (nla_put_shortaddr(msg, IEEE802154_ATTR_SRC_SHORT_ADDR,
addr->short_addr))
goto nla_put_failure;
}
if (nla_put_u8(msg, IEEE802154_ATTR_REASON, reason))
goto nla_put_failure;
return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
nla_put_failure:
nlmsg_free(msg);
return -ENOBUFS;
}
EXPORT_SYMBOL(ieee802154_nl_disassoc_indic);
int ieee802154_nl_disassoc_confirm(struct net_device *dev, u8 status)
{
struct sk_buff *msg;
pr_debug("%s\n", __func__);
msg = ieee802154_nl_create(0, IEEE802154_DISASSOCIATE_CONF);
if (!msg)
return -ENOBUFS;
if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
dev->dev_addr) ||
nla_put_u8(msg, IEEE802154_ATTR_STATUS, status))
goto nla_put_failure;
return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
nla_put_failure:
nlmsg_free(msg);
return -ENOBUFS;
}
EXPORT_SYMBOL(ieee802154_nl_disassoc_confirm);
int ieee802154_nl_beacon_indic(struct net_device *dev, __le16 panid,
__le16 coord_addr)
{
struct sk_buff *msg;
pr_debug("%s\n", __func__);
msg = ieee802154_nl_create(0, IEEE802154_BEACON_NOTIFY_INDIC);
if (!msg)
return -ENOBUFS;
if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
dev->dev_addr) ||
nla_put_shortaddr(msg, IEEE802154_ATTR_COORD_SHORT_ADDR,
coord_addr) ||
nla_put_shortaddr(msg, IEEE802154_ATTR_COORD_PAN_ID, panid))
goto nla_put_failure;
return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
nla_put_failure:
nlmsg_free(msg);
return -ENOBUFS;
}
EXPORT_SYMBOL(ieee802154_nl_beacon_indic);
int ieee802154_nl_scan_confirm(struct net_device *dev,
u8 status, u8 scan_type,
u32 unscanned, u8 page,
u8 *edl/* , struct list_head *pan_desc_list */)
{
struct sk_buff *msg;
pr_debug("%s\n", __func__);
msg = ieee802154_nl_create(0, IEEE802154_SCAN_CONF);
if (!msg)
return -ENOBUFS;
if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
dev->dev_addr) ||
nla_put_u8(msg, IEEE802154_ATTR_STATUS, status) ||
nla_put_u8(msg, IEEE802154_ATTR_SCAN_TYPE, scan_type) ||
nla_put_u32(msg, IEEE802154_ATTR_CHANNELS, unscanned) ||
nla_put_u8(msg, IEEE802154_ATTR_PAGE, page) ||
(edl &&
nla_put(msg, IEEE802154_ATTR_ED_LIST, 27, edl)))
goto nla_put_failure;
return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
nla_put_failure:
nlmsg_free(msg);
return -ENOBUFS;
}
EXPORT_SYMBOL(ieee802154_nl_scan_confirm);
int ieee802154_nl_start_confirm(struct net_device *dev, u8 status)
{ {
struct sk_buff *msg; struct sk_buff *msg;
...@@ -274,8 +94,9 @@ static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 portid, ...@@ -274,8 +94,9 @@ static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 portid,
goto out; goto out;
ops = ieee802154_mlme_ops(dev); ops = ieee802154_mlme_ops(dev);
phy = ops->get_phy(dev); phy = dev->ieee802154_ptr->wpan_phy;
BUG_ON(!phy); BUG_ON(!phy);
get_device(&phy->dev);
short_addr = ops->get_short_addr(dev); short_addr = ops->get_short_addr(dev);
pan_id = ops->get_pan_id(dev); pan_id = ops->get_pan_id(dev);
...@@ -477,7 +298,7 @@ int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info) ...@@ -477,7 +298,7 @@ int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info)
u8 channel, bcn_ord, sf_ord; u8 channel, bcn_ord, sf_ord;
u8 page; u8 page;
int pan_coord, blx, coord_realign; int pan_coord, blx, coord_realign;
int ret = -EOPNOTSUPP; int ret = -EBUSY;
if (!info->attrs[IEEE802154_ATTR_COORD_PAN_ID] || if (!info->attrs[IEEE802154_ATTR_COORD_PAN_ID] ||
!info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR] || !info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR] ||
...@@ -493,8 +314,14 @@ int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info) ...@@ -493,8 +314,14 @@ int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info)
dev = ieee802154_nl_get_dev(info); dev = ieee802154_nl_get_dev(info);
if (!dev) if (!dev)
return -ENODEV; return -ENODEV;
if (!ieee802154_mlme_ops(dev)->start_req)
if (netif_running(dev))
goto out;
if (!ieee802154_mlme_ops(dev)->start_req) {
ret = -EOPNOTSUPP;
goto out; goto out;
}
addr.mode = IEEE802154_ADDR_SHORT; addr.mode = IEEE802154_ADDR_SHORT;
addr.short_addr = nla_get_shortaddr( addr.short_addr = nla_get_shortaddr(
...@@ -524,6 +351,11 @@ int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info) ...@@ -524,6 +351,11 @@ int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info)
ret = ieee802154_mlme_ops(dev)->start_req(dev, &addr, channel, page, ret = ieee802154_mlme_ops(dev)->start_req(dev, &addr, channel, page,
bcn_ord, sf_ord, pan_coord, blx, coord_realign); bcn_ord, sf_ord, pan_coord, blx, coord_realign);
/* FIXME: add validation for unused parameters to be sane
* for SoftMAC
*/
ieee802154_nl_start_confirm(dev, IEEE802154_SUCCESS);
out: out:
dev_put(dev); dev_put(dev);
return ret; return ret;
...@@ -662,7 +494,8 @@ int ieee802154_set_macparams(struct sk_buff *skb, struct genl_info *info) ...@@ -662,7 +494,8 @@ int ieee802154_set_macparams(struct sk_buff *skb, struct genl_info *info)
!info->attrs[IEEE802154_ATTR_FRAME_RETRIES]) !info->attrs[IEEE802154_ATTR_FRAME_RETRIES])
goto out; goto out;
phy = ops->get_phy(dev); phy = dev->ieee802154_ptr->wpan_phy;
get_device(&phy->dev);
ops->get_mac_params(dev, &params); ops->get_mac_params(dev, &params);
......
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
#include <linux/nl802154.h> #include <linux/nl802154.h>
#include "ieee802154.h" #include "ieee802154.h"
#include "rdev-ops.h"
#include "core.h"
static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 portid, static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 portid,
u32 seq, int flags, struct wpan_phy *phy) u32 seq, int flags, struct wpan_phy *phy)
...@@ -203,11 +205,6 @@ int ieee802154_add_iface(struct sk_buff *skb, struct genl_info *info) ...@@ -203,11 +205,6 @@ int ieee802154_add_iface(struct sk_buff *skb, struct genl_info *info)
if (!msg) if (!msg)
goto out_dev; goto out_dev;
if (!phy->add_iface) {
rc = -EINVAL;
goto nla_put_failure;
}
if (info->attrs[IEEE802154_ATTR_HW_ADDR] && if (info->attrs[IEEE802154_ATTR_HW_ADDR] &&
nla_len(info->attrs[IEEE802154_ATTR_HW_ADDR]) != nla_len(info->attrs[IEEE802154_ATTR_HW_ADDR]) !=
IEEE802154_ADDR_LEN) { IEEE802154_ADDR_LEN) {
...@@ -223,11 +220,13 @@ int ieee802154_add_iface(struct sk_buff *skb, struct genl_info *info) ...@@ -223,11 +220,13 @@ int ieee802154_add_iface(struct sk_buff *skb, struct genl_info *info)
} }
} }
dev = phy->add_iface(phy, devname, type); dev = rdev_add_virtual_intf_deprecated(wpan_phy_to_rdev(phy), devname,
type);
if (IS_ERR(dev)) { if (IS_ERR(dev)) {
rc = PTR_ERR(dev); rc = PTR_ERR(dev);
goto nla_put_failure; goto nla_put_failure;
} }
dev_hold(dev);
if (info->attrs[IEEE802154_ATTR_HW_ADDR]) { if (info->attrs[IEEE802154_ATTR_HW_ADDR]) {
struct sockaddr addr; struct sockaddr addr;
...@@ -257,7 +256,7 @@ int ieee802154_add_iface(struct sk_buff *skb, struct genl_info *info) ...@@ -257,7 +256,7 @@ int ieee802154_add_iface(struct sk_buff *skb, struct genl_info *info)
dev_unregister: dev_unregister:
rtnl_lock(); /* del_iface must be called with RTNL lock */ rtnl_lock(); /* del_iface must be called with RTNL lock */
phy->del_iface(phy, dev); rdev_del_virtual_intf_deprecated(wpan_phy_to_rdev(phy), dev);
dev_put(dev); dev_put(dev);
rtnl_unlock(); rtnl_unlock();
nla_put_failure: nla_put_failure:
...@@ -288,8 +287,9 @@ int ieee802154_del_iface(struct sk_buff *skb, struct genl_info *info) ...@@ -288,8 +287,9 @@ int ieee802154_del_iface(struct sk_buff *skb, struct genl_info *info)
if (!dev) if (!dev)
return -ENODEV; return -ENODEV;
phy = ieee802154_mlme_ops(dev)->get_phy(dev); phy = dev->ieee802154_ptr->wpan_phy;
BUG_ON(!phy); BUG_ON(!phy);
get_device(&phy->dev);
rc = -EINVAL; rc = -EINVAL;
/* phy name is optional, but should be checked if it's given */ /* phy name is optional, but should be checked if it's given */
...@@ -319,13 +319,8 @@ int ieee802154_del_iface(struct sk_buff *skb, struct genl_info *info) ...@@ -319,13 +319,8 @@ int ieee802154_del_iface(struct sk_buff *skb, struct genl_info *info)
if (!msg) if (!msg)
goto out_dev; goto out_dev;
if (!phy->del_iface) {
rc = -EINVAL;
goto nla_put_failure;
}
rtnl_lock(); rtnl_lock();
phy->del_iface(phy, dev); rdev_del_virtual_intf_deprecated(wpan_phy_to_rdev(phy), dev);
/* We don't have device anymore */ /* We don't have device anymore */
dev_put(dev); dev_put(dev);
......
#ifndef __CFG802154_RDEV_OPS
#define __CFG802154_RDEV_OPS
#include <net/cfg802154.h>
#include "core.h"
static inline struct net_device *
rdev_add_virtual_intf_deprecated(struct cfg802154_registered_device *rdev,
const char *name, int type)
{
return rdev->ops->add_virtual_intf_deprecated(&rdev->wpan_phy, name,
type);
}
static inline void
rdev_del_virtual_intf_deprecated(struct cfg802154_registered_device *rdev,
struct net_device *dev)
{
rdev->ops->del_virtual_intf_deprecated(&rdev->wpan_phy, dev);
}
#endif /* __CFG802154_RDEV_OPS */
...@@ -17,6 +17,16 @@ ...@@ -17,6 +17,16 @@
#include <net/cfg802154.h> #include <net/cfg802154.h>
#include "core.h"
#include "sysfs.h"
static inline struct cfg802154_registered_device *
dev_to_rdev(struct device *dev)
{
return container_of(dev, struct cfg802154_registered_device,
wpan_phy.dev);
}
#define MASTER_SHOW_COMPLEX(name, format_string, args...) \ #define MASTER_SHOW_COMPLEX(name, format_string, args...) \
static ssize_t name ## _show(struct device *dev, \ static ssize_t name ## _show(struct device *dev, \
struct device_attribute *attr, char *buf) \ struct device_attribute *attr, char *buf) \
...@@ -60,11 +70,11 @@ static ssize_t channels_supported_show(struct device *dev, ...@@ -60,11 +70,11 @@ static ssize_t channels_supported_show(struct device *dev,
} }
static DEVICE_ATTR_RO(channels_supported); static DEVICE_ATTR_RO(channels_supported);
static void wpan_phy_release(struct device *d) static void wpan_phy_release(struct device *dev)
{ {
struct wpan_phy *phy = container_of(d, struct wpan_phy, dev); struct cfg802154_registered_device *rdev = dev_to_rdev(dev);
kfree(phy); cfg802154_dev_free(rdev);
} }
static struct attribute *pmib_attrs[] = { static struct attribute *pmib_attrs[] = {
......
obj-$(CONFIG_MAC802154) += mac802154.o obj-$(CONFIG_MAC802154) += mac802154.o
mac802154-objs := main.o rx.o tx.o mac_cmd.o mib.o \ mac802154-objs := main.o rx.o tx.o mac_cmd.o mib.o \
iface.o llsec.o util.o iface.o llsec.o util.o cfg.o
ccflags-y += -D__CHECK_ENDIAN__ ccflags-y += -D__CHECK_ENDIAN__
/* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Authors:
* Alexander Aring <aar@pengutronix.de>
*
* Based on: net/mac80211/cfg.c
*/
#include <net/rtnetlink.h>
#include <net/cfg802154.h>
#include "ieee802154_i.h"
#include "cfg.h"
static struct net_device *
ieee802154_add_iface_deprecated(struct wpan_phy *wpan_phy,
const char *name, int type)
{
struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
struct net_device *dev;
rtnl_lock();
dev = ieee802154_if_add(local, name, NULL, type);
rtnl_unlock();
return dev;
}
static void ieee802154_del_iface_deprecated(struct wpan_phy *wpan_phy,
struct net_device *dev)
{
struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
ieee802154_if_remove(sdata);
}
const struct cfg802154_ops mac802154_config_ops = {
.add_virtual_intf_deprecated = ieee802154_add_iface_deprecated,
.del_virtual_intf_deprecated = ieee802154_del_iface_deprecated,
};
/* mac802154 configuration hooks for cfg802154
*/
#ifndef __CFG_H
#define __CFG_H
extern const struct cfg802154_ops mac802154_config_ops;
#endif /* __CFG_H */
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#define __IEEE802154_I_H #define __IEEE802154_I_H
#include <linux/mutex.h> #include <linux/mutex.h>
#include <net/cfg802154.h>
#include <net/mac802154.h> #include <net/mac802154.h>
#include <net/ieee802154_netdev.h> #include <net/ieee802154_netdev.h>
...@@ -73,18 +74,20 @@ enum ieee802154_sdata_state_bits { ...@@ -73,18 +74,20 @@ enum ieee802154_sdata_state_bits {
struct ieee802154_sub_if_data { struct ieee802154_sub_if_data {
struct list_head list; /* the ieee802154_priv->slaves list */ struct list_head list; /* the ieee802154_priv->slaves list */
struct wpan_dev wpan_dev;
struct ieee802154_local *local; struct ieee802154_local *local;
struct net_device *dev; struct net_device *dev;
int type;
unsigned long state; unsigned long state;
char name[IFNAMSIZ];
spinlock_t mib_lock; spinlock_t mib_lock;
__le16 pan_id; __le16 pan_id;
__le16 short_addr; __le16 short_addr;
__le64 extended_addr; __le64 extended_addr;
bool promisuous_mode; bool promiscuous_mode;
struct ieee802154_mac_params mac_params; struct ieee802154_mac_params mac_params;
...@@ -99,6 +102,8 @@ struct ieee802154_sub_if_data { ...@@ -99,6 +102,8 @@ struct ieee802154_sub_if_data {
struct mutex sec_mtx; struct mutex sec_mtx;
struct mac802154_llsec sec; struct mac802154_llsec sec;
/* must be last, dynamically sized area in this! */
struct ieee802154_vif vif;
}; };
#define MAC802154_CHAN_NONE 0xff /* No channel is assigned */ #define MAC802154_CHAN_NONE 0xff /* No channel is assigned */
...@@ -135,7 +140,6 @@ ieee802154_subif_start_xmit(struct sk_buff *skb, struct net_device *dev); ...@@ -135,7 +140,6 @@ ieee802154_subif_start_xmit(struct sk_buff *skb, struct net_device *dev);
/* MIB callbacks */ /* MIB callbacks */
void mac802154_dev_set_short_addr(struct net_device *dev, __le16 val); void mac802154_dev_set_short_addr(struct net_device *dev, __le16 val);
__le16 mac802154_dev_get_short_addr(const struct net_device *dev); __le16 mac802154_dev_get_short_addr(const struct net_device *dev);
void mac802154_dev_set_ieee_addr(struct net_device *dev);
__le16 mac802154_dev_get_pan_id(const struct net_device *dev); __le16 mac802154_dev_get_pan_id(const struct net_device *dev);
void mac802154_dev_set_pan_id(struct net_device *dev, __le16 val); void mac802154_dev_set_pan_id(struct net_device *dev, __le16 val);
void mac802154_dev_set_page_channel(struct net_device *dev, u8 page, u8 chan); void mac802154_dev_set_page_channel(struct net_device *dev, u8 page, u8 chan);
...@@ -174,4 +178,11 @@ void mac802154_get_table(struct net_device *dev, ...@@ -174,4 +178,11 @@ void mac802154_get_table(struct net_device *dev,
struct ieee802154_llsec_table **t); struct ieee802154_llsec_table **t);
void mac802154_unlock_table(struct net_device *dev); void mac802154_unlock_table(struct net_device *dev);
struct net_device *
mac802154_add_iface(struct wpan_phy *phy, const char *name, int type);
void ieee802154_if_remove(struct ieee802154_sub_if_data *sdata);
struct net_device *
ieee802154_if_add(struct ieee802154_local *local, const char *name,
struct wpan_dev **new_wpan_dev, int type);
#endif /* __IEEE802154_I_H */ #endif /* __IEEE802154_I_H */
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#include <net/rtnetlink.h> #include <net/rtnetlink.h>
#include <linux/nl802154.h> #include <linux/nl802154.h>
#include <net/af_ieee802154.h>
#include <net/mac802154.h> #include <net/mac802154.h>
#include <net/ieee802154_netdev.h> #include <net/ieee802154_netdev.h>
#include <net/cfg802154.h> #include <net/cfg802154.h>
...@@ -110,37 +109,21 @@ mac802154_wpan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ...@@ -110,37 +109,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) 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; struct sockaddr *addr = p;
__le64 extended_addr;
if (netif_running(dev)) if (netif_running(dev))
return -EBUSY; return -EBUSY;
/* FIXME: validate addr */ ieee802154_be64_to_le64(&extended_addr, addr->sa_data);
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); if (!ieee802154_is_valid_extended_addr(extended_addr))
mac802154_dev_set_ieee_addr(dev); return -EINVAL;
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;
}
void mac802154_get_mac_params(struct net_device *dev, memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
struct ieee802154_mac_params *params) sdata->extended_addr = extended_addr;
{
struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
mutex_lock(&sdata->local->iflist_mtx); return mac802154_wpan_update_llsec(dev);
*params = sdata->mac_params;
mutex_unlock(&sdata->local->iflist_mtx);
} }
static int mac802154_slave_open(struct net_device *dev) static int mac802154_slave_open(struct net_device *dev)
...@@ -152,10 +135,11 @@ static int mac802154_slave_open(struct net_device *dev) ...@@ -152,10 +135,11 @@ static int mac802154_slave_open(struct net_device *dev)
ASSERT_RTNL(); ASSERT_RTNL();
if (sdata->type == IEEE802154_DEV_WPAN) { if (sdata->vif.type == IEEE802154_DEV_WPAN) {
mutex_lock(&sdata->local->iflist_mtx); mutex_lock(&sdata->local->iflist_mtx);
list_for_each_entry(subif, &sdata->local->interfaces, list) { list_for_each_entry(subif, &sdata->local->interfaces, list) {
if (subif != sdata && subif->type == sdata->type && if (subif != sdata &&
subif->vif.type == sdata->vif.type &&
ieee802154_sdata_running(subif)) { ieee802154_sdata_running(subif)) {
mutex_unlock(&sdata->local->iflist_mtx); mutex_unlock(&sdata->local->iflist_mtx);
return -EBUSY; return -EBUSY;
...@@ -197,32 +181,27 @@ static int mac802154_wpan_open(struct net_device *dev) ...@@ -197,32 +181,27 @@ static int mac802154_wpan_open(struct net_device *dev)
mutex_lock(&phy->pib_lock); mutex_lock(&phy->pib_lock);
if (local->hw.flags & IEEE802154_HW_PROMISCUOUS) { if (local->hw.flags & IEEE802154_HW_PROMISCUOUS) {
rc = drv_set_promiscuous_mode(local, sdata->promisuous_mode); rc = drv_set_promiscuous_mode(local, sdata->promiscuous_mode);
if (rc < 0) if (rc < 0)
goto out; goto out;
} }
if (local->hw.flags & IEEE802154_HW_TXPOWER) { if (local->hw.flags & IEEE802154_HW_AFILT) {
rc = drv_set_tx_power(local, sdata->mac_params.transmit_power); rc = drv_set_pan_id(local, sdata->pan_id);
if (rc < 0) if (rc < 0)
goto out; goto out;
}
if (local->hw.flags & IEEE802154_HW_LBT) { rc = drv_set_extended_addr(local, sdata->extended_addr);
rc = drv_set_lbt_mode(local, sdata->mac_params.lbt);
if (rc < 0) if (rc < 0)
goto out; goto out;
}
if (local->hw.flags & IEEE802154_HW_CCA_MODE) { rc = drv_set_short_addr(local, sdata->short_addr);
rc = drv_set_cca_mode(local, sdata->mac_params.cca_mode);
if (rc < 0) if (rc < 0)
goto out; goto out;
} }
if (local->hw.flags & IEEE802154_HW_CCA_ED_LEVEL) { if (local->hw.flags & IEEE802154_HW_LBT) {
rc = drv_set_cca_ed_level(local, rc = drv_set_lbt_mode(local, sdata->mac_params.lbt);
sdata->mac_params.cca_ed_level);
if (rc < 0) if (rc < 0)
goto out; goto out;
} }
...@@ -402,30 +381,23 @@ static void mac802154_wpan_free(struct net_device *dev) ...@@ -402,30 +381,23 @@ static void mac802154_wpan_free(struct net_device *dev)
free_netdev(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_EXTENDED_ADDR_LEN;
memset(dev->broadcast, 0xff, IEEE802154_EXTENDED_ADDR_LEN);
dev->addr_len = IEEE802154_ADDR_LEN;
memset(dev->broadcast, 0xff, IEEE802154_ADDR_LEN);
dev->hard_header_len = MAC802154_FRAME_HARD_HEADER_LEN; dev->hard_header_len = MAC802154_FRAME_HARD_HEADER_LEN;
dev->header_ops = &mac802154_header_ops;
dev->needed_tailroom = 2 + 16; /* FCS + MIC */ dev->needed_tailroom = 2 + 16; /* FCS + MIC */
dev->mtu = IEEE802154_MTU; dev->mtu = IEEE802154_MTU;
dev->tx_queue_len = 300; dev->tx_queue_len = 300;
dev->type = ARPHRD_IEEE802154;
dev->flags = IFF_NOARP | IFF_BROADCAST; dev->flags = IFF_NOARP | IFF_BROADCAST;
}
dev->destructor = mac802154_wpan_free; static int
dev->netdev_ops = &mac802154_wpan_ops; ieee802154_setup_sdata(struct ieee802154_sub_if_data *sdata, int type)
dev->ml_priv = &mac802154_mlme_wpan; {
/* set some type-dependent values */
sdata = IEEE802154_DEV_TO_SUB_IF(dev); sdata->vif.type = type;
sdata->type = IEEE802154_DEV_WPAN;
spin_lock_init(&sdata->mib_lock);
mutex_init(&sdata->sec_mtx);
get_random_bytes(&sdata->bsn, 1); get_random_bytes(&sdata->bsn, 1);
get_random_bytes(&sdata->dsn, 1); get_random_bytes(&sdata->dsn, 1);
...@@ -437,30 +409,113 @@ void mac802154_wpan_setup(struct net_device *dev) ...@@ -437,30 +409,113 @@ void mac802154_wpan_setup(struct net_device *dev)
/* for compatibility, actual default is 3 */ /* for compatibility, actual default is 3 */
sdata->mac_params.frame_retries = -1; sdata->mac_params.frame_retries = -1;
ieee802154_be64_to_le64(&sdata->extended_addr, sdata->dev->dev_addr);
sdata->pan_id = cpu_to_le16(IEEE802154_PANID_BROADCAST); sdata->pan_id = cpu_to_le16(IEEE802154_PANID_BROADCAST);
sdata->short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST); sdata->short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST);
sdata->promisuous_mode = false; 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->promiscuous_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->promiscuous_mode = true;
break;
default:
BUG();
}
mac802154_llsec_init(&sdata->sec); 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->needed_tailroom = 2; /* room for FCS */ ASSERT_RTNL();
dev->mtu = IEEE802154_MTU;
dev->tx_queue_len = 10; ndev = alloc_netdev(sizeof(*sdata) + local->hw.vif_data_size, name,
dev->type = ARPHRD_IEEE802154_MONITOR; NET_NAME_UNKNOWN, ieee802154_if_setup);
dev->flags = IFF_NOARP | IFF_BROADCAST; if (!ndev)
return ERR_PTR(-ENOMEM);
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;
}
ieee802154_le64_to_be64(ndev->perm_addr,
&local->hw.phy->perm_extended_addr);
memcpy(ndev->dev_addr, ndev->perm_addr, IEEE802154_EXTENDED_ADDR_LEN);
/* 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);
dev->destructor = free_netdev; if (new_wpan_dev)
dev->netdev_ops = &mac802154_monitor_ops; *new_wpan_dev = &sdata->wpan_dev;
dev->ml_priv = &mac802154_mlme_reduced;
sdata = IEEE802154_DEV_TO_SUB_IF(dev); return ndev;
sdata->type = IEEE802154_DEV_MONITOR;
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->promisuous_mode = true; synchronize_rcu();
unregister_netdevice(sdata->dev);
} }
...@@ -25,9 +25,9 @@ ...@@ -25,9 +25,9 @@
#include <net/ieee802154_netdev.h> #include <net/ieee802154_netdev.h>
#include <net/cfg802154.h> #include <net/cfg802154.h>
#include <net/mac802154.h> #include <net/mac802154.h>
#include <net/nl802154.h>
#include "ieee802154_i.h" #include "ieee802154_i.h"
#include "driver-ops.h"
static int mac802154_mlme_start_req(struct net_device *dev, static int mac802154_mlme_start_req(struct net_device *dev,
struct ieee802154_addr *addr, struct ieee802154_addr *addr,
...@@ -43,7 +43,6 @@ static int mac802154_mlme_start_req(struct net_device *dev, ...@@ -43,7 +43,6 @@ static int mac802154_mlme_start_req(struct net_device *dev,
mac802154_dev_set_pan_id(dev, addr->pan_id); mac802154_dev_set_pan_id(dev, addr->pan_id);
mac802154_dev_set_short_addr(dev, addr->short_addr); mac802154_dev_set_short_addr(dev, addr->short_addr);
mac802154_dev_set_ieee_addr(dev);
mac802154_dev_set_page_channel(dev, page, channel); mac802154_dev_set_page_channel(dev, page, channel);
if (ops->llsec) { if (ops->llsec) {
...@@ -65,32 +64,38 @@ static int mac802154_mlme_start_req(struct net_device *dev, ...@@ -65,32 +64,38 @@ static int mac802154_mlme_start_req(struct net_device *dev,
rc = ops->llsec->set_params(dev, &params, changed); rc = ops->llsec->set_params(dev, &params, changed);
} }
/* FIXME: add validation for unused parameters to be sane
* for SoftMAC
*/
ieee802154_nl_start_confirm(dev, IEEE802154_SUCCESS);
return rc; return rc;
} }
static struct wpan_phy *mac802154_get_phy(const struct net_device *dev)
{
struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
BUG_ON(dev->type != ARPHRD_IEEE802154);
return to_phy(get_device(&sdata->local->phy->dev));
}
static int mac802154_set_mac_params(struct net_device *dev, static int mac802154_set_mac_params(struct net_device *dev,
const struct ieee802154_mac_params *params) const struct ieee802154_mac_params *params)
{ {
struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
struct ieee802154_local *local = sdata->local;
int ret;
mutex_lock(&sdata->local->iflist_mtx); mutex_lock(&sdata->local->iflist_mtx);
sdata->mac_params = *params; sdata->mac_params = *params;
mutex_unlock(&sdata->local->iflist_mtx); mutex_unlock(&sdata->local->iflist_mtx);
if (local->hw.flags & IEEE802154_HW_TXPOWER) {
ret = drv_set_tx_power(local, params->transmit_power);
if (ret < 0)
return ret;
}
if (local->hw.flags & IEEE802154_HW_CCA_MODE) {
ret = drv_set_cca_mode(local, params->cca_mode);
if (ret < 0)
return ret;
}
if (local->hw.flags & IEEE802154_HW_CCA_ED_LEVEL) {
ret = drv_set_cca_ed_level(local, params->cca_ed_level);
if (ret < 0)
return ret;
}
return 0; return 0;
} }
...@@ -120,12 +125,7 @@ static struct ieee802154_llsec_ops mac802154_llsec_ops = { ...@@ -120,12 +125,7 @@ static struct ieee802154_llsec_ops mac802154_llsec_ops = {
.unlock_table = mac802154_unlock_table, .unlock_table = mac802154_unlock_table,
}; };
struct ieee802154_reduced_mlme_ops mac802154_mlme_reduced = {
.get_phy = mac802154_get_phy,
};
struct ieee802154_mlme_ops mac802154_mlme_wpan = { struct ieee802154_mlme_ops mac802154_mlme_wpan = {
.get_phy = mac802154_get_phy,
.start_req = mac802154_mlme_start_req, .start_req = mac802154_mlme_start_req,
.get_pan_id = mac802154_dev_get_pan_id, .get_pan_id = mac802154_dev_get_pan_id,
.get_short_addr = mac802154_dev_get_short_addr, .get_short_addr = mac802154_dev_get_short_addr,
......
...@@ -28,90 +28,7 @@ ...@@ -28,90 +28,7 @@
#include <net/cfg802154.h> #include <net/cfg802154.h>
#include "ieee802154_i.h" #include "ieee802154_i.h"
#include "cfg.h"
static int
mac802154_netdev_register(struct wpan_phy *phy, struct net_device *dev)
{
struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
struct ieee802154_local *local;
int err;
local = wpan_phy_priv(phy);
sdata->dev = dev;
sdata->local = local;
dev->needed_headroom = local->hw.extra_tx_headroom;
SET_NETDEV_DEV(dev, &local->phy->dev);
err = register_netdev(dev);
if (err < 0)
return err;
rtnl_lock();
mutex_lock(&local->iflist_mtx);
list_add_tail_rcu(&sdata->list, &local->interfaces);
mutex_unlock(&local->iflist_mtx);
rtnl_unlock();
return 0;
}
static void
mac802154_del_iface(struct wpan_phy *phy, struct net_device *dev)
{
struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
ASSERT_RTNL();
BUG_ON(sdata->local->phy != phy);
mutex_lock(&sdata->local->iflist_mtx);
list_del_rcu(&sdata->list);
mutex_unlock(&sdata->local->iflist_mtx);
synchronize_rcu();
unregister_netdevice(sdata->dev);
}
static struct net_device *
mac802154_add_iface(struct wpan_phy *phy, const char *name, int type)
{
struct net_device *dev;
int err = -ENOMEM;
switch (type) {
case IEEE802154_DEV_MONITOR:
dev = alloc_netdev(sizeof(struct ieee802154_sub_if_data),
name, NET_NAME_UNKNOWN,
mac802154_monitor_setup);
break;
case IEEE802154_DEV_WPAN:
dev = alloc_netdev(sizeof(struct ieee802154_sub_if_data),
name, NET_NAME_UNKNOWN,
mac802154_wpan_setup);
break;
default:
dev = NULL;
err = -EINVAL;
break;
}
if (!dev)
goto err;
err = mac802154_netdev_register(phy, dev);
if (err)
goto err_free;
dev_hold(dev); /* we return an incremented device refcount */
return dev;
err_free:
free_netdev(dev);
err:
return ERR_PTR(err);
}
static void ieee802154_tasklet_handler(unsigned long data) static void ieee802154_tasklet_handler(unsigned long data)
{ {
...@@ -169,7 +86,7 @@ ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops) ...@@ -169,7 +86,7 @@ ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops)
priv_size = ALIGN(sizeof(*local), NETDEV_ALIGN) + priv_data_len; priv_size = ALIGN(sizeof(*local), NETDEV_ALIGN) + priv_data_len;
phy = wpan_phy_alloc(priv_size); phy = wpan_phy_alloc(&mac802154_config_ops, priv_size);
if (!phy) { if (!phy) {
pr_err("failure to allocate master IEEE802.15.4 device\n"); pr_err("failure to allocate master IEEE802.15.4 device\n");
return NULL; return NULL;
...@@ -209,6 +126,7 @@ EXPORT_SYMBOL(ieee802154_free_hw); ...@@ -209,6 +126,7 @@ EXPORT_SYMBOL(ieee802154_free_hw);
int ieee802154_register_hw(struct ieee802154_hw *hw) int ieee802154_register_hw(struct ieee802154_hw *hw)
{ {
struct ieee802154_local *local = hw_to_local(hw); struct ieee802154_local *local = hw_to_local(hw);
struct net_device *dev;
int rc = -ENOSYS; int rc = -ENOSYS;
local->workqueue = local->workqueue =
...@@ -220,13 +138,21 @@ int ieee802154_register_hw(struct ieee802154_hw *hw) ...@@ -220,13 +138,21 @@ int ieee802154_register_hw(struct ieee802154_hw *hw)
wpan_phy_set_dev(local->phy, local->hw.parent); wpan_phy_set_dev(local->phy, local->hw.parent);
local->phy->add_iface = mac802154_add_iface;
local->phy->del_iface = mac802154_del_iface;
rc = wpan_phy_register(local->phy); rc = wpan_phy_register(local->phy);
if (rc < 0) if (rc < 0)
goto out_wq; goto out_wq;
rtnl_lock();
dev = ieee802154_if_add(local, "wpan%d", NULL, IEEE802154_DEV_WPAN);
if (IS_ERR(dev)) {
rtnl_unlock();
rc = PTR_ERR(dev);
goto out_wq;
}
rtnl_unlock();
return 0; return 0;
out_wq: out_wq:
......
...@@ -26,51 +26,6 @@ ...@@ -26,51 +26,6 @@
#include "ieee802154_i.h" #include "ieee802154_i.h"
#include "driver-ops.h" #include "driver-ops.h"
struct hw_addr_filt_notify_work {
struct work_struct work;
struct net_device *dev;
unsigned long changed;
};
static struct ieee802154_local *mac802154_slave_get_priv(struct net_device *dev)
{
struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
BUG_ON(dev->type != ARPHRD_IEEE802154);
return sdata->local;
}
static void hw_addr_notify(struct work_struct *work)
{
struct hw_addr_filt_notify_work *nw = container_of(work,
struct hw_addr_filt_notify_work, work);
struct ieee802154_local *local = mac802154_slave_get_priv(nw->dev);
int res;
res = local->ops->set_hw_addr_filt(&local->hw, &local->hw.hw_filt,
nw->changed);
if (res)
pr_debug("failed changed mask %lx\n", nw->changed);
kfree(nw);
}
static void set_hw_addr_filt(struct net_device *dev, unsigned long changed)
{
struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
struct hw_addr_filt_notify_work *work;
work = kzalloc(sizeof(*work), GFP_ATOMIC);
if (!work)
return;
INIT_WORK(&work->work, hw_addr_notify);
work->dev = dev;
work->changed = changed;
queue_work(sdata->local->workqueue, &work->work);
}
void mac802154_dev_set_short_addr(struct net_device *dev, __le16 val) void mac802154_dev_set_short_addr(struct net_device *dev, __le16 val)
{ {
struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
...@@ -80,12 +35,6 @@ void mac802154_dev_set_short_addr(struct net_device *dev, __le16 val) ...@@ -80,12 +35,6 @@ void mac802154_dev_set_short_addr(struct net_device *dev, __le16 val)
spin_lock_bh(&sdata->mib_lock); spin_lock_bh(&sdata->mib_lock);
sdata->short_addr = val; sdata->short_addr = val;
spin_unlock_bh(&sdata->mib_lock); spin_unlock_bh(&sdata->mib_lock);
if ((sdata->local->ops->set_hw_addr_filt) &&
(sdata->local->hw.hw_filt.short_addr != sdata->short_addr)) {
sdata->local->hw.hw_filt.short_addr = sdata->short_addr;
set_hw_addr_filt(dev, IEEE802154_AFILT_SADDR_CHANGED);
}
} }
__le16 mac802154_dev_get_short_addr(const struct net_device *dev) __le16 mac802154_dev_get_short_addr(const struct net_device *dev)
...@@ -102,20 +51,6 @@ __le16 mac802154_dev_get_short_addr(const struct net_device *dev) ...@@ -102,20 +51,6 @@ __le16 mac802154_dev_get_short_addr(const struct net_device *dev)
return ret; return ret;
} }
void mac802154_dev_set_ieee_addr(struct net_device *dev)
{
struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
struct ieee802154_local *local = sdata->local;
sdata->extended_addr = ieee802154_devaddr_from_raw(dev->dev_addr);
if (local->ops->set_hw_addr_filt &&
local->hw.hw_filt.ieee_addr != sdata->extended_addr) {
local->hw.hw_filt.ieee_addr = sdata->extended_addr;
set_hw_addr_filt(dev, IEEE802154_AFILT_IEEEADDR_CHANGED);
}
}
__le16 mac802154_dev_get_pan_id(const struct net_device *dev) __le16 mac802154_dev_get_pan_id(const struct net_device *dev)
{ {
struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
...@@ -139,12 +74,6 @@ void mac802154_dev_set_pan_id(struct net_device *dev, __le16 val) ...@@ -139,12 +74,6 @@ void mac802154_dev_set_pan_id(struct net_device *dev, __le16 val)
spin_lock_bh(&sdata->mib_lock); spin_lock_bh(&sdata->mib_lock);
sdata->pan_id = val; sdata->pan_id = val;
spin_unlock_bh(&sdata->mib_lock); spin_unlock_bh(&sdata->mib_lock);
if ((sdata->local->ops->set_hw_addr_filt) &&
(sdata->local->hw.hw_filt.pan_id != sdata->pan_id)) {
sdata->local->hw.hw_filt.pan_id = sdata->pan_id;
set_hw_addr_filt(dev, IEEE802154_AFILT_PANID_CHANGED);
}
} }
u8 mac802154_dev_get_dsn(const struct net_device *dev) u8 mac802154_dev_get_dsn(const struct net_device *dev)
......
...@@ -208,7 +208,7 @@ __ieee802154_rx_handle_packet(struct ieee802154_local *local, ...@@ -208,7 +208,7 @@ __ieee802154_rx_handle_packet(struct ieee802154_local *local,
} }
list_for_each_entry_rcu(sdata, &local->interfaces, list) { list_for_each_entry_rcu(sdata, &local->interfaces, list) {
if (sdata->type != IEEE802154_DEV_WPAN || if (sdata->vif.type != IEEE802154_DEV_WPAN ||
!netif_running(sdata->dev)) !netif_running(sdata->dev))
continue; continue;
...@@ -233,7 +233,7 @@ ieee802154_monitors_rx(struct ieee802154_local *local, struct sk_buff *skb) ...@@ -233,7 +233,7 @@ ieee802154_monitors_rx(struct ieee802154_local *local, struct sk_buff *skb)
skb->protocol = htons(ETH_P_IEEE802154); skb->protocol = htons(ETH_P_IEEE802154);
list_for_each_entry_rcu(sdata, &local->interfaces, list) { list_for_each_entry_rcu(sdata, &local->interfaces, list) {
if (sdata->type != IEEE802154_DEV_MONITOR) if (sdata->vif.type != IEEE802154_DEV_MONITOR)
continue; continue;
if (!ieee802154_sdata_running(sdata)) if (!ieee802154_sdata_running(sdata))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment