ndlc.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Low Level Transport (NDLC) Driver for STMicroelectronics NFC Chip
  4. *
  5. * Copyright (C) 2014-2015 STMicroelectronics SAS. All rights reserved.
  6. */
  7. #include <linux/sched.h>
  8. #include <net/nfc/nci_core.h>
  9. #include "st-nci.h"
  10. #define NDLC_TIMER_T1 100
  11. #define NDLC_TIMER_T1_WAIT 400
  12. #define NDLC_TIMER_T2 1200
  13. #define PCB_TYPE_DATAFRAME 0x80
  14. #define PCB_TYPE_SUPERVISOR 0xc0
  15. #define PCB_TYPE_MASK PCB_TYPE_SUPERVISOR
  16. #define PCB_SYNC_ACK 0x20
  17. #define PCB_SYNC_NACK 0x10
  18. #define PCB_SYNC_WAIT 0x30
  19. #define PCB_SYNC_NOINFO 0x00
  20. #define PCB_SYNC_MASK PCB_SYNC_WAIT
  21. #define PCB_DATAFRAME_RETRANSMIT_YES 0x00
  22. #define PCB_DATAFRAME_RETRANSMIT_NO 0x04
  23. #define PCB_DATAFRAME_RETRANSMIT_MASK PCB_DATAFRAME_RETRANSMIT_NO
  24. #define PCB_SUPERVISOR_RETRANSMIT_YES 0x00
  25. #define PCB_SUPERVISOR_RETRANSMIT_NO 0x02
  26. #define PCB_SUPERVISOR_RETRANSMIT_MASK PCB_SUPERVISOR_RETRANSMIT_NO
  27. #define PCB_FRAME_CRC_INFO_PRESENT 0x08
  28. #define PCB_FRAME_CRC_INFO_NOTPRESENT 0x00
  29. #define PCB_FRAME_CRC_INFO_MASK PCB_FRAME_CRC_INFO_PRESENT
  30. #define NDLC_DUMP_SKB(info, skb) \
  31. do { \
  32. pr_debug("%s:\n", info); \
  33. print_hex_dump(KERN_DEBUG, "ndlc: ", DUMP_PREFIX_OFFSET, \
  34. 16, 1, skb->data, skb->len, 0); \
  35. } while (0)
  36. int ndlc_open(struct llt_ndlc *ndlc)
  37. {
  38. /* toggle reset pin */
  39. ndlc->ops->enable(ndlc->phy_id);
  40. ndlc->powered = 1;
  41. return 0;
  42. }
  43. EXPORT_SYMBOL(ndlc_open);
  44. void ndlc_close(struct llt_ndlc *ndlc)
  45. {
  46. struct nci_mode_set_cmd cmd;
  47. cmd.cmd_type = ST_NCI_SET_NFC_MODE;
  48. cmd.mode = 0;
  49. /* toggle reset pin */
  50. ndlc->ops->enable(ndlc->phy_id);
  51. nci_prop_cmd(ndlc->ndev, ST_NCI_CORE_PROP,
  52. sizeof(struct nci_mode_set_cmd), (__u8 *)&cmd);
  53. ndlc->powered = 0;
  54. ndlc->ops->disable(ndlc->phy_id);
  55. }
  56. EXPORT_SYMBOL(ndlc_close);
  57. int ndlc_send(struct llt_ndlc *ndlc, struct sk_buff *skb)
  58. {
  59. /* add ndlc header */
  60. u8 pcb = PCB_TYPE_DATAFRAME | PCB_DATAFRAME_RETRANSMIT_NO |
  61. PCB_FRAME_CRC_INFO_NOTPRESENT;
  62. *(u8 *)skb_push(skb, 1) = pcb;
  63. skb_queue_tail(&ndlc->send_q, skb);
  64. schedule_work(&ndlc->sm_work);
  65. return 0;
  66. }
  67. EXPORT_SYMBOL(ndlc_send);
  68. static void llt_ndlc_send_queue(struct llt_ndlc *ndlc)
  69. {
  70. struct sk_buff *skb;
  71. int r;
  72. unsigned long time_sent;
  73. if (ndlc->send_q.qlen)
  74. pr_debug("sendQlen=%d unackQlen=%d\n",
  75. ndlc->send_q.qlen, ndlc->ack_pending_q.qlen);
  76. while (ndlc->send_q.qlen) {
  77. skb = skb_dequeue(&ndlc->send_q);
  78. NDLC_DUMP_SKB("ndlc frame written", skb);
  79. r = ndlc->ops->write(ndlc->phy_id, skb);
  80. if (r < 0) {
  81. ndlc->hard_fault = r;
  82. break;
  83. }
  84. time_sent = jiffies;
  85. *(unsigned long *)skb->cb = time_sent;
  86. skb_queue_tail(&ndlc->ack_pending_q, skb);
  87. /* start timer t1 for ndlc aknowledge */
  88. ndlc->t1_active = true;
  89. mod_timer(&ndlc->t1_timer, time_sent +
  90. msecs_to_jiffies(NDLC_TIMER_T1));
  91. /* start timer t2 for chip availability */
  92. ndlc->t2_active = true;
  93. mod_timer(&ndlc->t2_timer, time_sent +
  94. msecs_to_jiffies(NDLC_TIMER_T2));
  95. }
  96. }
  97. static void llt_ndlc_requeue_data_pending(struct llt_ndlc *ndlc)
  98. {
  99. struct sk_buff *skb;
  100. u8 pcb;
  101. while ((skb = skb_dequeue_tail(&ndlc->ack_pending_q))) {
  102. pcb = skb->data[0];
  103. switch (pcb & PCB_TYPE_MASK) {
  104. case PCB_TYPE_SUPERVISOR:
  105. skb->data[0] = (pcb & ~PCB_SUPERVISOR_RETRANSMIT_MASK) |
  106. PCB_SUPERVISOR_RETRANSMIT_YES;
  107. break;
  108. case PCB_TYPE_DATAFRAME:
  109. skb->data[0] = (pcb & ~PCB_DATAFRAME_RETRANSMIT_MASK) |
  110. PCB_DATAFRAME_RETRANSMIT_YES;
  111. break;
  112. default:
  113. pr_err("UNKNOWN Packet Control Byte=%d\n", pcb);
  114. kfree_skb(skb);
  115. continue;
  116. }
  117. skb_queue_head(&ndlc->send_q, skb);
  118. }
  119. }
  120. static void llt_ndlc_rcv_queue(struct llt_ndlc *ndlc)
  121. {
  122. struct sk_buff *skb;
  123. u8 pcb;
  124. unsigned long time_sent;
  125. if (ndlc->rcv_q.qlen)
  126. pr_debug("rcvQlen=%d\n", ndlc->rcv_q.qlen);
  127. while ((skb = skb_dequeue(&ndlc->rcv_q)) != NULL) {
  128. pcb = skb->data[0];
  129. skb_pull(skb, 1);
  130. if ((pcb & PCB_TYPE_MASK) == PCB_TYPE_SUPERVISOR) {
  131. switch (pcb & PCB_SYNC_MASK) {
  132. case PCB_SYNC_ACK:
  133. skb = skb_dequeue(&ndlc->ack_pending_q);
  134. kfree_skb(skb);
  135. del_timer_sync(&ndlc->t1_timer);
  136. del_timer_sync(&ndlc->t2_timer);
  137. ndlc->t2_active = false;
  138. ndlc->t1_active = false;
  139. break;
  140. case PCB_SYNC_NACK:
  141. llt_ndlc_requeue_data_pending(ndlc);
  142. llt_ndlc_send_queue(ndlc);
  143. /* start timer t1 for ndlc aknowledge */
  144. time_sent = jiffies;
  145. ndlc->t1_active = true;
  146. mod_timer(&ndlc->t1_timer, time_sent +
  147. msecs_to_jiffies(NDLC_TIMER_T1));
  148. break;
  149. case PCB_SYNC_WAIT:
  150. time_sent = jiffies;
  151. ndlc->t1_active = true;
  152. mod_timer(&ndlc->t1_timer, time_sent +
  153. msecs_to_jiffies(NDLC_TIMER_T1_WAIT));
  154. break;
  155. default:
  156. kfree_skb(skb);
  157. break;
  158. }
  159. } else if ((pcb & PCB_TYPE_MASK) == PCB_TYPE_DATAFRAME) {
  160. nci_recv_frame(ndlc->ndev, skb);
  161. } else {
  162. kfree_skb(skb);
  163. }
  164. }
  165. }
  166. static void llt_ndlc_sm_work(struct work_struct *work)
  167. {
  168. struct llt_ndlc *ndlc = container_of(work, struct llt_ndlc, sm_work);
  169. llt_ndlc_send_queue(ndlc);
  170. llt_ndlc_rcv_queue(ndlc);
  171. if (ndlc->t1_active && timer_pending(&ndlc->t1_timer) == 0) {
  172. pr_debug
  173. ("Handle T1(recv SUPERVISOR) elapsed (T1 now inactive)\n");
  174. ndlc->t1_active = false;
  175. llt_ndlc_requeue_data_pending(ndlc);
  176. llt_ndlc_send_queue(ndlc);
  177. }
  178. if (ndlc->t2_active && timer_pending(&ndlc->t2_timer) == 0) {
  179. pr_debug("Handle T2(recv DATA) elapsed (T2 now inactive)\n");
  180. ndlc->t2_active = false;
  181. ndlc->t1_active = false;
  182. del_timer_sync(&ndlc->t1_timer);
  183. del_timer_sync(&ndlc->t2_timer);
  184. ndlc_close(ndlc);
  185. ndlc->hard_fault = -EREMOTEIO;
  186. }
  187. }
  188. void ndlc_recv(struct llt_ndlc *ndlc, struct sk_buff *skb)
  189. {
  190. if (skb == NULL) {
  191. pr_err("NULL Frame -> link is dead\n");
  192. ndlc->hard_fault = -EREMOTEIO;
  193. ndlc_close(ndlc);
  194. } else {
  195. NDLC_DUMP_SKB("incoming frame", skb);
  196. skb_queue_tail(&ndlc->rcv_q, skb);
  197. }
  198. schedule_work(&ndlc->sm_work);
  199. }
  200. EXPORT_SYMBOL(ndlc_recv);
  201. static void ndlc_t1_timeout(struct timer_list *t)
  202. {
  203. struct llt_ndlc *ndlc = from_timer(ndlc, t, t1_timer);
  204. schedule_work(&ndlc->sm_work);
  205. }
  206. static void ndlc_t2_timeout(struct timer_list *t)
  207. {
  208. struct llt_ndlc *ndlc = from_timer(ndlc, t, t2_timer);
  209. schedule_work(&ndlc->sm_work);
  210. }
  211. int ndlc_probe(void *phy_id, const struct nfc_phy_ops *phy_ops,
  212. struct device *dev, int phy_headroom, int phy_tailroom,
  213. struct llt_ndlc **ndlc_id, struct st_nci_se_status *se_status)
  214. {
  215. struct llt_ndlc *ndlc;
  216. ndlc = devm_kzalloc(dev, sizeof(struct llt_ndlc), GFP_KERNEL);
  217. if (!ndlc)
  218. return -ENOMEM;
  219. ndlc->ops = phy_ops;
  220. ndlc->phy_id = phy_id;
  221. ndlc->dev = dev;
  222. ndlc->powered = 0;
  223. *ndlc_id = ndlc;
  224. /* initialize timers */
  225. timer_setup(&ndlc->t1_timer, ndlc_t1_timeout, 0);
  226. timer_setup(&ndlc->t2_timer, ndlc_t2_timeout, 0);
  227. skb_queue_head_init(&ndlc->rcv_q);
  228. skb_queue_head_init(&ndlc->send_q);
  229. skb_queue_head_init(&ndlc->ack_pending_q);
  230. INIT_WORK(&ndlc->sm_work, llt_ndlc_sm_work);
  231. return st_nci_probe(ndlc, phy_headroom, phy_tailroom, se_status);
  232. }
  233. EXPORT_SYMBOL(ndlc_probe);
  234. void ndlc_remove(struct llt_ndlc *ndlc)
  235. {
  236. /* cancel timers */
  237. del_timer_sync(&ndlc->t1_timer);
  238. del_timer_sync(&ndlc->t2_timer);
  239. ndlc->t2_active = false;
  240. ndlc->t1_active = false;
  241. /* cancel work */
  242. cancel_work_sync(&ndlc->sm_work);
  243. st_nci_remove(ndlc->ndev);
  244. skb_queue_purge(&ndlc->rcv_q);
  245. skb_queue_purge(&ndlc->send_q);
  246. }
  247. EXPORT_SYMBOL(ndlc_remove);