/*
* Copyright (C) 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see .
*/
#ifndef __NET_HCI_H
#define __NET_HCI_H
#include
#include
struct nfc_hci_dev;
struct nfc_hci_ops {
int (*open) (struct nfc_hci_dev *hdev);
void (*close) (struct nfc_hci_dev *hdev);
int (*load_session) (struct nfc_hci_dev *hdev);
int (*hci_ready) (struct nfc_hci_dev *hdev);
/*
* xmit must always send the complete buffer before
* returning. Returned result must be 0 for success
* or negative for failure.
*/
int (*xmit) (struct nfc_hci_dev *hdev, struct sk_buff *skb);
int (*start_poll) (struct nfc_hci_dev *hdev,
u32 im_protocols, u32 tm_protocols);
void (*stop_poll) (struct nfc_hci_dev *hdev);
int (*dep_link_up)(struct nfc_hci_dev *hdev, struct nfc_target *target,
u8 comm_mode, u8 *gb, size_t gb_len);
int (*dep_link_down)(struct nfc_hci_dev *hdev);
int (*target_from_gate) (struct nfc_hci_dev *hdev, u8 gate,
struct nfc_target *target);
int (*complete_target_discovered) (struct nfc_hci_dev *hdev, u8 gate,
struct nfc_target *target);
int (*im_transceive) (struct nfc_hci_dev *hdev,
struct nfc_target *target, struct sk_buff *skb,
data_exchange_cb_t cb, void *cb_context);
int (*tm_send)(struct nfc_hci_dev *hdev, struct sk_buff *skb);
int (*check_presence)(struct nfc_hci_dev *hdev,
struct nfc_target *target);
int (*event_received)(struct nfc_hci_dev *hdev, u8 pipe, u8 event,
struct sk_buff *skb);
void (*cmd_received)(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd,
struct sk_buff *skb);
int (*fw_download)(struct nfc_hci_dev *hdev, const char *firmware_name);
int (*discover_se)(struct nfc_hci_dev *dev);
int (*enable_se)(struct nfc_hci_dev *dev, u32 se_idx);
int (*disable_se)(struct nfc_hci_dev *dev, u32 se_idx);
int (*se_io)(struct nfc_hci_dev *dev, u32 se_idx,
u8 *apdu, size_t apdu_length,
se_io_cb_t cb, void *cb_context);
};
/* Pipes */
#define NFC_HCI_DO_NOT_CREATE_PIPE 0x81
#define NFC_HCI_INVALID_PIPE 0x80
#define NFC_HCI_INVALID_GATE 0xFF
#define NFC_HCI_INVALID_HOST 0x80
#define NFC_HCI_LINK_MGMT_PIPE 0x00
#define NFC_HCI_ADMIN_PIPE 0x01
struct nfc_hci_gate {
u8 gate;
u8 pipe;
};
struct nfc_hci_pipe {
u8 gate;
u8 dest_host;
};
#define NFC_HCI_MAX_CUSTOM_GATES 50
/*
* According to specification 102 622 chapter 4.4 Pipes,
* the pipe identifier is 7 bits long.
*/
#define NFC_HCI_MAX_PIPES 127
struct nfc_hci_init_data {
u8 gate_count;
struct nfc_hci_gate gates[NFC_HCI_MAX_CUSTOM_GATES];
char session_id[9];
};
typedef int (*xmit) (struct sk_buff *skb, void *cb_data);
#define NFC_HCI_MAX_GATES 256
/*
* These values can be specified by a driver to indicate it requires some
* adaptation of the HCI standard.
*
* NFC_HCI_QUIRK_SHORT_CLEAR - send HCI_ADM_CLEAR_ALL_PIPE cmd with no params
*/
enum {
NFC_HCI_QUIRK_SHORT_CLEAR = 0,
};
struct nfc_hci_dev {
struct nfc_dev *ndev;
u32 max_data_link_payload;
bool shutting_down;
struct mutex msg_tx_mutex;
struct list_head msg_tx_queue;
struct work_struct msg_tx_work;
struct timer_list cmd_timer;
struct hci_msg *cmd_pending_msg;
struct sk_buff_head rx_hcp_frags;
struct work_struct msg_rx_work;
struct sk_buff_head msg_rx_queue;
struct nfc_hci_ops *ops;
struct nfc_llc *llc;
struct nfc_hci_init_data init_data;
void *clientdata;
u8 gate2pipe[NFC_HCI_MAX_GATES];
struct nfc_hci_pipe pipes[NFC_HCI_MAX_PIPES];
u8 sw_romlib;
u8 sw_patch;
u8 sw_flashlib_major;
u8 sw_flashlib_minor;
u8 hw_derivative;
u8 hw_version;
u8 hw_mpw;
u8 hw_software;
u8 hw_bsid;
int async_cb_type;
data_exchange_cb_t async_cb;
void *async_cb_context;
u8 *gb;
size_t gb_len;
unsigned long quirks;
};
/* hci device allocation */
struct nfc_hci_dev *nfc_hci_allocate_device(struct nfc_hci_ops *ops,
struct nfc_hci_init_data *init_data,
unsigned long quirks,
u32 protocols,
const char *llc_name,
int tx_headroom,
int tx_tailroom,
int max_link_payload);
void nfc_hci_free_device(struct nfc_hci_dev *hdev);
int nfc_hci_register_device(struct nfc_hci_dev *hdev);
void nfc_hci_unregister_device(struct nfc_hci_dev *hdev);
void nfc_hci_set_clientdata(struct nfc_hci_dev *hdev, void *clientdata);
void *nfc_hci_get_clientdata(struct nfc_hci_dev *hdev);
static inline int nfc_hci_set_vendor_cmds(struct nfc_hci_dev *hdev,
struct nfc_vendor_cmd *cmds,
int n_cmds)
{
return nfc_set_vendor_cmds(hdev->ndev, cmds, n_cmds);
}
void nfc_hci_driver_failure(struct nfc_hci_dev *hdev, int err);
int nfc_hci_result_to_errno(u8 result);
void nfc_hci_reset_pipes(struct nfc_hci_dev *dev);
void nfc_hci_reset_pipes_per_host(struct nfc_hci_dev *hdev, u8 host);
/* Host IDs */
#define NFC_HCI_HOST_CONTROLLER_ID 0x00
#define NFC_HCI_TERMINAL_HOST_ID 0x01
#define NFC_HCI_UICC_HOST_ID 0x02
/* Host Controller Gates and registry indexes */
#define NFC_HCI_ADMIN_GATE 0x00
#define NFC_HCI_ADMIN_SESSION_IDENTITY 0x01
#define NFC_HCI_ADMIN_MAX_PIPE 0x02
#define NFC_HCI_ADMIN_WHITELIST 0x03
#define NFC_HCI_ADMIN_HOST_LIST 0x04
#define NFC_HCI_LOOPBACK_GATE 0x04
#define NFC_HCI_ID_MGMT_GATE 0x05
#define NFC_HCI_ID_MGMT_VERSION_SW 0x01
#define NFC_HCI_ID_MGMT_VERSION_HW 0x03
#define NFC_HCI_ID_MGMT_VENDOR_NAME 0x04
#define NFC_HCI_ID_MGMT_MODEL_ID 0x05
#define NFC_HCI_ID_MGMT_HCI_VERSION 0x02
#define NFC_HCI_ID_MGMT_GATES_LIST 0x06
#define NFC_HCI_LINK_MGMT_GATE 0x06
#define NFC_HCI_LINK_MGMT_REC_ERROR 0x01
#define NFC_HCI_RF_READER_B_GATE 0x11
#define NFC_HCI_RF_READER_B_PUPI 0x03
#define NFC_HCI_RF_READER_B_APPLICATION_DATA 0x04
#define NFC_HCI_RF_READER_B_AFI 0x02
#define NFC_HCI_RF_READER_B_HIGHER_LAYER_RESPONSE 0x01
#define NFC_HCI_RF_READER_B_HIGHER_LAYER_DATA 0x05
#define NFC_HCI_RF_READER_A_GATE 0x13
#define NFC_HCI_RF_READER_A_UID 0x02
#define NFC_HCI_RF_READER_A_ATQA 0x04
#define NFC_HCI_RF_READER_A_APPLICATION_DATA 0x05
#define NFC_HCI_RF_READER_A_SAK 0x03
#define NFC_HCI_RF_READER_A_FWI_SFGT 0x06
#define NFC_HCI_RF_READER_A_DATARATE_MAX 0x01
#define NFC_HCI_TYPE_A_SEL_PROT(x) (((x) & 0x60) >> 5)
#define NFC_HCI_TYPE_A_SEL_PROT_MIFARE 0
#define NFC_HCI_TYPE_A_SEL_PROT_ISO14443 1
#define NFC_HCI_TYPE_A_SEL_PROT_DEP 2
#define NFC_HCI_TYPE_A_SEL_PROT_ISO14443_DEP 3
/* Generic events */
#define NFC_HCI_EVT_HCI_END_OF_OPERATION 0x01
#define NFC_HCI_EVT_POST_DATA 0x02
#define NFC_HCI_EVT_HOT_PLUG 0x03
/* Generic commands */
#define NFC_HCI_ANY_SET_PARAMETER 0x01
#define NFC_HCI_ANY_GET_PARAMETER 0x02
#define NFC_HCI_ANY_OPEN_PIPE 0x03
#define NFC_HCI_ANY_CLOSE_PIPE 0x04
/* Reader RF gates events */
#define NFC_HCI_EVT_READER_REQUESTED 0x10
#define NFC_HCI_EVT_END_OPERATION 0x11
/* Reader Application gate events */
#define NFC_HCI_EVT_TARGET_DISCOVERED 0x10
/* receiving messages from lower layer */
void nfc_hci_resp_received(struct nfc_hci_dev *hdev, u8 result,
struct sk_buff *skb);
void nfc_hci_cmd_received(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd,
struct sk_buff *skb);
void nfc_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event,
struct sk_buff *skb);
void nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb);
/* connecting to gates and sending hci instructions */
int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate,
u8 pipe);
int nfc_hci_disconnect_gate(struct nfc_hci_dev *hdev, u8 gate);
int nfc_hci_disconnect_all_gates(struct nfc_hci_dev *hdev);
int nfc_hci_get_param(struct nfc_hci_dev *hdev, u8 gate, u8 idx,
struct sk_buff **skb);
int nfc_hci_set_param(struct nfc_hci_dev *hdev, u8 gate, u8 idx,
const u8 *param, size_t param_len);
int nfc_hci_send_cmd(struct nfc_hci_dev *hdev, u8 gate, u8 cmd,
const u8 *param, size_t param_len, struct sk_buff **skb);
int nfc_hci_send_cmd_async(struct nfc_hci_dev *hdev, u8 gate, u8 cmd,
const u8 *param, size_t param_len,
data_exchange_cb_t cb, void *cb_context);
int nfc_hci_send_event(struct nfc_hci_dev *hdev, u8 gate, u8 event,
const u8 *param, size_t param_len);
int nfc_hci_target_discovered(struct nfc_hci_dev *hdev, u8 gate);
u32 nfc_hci_sak_to_protocol(u8 sak);
#endif /* __NET_HCI_H */
t::20170111-fw-fixes)$ sudo ./fw_fallback.sh
./fw_fallback.sh: timeout works
./fw_fallback.sh: firmware comparison works
./fw_fallback.sh: fallback mechanism works
[ this then sits here when it is trying the cancellation test ]
Kernel log:
test_firmware: loading 'nope-test-firmware.bin'
misc test_firmware: Direct firmware load for nope-test-firmware.bin failed with error -2
misc test_firmware: Falling back to user helper
BUG: unable to handle kernel NULL pointer dereference at 0000000000000038
IP: _request_firmware+0xa27/0xad0
PGD 0
Oops: 0000 [#1] SMP
Modules linked in: test_firmware(E) ... etc ...
CPU: 1 PID: 1396 Comm: fw_fallback.sh Tainted: G W E 4.10.0-rc3-next-20170111+ #30
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.10.1-0-g8891697-prebuilt.qemu-project.org 04/01/2014
task: ffff9740b27f4340 task.stack: ffffbb15c0bc8000
RIP: 0010:_request_firmware+0xa27/0xad0
RSP: 0018:ffffbb15c0bcbd10 EFLAGS: 00010246
RAX: 00000000fffffffe RBX: ffff9740afe5aa80 RCX: 0000000000000000
RDX: ffff9740b27f4340 RSI: 0000000000000283 RDI: 0000000000000000
RBP: ffffbb15c0bcbd90 R08: ffffbb15c0bcbcd8 R09: 0000000000000000
R10: 0000000894a0d4b1 R11: 000000000000008c R12: ffffffffc0312480
R13: 0000000000000005 R14: ffff9740b1c32400 R15: 00000000000003e8
FS: 00007f8604422700(0000) GS:ffff9740bfc80000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000038 CR3: 000000012164c000 CR4: 00000000000006e0
Call Trace:
request_firmware+0x37/0x50
trigger_request_store+0x79/0xd0 [test_firmware]
dev_attr_store+0x18/0x30
sysfs_kf_write+0x37/0x40
kernfs_fop_write+0x110/0x1a0
__vfs_write+0x37/0x160
? _cond_resched+0x1a/0x50
vfs_write+0xb5/0x1a0
SyS_write+0x55/0xc0
? trace_do_page_fault+0x37/0xd0
entry_SYSCALL_64_fastpath+0x1e/0xad
RIP: 0033:0x7f8603f49620
RSP: 002b:00007fff6287b788 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
RAX: ffffffffffffffda RBX: 000055c307b110a0 RCX: 00007f8603f49620
RDX: 0000000000000016 RSI: 000055c3084d8a90 RDI: 0000000000000001
RBP: 0000000000000016 R08: 000000000000c0ff R09: 000055c3084d6336
R10: 000055c307b108b0 R11: 0000000000000246 R12: 000055c307b13c80
R13: 000055c3084d6320 R14: 0000000000000000 R15: 00007fff6287b950
Code: 9f 64 84 e8 9c 61 fe ff b8 f4 ff ff ff e9 6b f9 ff
ff 48 c7 c7 40 6b 8d 84 89 45 a8 e8 43 84 18 00 49 8b be 00 03 00 00 8b
45 a8 <83> 7f 38 02 74 08 e8 6e ec ff ff 8b 45 a8 49 c7 86 00 03 00 00
RIP: _request_firmware+0xa27/0xad0 RSP: ffffbb15c0bcbd10
CR2: 0000000000000038
---[ end trace 6d94ac339c133e6f ]---
Fixes: 5d47ec02c37e ("firmware: Correct handling of fw_state_wait() return value")
Reported-and-Tested-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reported-and-Tested-by: Patrick Bruenn <p.bruenn@beckhoff.com>
Reported-by: Chris Wilson <chris@chris-wilson.co.uk>
CC: <stable@vger.kernel.org> [3.10+]
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>