diff options
Diffstat (limited to 'drivers/nfc/s3fwrn5/core.c')
-rw-r--r-- | drivers/nfc/s3fwrn5/core.c | 50 |
1 files changed, 34 insertions, 16 deletions
diff --git a/drivers/nfc/s3fwrn5/core.c b/drivers/nfc/s3fwrn5/core.c index 91d4d5b28a7d..0270e05b68df 100644 --- a/drivers/nfc/s3fwrn5/core.c +++ b/drivers/nfc/s3fwrn5/core.c @@ -20,13 +20,26 @@ NFC_PROTO_ISO14443_B_MASK | \ NFC_PROTO_ISO15693_MASK) +static int s3fwrn5_firmware_init(struct s3fwrn5_info *info) +{ + struct s3fwrn5_fw_info *fw_info = &info->fw_info; + int ret; + + s3fwrn5_fw_init(fw_info, "sec_s3fwrn5_firmware.bin"); + + /* Get firmware data */ + ret = s3fwrn5_fw_request_firmware(fw_info); + if (ret < 0) + dev_err(&fw_info->ndev->nfc_dev->dev, + "Failed to get fw file, ret=%02x\n", ret); + return ret; +} + static int s3fwrn5_firmware_update(struct s3fwrn5_info *info) { bool need_update; int ret; - s3fwrn5_fw_init(&info->fw_info, "sec_s3fwrn5_firmware.bin"); - /* Update firmware */ s3fwrn5_set_wake(info, false); @@ -97,11 +110,15 @@ static int s3fwrn5_nci_send(struct nci_dev *ndev, struct sk_buff *skb) } ret = s3fwrn5_write(info, skb); - if (ret < 0) + if (ret < 0) { kfree_skb(skb); + mutex_unlock(&info->mutex); + return ret; + } + consume_skb(skb); mutex_unlock(&info->mutex); - return ret; + return 0; } static int s3fwrn5_nci_post_setup(struct nci_dev *ndev) @@ -109,9 +126,14 @@ static int s3fwrn5_nci_post_setup(struct nci_dev *ndev) struct s3fwrn5_info *info = nci_get_drvdata(ndev); int ret; + if (s3fwrn5_firmware_init(info)) { + //skip bootloader mode + return 0; + } + ret = s3fwrn5_firmware_update(info); if (ret < 0) - goto out; + return ret; /* NCI core reset */ @@ -120,23 +142,22 @@ static int s3fwrn5_nci_post_setup(struct nci_dev *ndev) ret = nci_core_reset(info->ndev); if (ret < 0) - goto out; - - ret = nci_core_init(info->ndev); + return ret; -out: - return ret; + return nci_core_init(info->ndev); } -static struct nci_ops s3fwrn5_nci_ops = { +static const struct nci_ops s3fwrn5_nci_ops = { .open = s3fwrn5_nci_open, .close = s3fwrn5_nci_close, .send = s3fwrn5_nci_send, .post_setup = s3fwrn5_nci_post_setup, + .prop_ops = s3fwrn5_nci_prop_ops, + .n_prop_ops = ARRAY_SIZE(s3fwrn5_nci_prop_ops), }; int s3fwrn5_probe(struct nci_dev **ndev, void *phy_id, struct device *pdev, - const struct s3fwrn5_phy_ops *phy_ops, unsigned int max_payload) + const struct s3fwrn5_phy_ops *phy_ops) { struct s3fwrn5_info *info; int ret; @@ -148,14 +169,10 @@ int s3fwrn5_probe(struct nci_dev **ndev, void *phy_id, struct device *pdev, info->phy_id = phy_id; info->pdev = pdev; info->phy_ops = phy_ops; - info->max_payload = max_payload; mutex_init(&info->mutex); s3fwrn5_set_mode(info, S3FWRN5_MODE_COLD); - s3fwrn5_nci_get_prop_ops(&s3fwrn5_nci_ops.prop_ops, - &s3fwrn5_nci_ops.n_prop_ops); - info->ndev = nci_allocate_device(&s3fwrn5_nci_ops, S3FWRN5_NFC_PROTOCOLS, 0, 0); if (!info->ndev) @@ -198,6 +215,7 @@ int s3fwrn5_recv_frame(struct nci_dev *ndev, struct sk_buff *skb, case S3FWRN5_MODE_FW: return s3fwrn5_fw_recv_frame(ndev, skb); default: + kfree_skb(skb); return -ENODEV; } } |