From 9f440b7bc786883c117be9c0f438a27b356f64b4 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Fri, 8 Feb 2013 15:53:36 +0100 Subject: brcmfmac: add peer-to-peer group discovery support First part for P2P support. It is a variation on the existing scanning functionality and is used to discover peer-to-peer group owners and/or peer-to-peer devices in listen state. Tested with wpa_cli/wpa_supplicant v2.0-devel. Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- .../net/wireless/brcm80211/brcmfmac/wl_cfg80211.h | 78 +++++++++++++++++++++- 1 file changed, 76 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h index e4d9cc7a8e63..014a463a86b9 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h @@ -41,6 +41,38 @@ #define WL_AUTH_SHARED_KEY 1 /* d11 shared authentication */ #define IE_MAX_LEN 512 +/* IE TLV processing */ +#define TLV_LEN_OFF 1 /* length offset */ +#define TLV_HDR_LEN 2 /* header length */ +#define TLV_BODY_OFF 2 /* body offset */ +#define TLV_OUI_LEN 3 /* oui id length */ + +/* 802.11 Mgmt Packet flags */ +#define BRCMF_VNDR_IE_BEACON_FLAG 0x1 +#define BRCMF_VNDR_IE_PRBRSP_FLAG 0x2 +#define BRCMF_VNDR_IE_ASSOCRSP_FLAG 0x4 +#define BRCMF_VNDR_IE_AUTHRSP_FLAG 0x8 +#define BRCMF_VNDR_IE_PRBREQ_FLAG 0x10 +#define BRCMF_VNDR_IE_ASSOCREQ_FLAG 0x20 +/* vendor IE in IW advertisement protocol ID field */ +#define BRCMF_VNDR_IE_IWAPID_FLAG 0x40 +/* allow custom IE id */ +#define BRCMF_VNDR_IE_CUSTOM_FLAG 0x100 + +/* P2P Action Frames flags (spec ordered) */ +#define BRCMF_VNDR_IE_GONREQ_FLAG 0x001000 +#define BRCMF_VNDR_IE_GONRSP_FLAG 0x002000 +#define BRCMF_VNDR_IE_GONCFM_FLAG 0x004000 +#define BRCMF_VNDR_IE_INVREQ_FLAG 0x008000 +#define BRCMF_VNDR_IE_INVRSP_FLAG 0x010000 +#define BRCMF_VNDR_IE_DISREQ_FLAG 0x020000 +#define BRCMF_VNDR_IE_DISRSP_FLAG 0x040000 +#define BRCMF_VNDR_IE_PRDREQ_FLAG 0x080000 +#define BRCMF_VNDR_IE_PRDRSP_FLAG 0x100000 + +#define BRCMF_VNDR_IE_P2PAF_SHIFT 12 + + /** * enum brcmf_scan_status - dongle scan status * @@ -52,11 +84,19 @@ enum brcmf_scan_status { BRCMF_SCAN_STATUS_ABORT, }; -/* wi-fi mode */ +/** + * enum wl_mode - driver mode of virtual interface. + * + * @WL_MODE_BSS: connects to BSS. + * @WL_MODE_IBSS: operate as ad-hoc. + * @WL_MODE_AP: operate as access-point. + * @WL_MODE_P2P: provide P2P discovery. + */ enum wl_mode { WL_MODE_BSS, WL_MODE_IBSS, - WL_MODE_AP + WL_MODE_AP, + WL_MODE_P2P }; /* dongle configuration */ @@ -122,14 +162,18 @@ enum brcmf_vif_status { /** * struct vif_saved_ie - holds saved IEs for a virtual interface. * + * @probe_req_ie: IE info for probe request. * @probe_res_ie: IE info for probe response. * @beacon_ie: IE info for beacon frame. + * @probe_req_ie_len: IE info length for probe request. * @probe_res_ie_len: IE info length for probe response. * @beacon_ie_len: IE info length for beacon frame. */ struct vif_saved_ie { + u8 probe_req_ie[VNDR_IES_BUF_LEN]; u8 probe_res_ie[IE_MAX_LEN]; u8 beacon_ie[IE_MAX_LEN]; + u32 probe_req_ie_len; u32 probe_res_ie_len; u32 beacon_ie_len; }; @@ -189,6 +233,9 @@ struct escan_info { u8 escan_buf[WL_ESCAN_BUF_SIZE]; struct wiphy *wiphy; struct net_device *ndev; + s32 (*run)(struct brcmf_cfg80211_info *cfg, + struct net_device *ndev, + struct cfg80211_scan_request *request, u16 action); }; /** @@ -277,6 +324,7 @@ struct brcmf_pno_scanresults_le { * * @wiphy: wiphy object for cfg80211 interface. * @conf: dongle configuration. + * @p2p: peer-to-peer specific information. * @scan_request: cfg80211 scan request object. * @usr_sync: mainly for dongle up/down synchronization. * @bss_list: bss_list holding scanned ap information. @@ -308,6 +356,7 @@ struct brcmf_pno_scanresults_le { struct brcmf_cfg80211_info { struct wiphy *wiphy; struct brcmf_cfg80211_conf *conf; + struct brcmf_p2p_info p2p; struct cfg80211_scan_request *scan_request; struct mutex usr_sync; struct brcmf_scan_results *bss_list; @@ -337,6 +386,19 @@ struct brcmf_cfg80211_info { u8 vif_cnt; }; +/** + * struct brcmf_tlv - tag_ID/length/value_buffer tuple. + * + * @id: tag identifier. + * @len: number of bytes in value buffer. + * @data: value buffer. + */ +struct brcmf_tlv { + u8 id; + u8 len; + u8 data[1]; +}; + static inline struct wiphy *cfg_to_wiphy(struct brcmf_cfg80211_info *cfg) { return cfg->wiphy; @@ -389,4 +451,16 @@ void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg); s32 brcmf_cfg80211_up(struct net_device *ndev); s32 brcmf_cfg80211_down(struct net_device *ndev); +struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg, + struct net_device *netdev, + enum nl80211_iftype type, + bool pm_block); +void brcmf_free_vif(struct brcmf_cfg80211_vif *vif); + +s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag, + const u8 *vndr_ie_buf, u32 vndr_ie_len); +struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key); +u16 channel_to_chanspec(struct ieee80211_channel *ch); +u32 wl_get_vif_state_all(struct brcmf_cfg80211_info *cfg, unsigned long state); + #endif /* _wl_cfg80211_h_ */ -- cgit From d3c0b63396442d564ceb4db0dcc51e70918b9c93 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Fri, 8 Feb 2013 15:53:37 +0100 Subject: brcmfmac: add support for creating P2P client/GO interface This patch allow the creation of P2P client and group owner virtual interfaces in the driver. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky (Zhenhui) Lin Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- .../net/wireless/brcm80211/brcmfmac/wl_cfg80211.h | 26 +++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h index 014a463a86b9..691f613d99d2 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h @@ -319,6 +319,23 @@ struct brcmf_pno_scanresults_le { __le32 count; }; +/** + * struct brcmf_cfg80211_vif_event - virtual interface event information. + * + * @vif_wq: waitqueue awaiting interface event from firmware. + * @vif_event_lock: protects other members in this structure. + * @vif_complete: completion for net attach. + * @action: either add, change, or delete. + * @vif: virtual interface object related to the event. + */ +struct brcmf_cfg80211_vif_event { + wait_queue_head_t vif_wq; + struct mutex vif_event_lock; + struct completion vif_complete; + u8 action; + struct brcmf_cfg80211_vif *vif; +}; + /** * struct brcmf_cfg80211_info - dongle private data of cfg80211 interface * @@ -352,6 +369,7 @@ struct brcmf_pno_scanresults_le { * @escan_ioctl_buf: dongle command buffer for escan commands. * @vif_list: linked list of vif instances. * @vif_cnt: number of vif instances. + * @vif_event: vif event signalling. */ struct brcmf_cfg80211_info { struct wiphy *wiphy; @@ -384,6 +402,7 @@ struct brcmf_cfg80211_info { u8 *escan_ioctl_buf; struct list_head vif_list; u8 vif_cnt; + struct brcmf_cfg80211_vif_event vif_event; }; /** @@ -452,7 +471,6 @@ s32 brcmf_cfg80211_up(struct net_device *ndev); s32 brcmf_cfg80211_down(struct net_device *ndev); struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg, - struct net_device *netdev, enum nl80211_iftype type, bool pm_block); void brcmf_free_vif(struct brcmf_cfg80211_vif *vif); @@ -462,5 +480,11 @@ s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag, struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key); u16 channel_to_chanspec(struct ieee80211_channel *ch); u32 wl_get_vif_state_all(struct brcmf_cfg80211_info *cfg, unsigned long state); +void brcmf_cfg80211_arm_vif_event(struct brcmf_cfg80211_info *cfg, + struct brcmf_cfg80211_vif *vif); +bool brcmf_cfg80211_vif_event_armed(struct brcmf_cfg80211_info *cfg); +int brcmf_cfg80211_wait_vif_event_timeout(struct brcmf_cfg80211_info *cfg, + u8 action, ulong timeout); +void brcmf_cfg80211_vif_complete(struct brcmf_cfg80211_info *info); #endif /* _wl_cfg80211_h_ */ -- cgit From 0de8aace0ff499bf1b6597e7f272961d2e335933 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Fri, 8 Feb 2013 15:53:38 +0100 Subject: brcmfmac: add support for P2P listen mode. With this patch a device can be put in p2p listen mode and becomes visible for other p2p devices (via p2p_find). Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Arend van Spriel Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h index 691f613d99d2..a996afa8df4d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h @@ -189,6 +189,7 @@ struct vif_saved_ie { * @sme_state: SME state using enum brcmf_vif_status bits. * @pm_block: power-management blocked. * @list: linked list. + * @mgmt_rx_reg: registered rx mgmt frame types. */ struct brcmf_cfg80211_vif { struct brcmf_if *ifp; @@ -200,6 +201,7 @@ struct brcmf_cfg80211_vif { bool pm_block; struct vif_saved_ie saved_ie; struct list_head list; + u16 mgmt_rx_reg; }; /* association inform */ -- cgit From 5f4f9f114eef4907b6077d19dd5ad7d0a27e0f80 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Fri, 8 Feb 2013 15:53:41 +0100 Subject: brcmfmac: implement support for deleting virtual interfaces Deletion of the virtual interface was not fully supported so adding it now. Tested using p2p_connect command in wpa_supplicant. Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h index a996afa8df4d..506818844a74 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h @@ -148,6 +148,7 @@ struct brcmf_cfg80211_profile { * @BRCMF_VIF_STATUS_READY: ready for operation. * @BRCMF_VIF_STATUS_CONNECTING: connect/join in progress. * @BRCMF_VIF_STATUS_CONNECTED: connected/joined succesfully. + * @BRCMF_VIF_STATUS_DISCONNECTING: disconnect/disable in progress. * @BRCMF_VIF_STATUS_AP_CREATING: interface configured for AP operation. * @BRCMF_VIF_STATUS_AP_CREATED: AP operation started. */ @@ -155,6 +156,7 @@ enum brcmf_vif_status { BRCMF_VIF_STATUS_READY, BRCMF_VIF_STATUS_CONNECTING, BRCMF_VIF_STATUS_CONNECTED, + BRCMF_VIF_STATUS_DISCONNECTING, BRCMF_VIF_STATUS_AP_CREATING, BRCMF_VIF_STATUS_AP_CREATED }; @@ -405,6 +407,7 @@ struct brcmf_cfg80211_info { struct list_head vif_list; u8 vif_cnt; struct brcmf_cfg80211_vif_event vif_event; + struct completion vif_disabled; }; /** @@ -479,6 +482,7 @@ void brcmf_free_vif(struct brcmf_cfg80211_vif *vif); s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag, const u8 *vndr_ie_buf, u32 vndr_ie_len); +s32 brcmf_vif_clear_mgmt_ies(struct brcmf_cfg80211_vif *vif); struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key); u16 channel_to_chanspec(struct ieee80211_channel *ch); u32 wl_get_vif_state_all(struct brcmf_cfg80211_info *cfg, unsigned long state); -- cgit From 7a5c1f64f64c8504c8117558a426b610ebc77aa0 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Fri, 8 Feb 2013 15:53:44 +0100 Subject: brcmfmac: add p2p change vif routines. Add support for changing existing interface into p2p go interface. Reviewed-by: Arend Van Spriel Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h index 506818844a74..215530881539 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h @@ -492,5 +492,9 @@ bool brcmf_cfg80211_vif_event_armed(struct brcmf_cfg80211_info *cfg); int brcmf_cfg80211_wait_vif_event_timeout(struct brcmf_cfg80211_info *cfg, u8 action, ulong timeout); void brcmf_cfg80211_vif_complete(struct brcmf_cfg80211_info *info); +s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, + struct net_device *ndev, + bool aborted, bool fw_abort); +void brcmf_set_mpc(struct net_device *ndev, int mpc); #endif /* _wl_cfg80211_h_ */ -- cgit From 89286dc9452082c710e0767f3191b03421601214 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Fri, 8 Feb 2013 15:53:46 +0100 Subject: brcmfmac: Update connect setup/handling routines for multiple bss. In preparation of p2p connections update the sta connect setup and handling routines. Use join iovar and bsscfg commands where applicable. Handle assoc ind per bsscfg (vif) and generalize vndr ie setup to support assoc IEs and support all setup types, e.g. sta, ap and p2p. Reviewed-by: Arend Van Spriel Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h index 215530881539..259571269983 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h @@ -175,9 +175,11 @@ struct vif_saved_ie { u8 probe_req_ie[VNDR_IES_BUF_LEN]; u8 probe_res_ie[IE_MAX_LEN]; u8 beacon_ie[IE_MAX_LEN]; + u8 assoc_req_ie[IE_MAX_LEN]; u32 probe_req_ie_len; u32 probe_res_ie_len; u32 beacon_ie_len; + u32 assoc_req_ie_len; }; /** -- cgit From 18e2f61db3b708e0a22ccc403cb6ab2203d6faab Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Fri, 8 Feb 2013 15:53:49 +0100 Subject: brcmfmac: P2P action frame tx. With this patch it is possible to send action frames. Reviewed-by: Arend Van Spriel Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h index 259571269983..a020555a338b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h @@ -498,5 +498,6 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, struct net_device *ndev, bool aborted, bool fw_abort); void brcmf_set_mpc(struct net_device *ndev, int mpc); +void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg); #endif /* _wl_cfg80211_h_ */ -- cgit From dae3a27359adc277ea3b399b8240ce348304289e Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Fri, 8 Feb 2013 15:54:00 +0100 Subject: brcmfmac: Cleanup of unused defines. Remove some unused defines and comments. Also use same define for IE length. Reviewed-by: Arend Van Spriel Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h index a020555a338b..b886f22a4acb 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h @@ -172,7 +172,7 @@ enum brcmf_vif_status { * @beacon_ie_len: IE info length for beacon frame. */ struct vif_saved_ie { - u8 probe_req_ie[VNDR_IES_BUF_LEN]; + u8 probe_req_ie[IE_MAX_LEN]; u8 probe_res_ie[IE_MAX_LEN]; u8 beacon_ie[IE_MAX_LEN]; u8 assoc_req_ie[IE_MAX_LEN]; -- cgit From 4b3a89de8a2e91bf873a0044fa62b2f5afb6693a Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Fri, 8 Feb 2013 15:54:01 +0100 Subject: brcmfmac: Create netdev before returning from add_virtual_intf. Currently netdev gets created possibly after returning from add_virtual_intf. This is because add_if is handled asynch. This is wrong and netdev should be up before returning. Reviewed-by: Arend Van Spriel Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Piotr Haber Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h index b886f22a4acb..8b5d4989906c 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h @@ -337,7 +337,6 @@ struct brcmf_pno_scanresults_le { struct brcmf_cfg80211_vif_event { wait_queue_head_t vif_wq; struct mutex vif_event_lock; - struct completion vif_complete; u8 action; struct brcmf_cfg80211_vif *vif; }; @@ -493,7 +492,6 @@ void brcmf_cfg80211_arm_vif_event(struct brcmf_cfg80211_info *cfg, bool brcmf_cfg80211_vif_event_armed(struct brcmf_cfg80211_info *cfg); int brcmf_cfg80211_wait_vif_event_timeout(struct brcmf_cfg80211_info *cfg, u8 action, ulong timeout); -void brcmf_cfg80211_vif_complete(struct brcmf_cfg80211_info *info); s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, struct net_device *ndev, bool aborted, bool fw_abort); -- cgit