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