aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/nfc
diff options
context:
space:
mode:
authorWaldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com>2012-12-10 08:42:46 -0500
committerSamuel Ortiz <sameo@linux.intel.com>2013-01-09 18:51:36 -0500
commitb1e666f503b5479efe9adf79fb46f09fe4f04af5 (patch)
treefa92b74d9d48a011277205e81e533e1d6a9cd585 /drivers/nfc
parent13003649b1ebb4ea51341a9405a2ec5b10cf4f7e (diff)
NFC: pn533: Del frame logic from Data Exchange cmd
Remove frame logic from transceive cb using new iface for async send. For pn533_wq_mi_recv() use pn533_send_cmd_direct_async which sends the cmd directly to the hardware, skipping cmd queue. Signed-off-by: Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/nfc')
-rw-r--r--drivers/nfc/pn533.c309
1 files changed, 141 insertions, 168 deletions
diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index aa7803f16773..91e1594dfd13 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -360,6 +360,7 @@ struct pn533 {
360 360
361 pn533_cmd_complete_t cmd_complete; 361 pn533_cmd_complete_t cmd_complete;
362 void *cmd_complete_arg; 362 void *cmd_complete_arg;
363 void *cmd_complete_mi_arg;
363 struct mutex cmd_lock; 364 struct mutex cmd_lock;
364 u8 cmd; 365 u8 cmd;
365 366
@@ -848,6 +849,57 @@ static int pn533_send_cmd_async(struct pn533 *dev, u8 cmd_code,
848 return rc; 849 return rc;
849} 850}
850 851
852/*
853 * pn533_send_cmd_direct_async
854 *
855 * The function sends a piority cmd directly to the chip omiting the cmd
856 * queue. It's intended to be used by chaining mechanism of received responses
857 * where the host has to request every single chunk of data before scheduling
858 * next cmd from the queue.
859 */
860static int pn533_send_cmd_direct_async(struct pn533 *dev, u8 cmd_code,
861 struct sk_buff *req,
862 pn533_send_async_complete_t complete_cb,
863 void *complete_cb_context)
864{
865 struct pn533_send_async_complete_arg *arg;
866 struct sk_buff *resp;
867 int rc;
868 int resp_len = PN533_FRAME_HEADER_LEN +
869 PN533_FRAME_MAX_PAYLOAD_LEN +
870 PN533_FRAME_TAIL_LEN;
871
872 nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
873
874 resp = alloc_skb(resp_len, GFP_KERNEL);
875 if (!resp)
876 return -ENOMEM;
877
878 arg = kzalloc(sizeof(arg), GFP_KERNEL);
879 if (!arg) {
880 dev_kfree_skb(resp);
881 return -ENOMEM;
882 }
883
884 arg->complete_cb = complete_cb;
885 arg->complete_cb_context = complete_cb_context;
886 arg->resp = resp;
887 arg->req = req;
888
889 pn533_build_cmd_frame(cmd_code, req);
890
891 rc = __pn533_send_cmd_frame_async(dev, (struct pn533_frame *)req->data,
892 (struct pn533_frame *)resp->data,
893 resp_len, pn533_send_async_complete,
894 arg);
895 if (rc < 0) {
896 dev_kfree_skb(resp);
897 kfree(arg);
898 }
899
900 return rc;
901}
902
851static void pn533_wq_cmd(struct work_struct *work) 903static void pn533_wq_cmd(struct work_struct *work)
852{ 904{
853 struct pn533 *dev = container_of(work, struct pn533, cmd_work); 905 struct pn533 *dev = container_of(work, struct pn533, cmd_work);
@@ -2024,69 +2076,7 @@ static int pn533_dep_link_down(struct nfc_dev *nfc_dev)
2024 return 0; 2076 return 0;
2025} 2077}
2026 2078
2027static int pn533_build_tx_frame(struct pn533 *dev, struct sk_buff *skb,
2028 bool target)
2029{
2030 int payload_len = skb->len;
2031 struct pn533_frame *out_frame;
2032 u8 tg;
2033
2034 nfc_dev_dbg(&dev->interface->dev, "%s - Sending %d bytes", __func__,
2035 payload_len);
2036
2037 if (payload_len > PN533_CMD_DATAEXCH_DATA_MAXLEN) {
2038 /* TODO: Implement support to multi-part data exchange */
2039 nfc_dev_err(&dev->interface->dev, "Data length greater than the"
2040 " max allowed: %d",
2041 PN533_CMD_DATAEXCH_DATA_MAXLEN);
2042 return -ENOSYS;
2043 }
2044
2045 skb_push(skb, PN533_FRAME_HEADER_LEN);
2046
2047 if (target == true) {
2048 switch (dev->device_type) {
2049 case PN533_DEVICE_PASORI:
2050 if (dev->tgt_active_prot == NFC_PROTO_FELICA) {
2051 out_frame = (struct pn533_frame *) skb->data;
2052 pn533_tx_frame_init(out_frame,
2053 PN533_CMD_IN_COMM_THRU);
2054
2055 break;
2056 }
2057
2058 default:
2059 skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN);
2060 out_frame = (struct pn533_frame *) skb->data;
2061 pn533_tx_frame_init(out_frame,
2062 PN533_CMD_IN_DATA_EXCHANGE);
2063 tg = 1;
2064 memcpy(PN533_FRAME_CMD_PARAMS_PTR(out_frame),
2065 &tg, sizeof(u8));
2066 out_frame->datalen += sizeof(u8);
2067
2068 break;
2069 }
2070
2071 } else {
2072 skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN - 1);
2073 out_frame = (struct pn533_frame *) skb->data;
2074 pn533_tx_frame_init(out_frame, PN533_CMD_TG_SET_DATA);
2075 }
2076
2077
2078 /* The data is already in the out_frame, just update the datalen */
2079 out_frame->datalen += payload_len;
2080
2081 pn533_tx_frame_finish(out_frame);
2082 skb_put(skb, PN533_FRAME_TAIL_LEN);
2083
2084 return 0;
2085}
2086
2087struct pn533_data_exchange_arg { 2079struct pn533_data_exchange_arg {
2088 struct sk_buff *skb_resp;
2089 struct sk_buff *skb_out;
2090 data_exchange_cb_t cb; 2080 data_exchange_cb_t cb;
2091 void *cb_context; 2081 void *cb_context;
2092}; 2082};
@@ -2130,47 +2120,44 @@ out:
2130} 2120}
2131 2121
2132static int pn533_data_exchange_complete(struct pn533 *dev, void *_arg, 2122static int pn533_data_exchange_complete(struct pn533 *dev, void *_arg,
2133 u8 *params, int params_len) 2123 struct sk_buff *resp)
2134{ 2124{
2135 struct pn533_data_exchange_arg *arg = _arg; 2125 struct pn533_data_exchange_arg *arg = _arg;
2136 struct sk_buff *skb = NULL, *skb_resp = arg->skb_resp; 2126 struct sk_buff *skb;
2137 struct pn533_frame *in_frame = (struct pn533_frame *) skb_resp->data; 2127 int rc = 0;
2138 int err = 0; 2128 u8 status, ret, mi;
2139 u8 status;
2140 u8 cmd_ret;
2141 2129
2142 nfc_dev_dbg(&dev->interface->dev, "%s", __func__); 2130 nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
2143 2131
2144 dev_kfree_skb(arg->skb_out); 2132 if (IS_ERR(resp)) {
2145 2133 rc = PTR_ERR(resp);
2146 if (params_len < 0) { /* error */ 2134 goto _error;
2147 err = params_len;
2148 goto error;
2149 } 2135 }
2150 2136
2151 status = params[0]; 2137 status = resp->data[0];
2138 ret = status & PN533_CMD_RET_MASK;
2139 mi = status & PN533_CMD_MI_MASK;
2140
2141 skb_pull(resp, sizeof(status));
2152 2142
2153 cmd_ret = status & PN533_CMD_RET_MASK; 2143 if (ret != PN533_CMD_RET_SUCCESS) {
2154 if (cmd_ret != PN533_CMD_RET_SUCCESS) { 2144 nfc_dev_err(&dev->interface->dev,
2155 nfc_dev_err(&dev->interface->dev, "PN533 reported error %d when" 2145 "PN533 reported error %d when exchanging data",
2156 " exchanging data", cmd_ret); 2146 ret);
2157 err = -EIO; 2147 rc = -EIO;
2158 goto error; 2148 goto error;
2159 } 2149 }
2160 2150
2161 skb_put(skb_resp, PN533_FRAME_SIZE(in_frame)); 2151 skb_queue_tail(&dev->resp_q, resp);
2162 skb_pull(skb_resp, PN533_FRAME_HEADER_LEN);
2163 skb_pull(skb_resp, PN533_CMD_DATAEXCH_HEAD_LEN);
2164 skb_trim(skb_resp, skb_resp->len - PN533_FRAME_TAIL_LEN);
2165 skb_queue_tail(&dev->resp_q, skb_resp);
2166 2152
2167 if (status & PN533_CMD_MI_MASK) { 2153 if (mi) {
2154 dev->cmd_complete_mi_arg = arg;
2168 queue_work(dev->wq, &dev->mi_work); 2155 queue_work(dev->wq, &dev->mi_work);
2169 return -EINPROGRESS; 2156 return -EINPROGRESS;
2170 } 2157 }
2171 2158
2172 skb = pn533_build_response(dev); 2159 skb = pn533_build_response(dev);
2173 if (skb == NULL) 2160 if (!skb)
2174 goto error; 2161 goto error;
2175 2162
2176 arg->cb(arg->cb_context, skb, 0); 2163 arg->cb(arg->cb_context, skb, 0);
@@ -2178,11 +2165,12 @@ static int pn533_data_exchange_complete(struct pn533 *dev, void *_arg,
2178 return 0; 2165 return 0;
2179 2166
2180error: 2167error:
2168 dev_kfree_skb(resp);
2169_error:
2181 skb_queue_purge(&dev->resp_q); 2170 skb_queue_purge(&dev->resp_q);
2182 dev_kfree_skb(skb_resp); 2171 arg->cb(arg->cb_context, NULL, rc);
2183 arg->cb(arg->cb_context, NULL, err);
2184 kfree(arg); 2172 kfree(arg);
2185 return 0; 2173 return rc;
2186} 2174}
2187 2175
2188static int pn533_transceive(struct nfc_dev *nfc_dev, 2176static int pn533_transceive(struct nfc_dev *nfc_dev,
@@ -2190,14 +2178,20 @@ static int pn533_transceive(struct nfc_dev *nfc_dev,
2190 data_exchange_cb_t cb, void *cb_context) 2178 data_exchange_cb_t cb, void *cb_context)
2191{ 2179{
2192 struct pn533 *dev = nfc_get_drvdata(nfc_dev); 2180 struct pn533 *dev = nfc_get_drvdata(nfc_dev);
2193 struct pn533_frame *out_frame, *in_frame; 2181 struct pn533_data_exchange_arg *arg = NULL;
2194 struct pn533_data_exchange_arg *arg;
2195 struct sk_buff *skb_resp;
2196 int skb_resp_len;
2197 int rc; 2182 int rc;
2198 2183
2199 nfc_dev_dbg(&dev->interface->dev, "%s", __func__); 2184 nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
2200 2185
2186 if (skb->len > PN533_CMD_DATAEXCH_DATA_MAXLEN) {
2187 /* TODO: Implement support to multi-part data exchange */
2188 nfc_dev_err(&dev->interface->dev,
2189 "Data length greater than the max allowed: %d",
2190 PN533_CMD_DATAEXCH_DATA_MAXLEN);
2191 rc = -ENOSYS;
2192 goto error;
2193 }
2194
2201 if (!dev->tgt_active_prot) { 2195 if (!dev->tgt_active_prot) {
2202 nfc_dev_err(&dev->interface->dev, "Cannot exchange data if" 2196 nfc_dev_err(&dev->interface->dev, "Cannot exchange data if"
2203 " there is no active target"); 2197 " there is no active target");
@@ -2205,51 +2199,43 @@ static int pn533_transceive(struct nfc_dev *nfc_dev,
2205 goto error; 2199 goto error;
2206 } 2200 }
2207 2201
2208 rc = pn533_build_tx_frame(dev, skb, true); 2202 arg = kmalloc(sizeof(*arg), GFP_KERNEL);
2209 if (rc)
2210 goto error;
2211
2212 skb_resp_len = PN533_FRAME_HEADER_LEN +
2213 PN533_CMD_DATAEXCH_HEAD_LEN +
2214 PN533_CMD_DATAEXCH_DATA_MAXLEN +
2215 PN533_FRAME_TAIL_LEN;
2216
2217 skb_resp = nfc_alloc_recv_skb(skb_resp_len, GFP_KERNEL);
2218 if (!skb_resp) {
2219 rc = -ENOMEM;
2220 goto error;
2221 }
2222
2223 in_frame = (struct pn533_frame *) skb_resp->data;
2224 out_frame = (struct pn533_frame *) skb->data;
2225
2226 arg = kmalloc(sizeof(struct pn533_data_exchange_arg), GFP_KERNEL);
2227 if (!arg) { 2203 if (!arg) {
2228 rc = -ENOMEM; 2204 rc = -ENOMEM;
2229 goto free_skb_resp; 2205 goto error;
2230 } 2206 }
2231 2207
2232 arg->skb_resp = skb_resp;
2233 arg->skb_out = skb;
2234 arg->cb = cb; 2208 arg->cb = cb;
2235 arg->cb_context = cb_context; 2209 arg->cb_context = cb_context;
2236 2210
2237 rc = pn533_send_cmd_frame_async(dev, out_frame, in_frame, skb_resp_len, 2211 switch (dev->device_type) {
2238 pn533_data_exchange_complete, arg); 2212 case PN533_DEVICE_PASORI:
2239 if (rc) { 2213 if (dev->tgt_active_prot == NFC_PROTO_FELICA) {
2240 nfc_dev_err(&dev->interface->dev, "Error %d when trying to" 2214 rc = pn533_send_data_async(dev, PN533_CMD_IN_COMM_THRU,
2241 " perform data_exchange", rc); 2215 skb,
2242 goto free_arg; 2216 pn533_data_exchange_complete,
2217 arg);
2218
2219 break;
2220 }
2221 default:
2222 *skb_push(skb, sizeof(u8)) = 1; /*TG*/
2223
2224 rc = pn533_send_data_async(dev, PN533_CMD_IN_DATA_EXCHANGE,
2225 skb, pn533_data_exchange_complete,
2226 arg);
2227
2228 break;
2243 } 2229 }
2244 2230
2231 if (rc < 0) /* rc from send_async */
2232 goto error;
2233
2245 return 0; 2234 return 0;
2246 2235
2247free_arg:
2248 kfree(arg);
2249free_skb_resp:
2250 kfree_skb(skb_resp);
2251error: 2236error:
2252 kfree_skb(skb); 2237 kfree(arg);
2238 dev_kfree_skb(skb);
2253 return rc; 2239 return rc;
2254} 2240}
2255 2241
@@ -2305,63 +2291,50 @@ static int pn533_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb)
2305static void pn533_wq_mi_recv(struct work_struct *work) 2291static void pn533_wq_mi_recv(struct work_struct *work)
2306{ 2292{
2307 struct pn533 *dev = container_of(work, struct pn533, mi_work); 2293 struct pn533 *dev = container_of(work, struct pn533, mi_work);
2308 struct sk_buff *skb_cmd; 2294
2309 struct pn533_data_exchange_arg *arg = dev->cmd_complete_arg; 2295 struct sk_buff *skb;
2310 struct pn533_frame *out_frame, *in_frame;
2311 struct sk_buff *skb_resp;
2312 int skb_resp_len;
2313 int rc; 2296 int rc;
2314 2297
2315 nfc_dev_dbg(&dev->interface->dev, "%s", __func__); 2298 nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
2316 2299
2317 /* This is a zero payload size skb */ 2300 skb = pn533_alloc_skb(PN533_CMD_DATAEXCH_HEAD_LEN);
2318 skb_cmd = pn533_alloc_skb(PN533_CMD_DATAEXCH_HEAD_LEN); 2301 if (!skb)
2319 if (skb_cmd == NULL) 2302 goto error;
2320 goto error_cmd;
2321 2303
2322 skb_reserve(skb_cmd, PN533_CMD_DATAEXCH_HEAD_LEN); 2304 switch (dev->device_type) {
2305 case PN533_DEVICE_PASORI:
2306 if (dev->tgt_active_prot == NFC_PROTO_FELICA) {
2307 rc = pn533_send_cmd_direct_async(dev,
2308 PN533_CMD_IN_COMM_THRU,
2309 skb,
2310 pn533_data_exchange_complete,
2311 dev->cmd_complete_mi_arg);
2323 2312
2324 rc = pn533_build_tx_frame(dev, skb_cmd, true); 2313 break;
2325 if (rc) 2314 }
2326 goto error_frame; 2315 default:
2316 *skb_put(skb, sizeof(u8)) = 1; /*TG*/
2327 2317
2328 skb_resp_len = PN533_FRAME_HEADER_LEN + 2318 rc = pn533_send_cmd_direct_async(dev,
2329 PN533_CMD_DATAEXCH_HEAD_LEN + 2319 PN533_CMD_IN_DATA_EXCHANGE,
2330 PN533_CMD_DATAEXCH_DATA_MAXLEN + 2320 skb,
2331 PN533_FRAME_TAIL_LEN; 2321 pn533_data_exchange_complete,
2322 dev->cmd_complete_mi_arg);
2332 2323
2333 skb_resp = alloc_skb(skb_resp_len, GFP_KERNEL); 2324 break;
2334 if (!skb_resp) {
2335 rc = -ENOMEM;
2336 goto error_frame;
2337 } 2325 }
2338 2326
2339 in_frame = (struct pn533_frame *) skb_resp->data; 2327 if (rc == 0) /* success */
2340 out_frame = (struct pn533_frame *) skb_cmd->data;
2341
2342 arg->skb_resp = skb_resp;
2343 arg->skb_out = skb_cmd;
2344
2345 rc = __pn533_send_cmd_frame_async(dev, out_frame, in_frame,
2346 skb_resp_len,
2347 pn533_data_exchange_complete,
2348 dev->cmd_complete_arg);
2349 if (!rc)
2350 return; 2328 return;
2351 2329
2352 nfc_dev_err(&dev->interface->dev, "Error %d when trying to" 2330 nfc_dev_err(&dev->interface->dev,
2353 " perform data_exchange", rc); 2331 "Error %d when trying to perform data_exchange", rc);
2354
2355 kfree_skb(skb_resp);
2356 2332
2357error_frame: 2333 dev_kfree_skb(skb);
2358 kfree_skb(skb_cmd); 2334 kfree(dev->cmd_complete_arg);
2359 2335
2360error_cmd: 2336error:
2361 pn533_send_ack(dev, GFP_KERNEL); 2337 pn533_send_ack(dev, GFP_KERNEL);
2362
2363 kfree(arg);
2364
2365 queue_work(dev->wq, &dev->cmd_work); 2338 queue_work(dev->wq, &dev->cmd_work);
2366} 2339}
2367 2340