NFC: Reserve tx head and tail room
authorSamuel Ortiz <sameo@linux.intel.com>
Fri, 19 Aug 2011 13:47:11 +0000 (15:47 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 24 Aug 2011 18:41:44 +0000 (14:41 -0400)
We can have the NFC core layer allocating the tx head and tail
room for the drivers and avoid 1 or more SKBs copy on write on
the Tx path.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/nfc/pn533.c
include/linux/nfc.h
include/net/nfc.h
net/nfc/core.c
net/nfc/rawsock.c

index c77e054..f81a93e 100644 (file)
@@ -1246,7 +1246,6 @@ static int pn533_data_exchange_tx_frame(struct pn533 *dev, struct sk_buff *skb)
 {
        int payload_len = skb->len;
        struct pn533_frame *out_frame;
-       struct sk_buff *discarded;
        u8 tg;
 
        nfc_dev_dbg(&dev->interface->dev, "%s - Sending %d bytes", __func__,
@@ -1260,18 +1259,6 @@ static int pn533_data_exchange_tx_frame(struct pn533 *dev, struct sk_buff *skb)
                return -ENOSYS;
        }
 
-       /* Reserving header space */
-       if (skb_cow_head(skb, PN533_CMD_DATAEXCH_HEAD_LEN)) {
-               nfc_dev_err(&dev->interface->dev, "Error to add header data");
-               return -ENOMEM;
-       }
-
-       /* Reserving tail space, see pn533_tx_frame_finish */
-       if (skb_cow_data(skb, PN533_FRAME_TAIL_SIZE, &discarded) < 0) {
-               nfc_dev_err(&dev->interface->dev, "Error to add tail data");
-               return -ENOMEM;
-       }
-
        skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN);
        out_frame = (struct pn533_frame *) skb->data;
 
@@ -1536,7 +1523,9 @@ static int pn533_probe(struct usb_interface *interface,
                        | NFC_PROTO_ISO14443_MASK
                        | NFC_PROTO_NFC_DEP_MASK;
 
-       dev->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols);
+       dev->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols,
+                                          PN533_CMD_DATAEXCH_HEAD_LEN,
+                                          PN533_FRAME_TAIL_SIZE);
        if (!dev->nfc_dev)
                goto kill_tasklet;
 
index 330a4c5..c525e0b 100644 (file)
@@ -123,4 +123,6 @@ struct sockaddr_nfc {
 #define NFC_SOCKPROTO_RAW      0
 #define NFC_SOCKPROTO_MAX      1
 
+#define NFC_HEADER_SIZE 1
+
 #endif /*__LINUX_NFC_H */
index cc01303..87b51fe 100644 (file)
@@ -82,6 +82,9 @@ struct nfc_dev {
        struct nfc_genl_data genl_data;
        u32 supported_protocols;
 
+       int tx_headroom;
+       int tx_tailroom;
+
        struct nfc_ops *ops;
 };
 #define to_nfc_dev(_dev) container_of(_dev, struct nfc_dev, dev)
@@ -89,7 +92,9 @@ struct nfc_dev {
 extern struct class nfc_class;
 
 struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,
-                                       u32 supported_protocols);
+                                       u32 supported_protocols,
+                                       int tx_headroom,
+                                       int tx_tailroom);
 
 /**
  * nfc_free_device - free nfc device
index b6fd4e1..284e2f6 100644 (file)
@@ -322,7 +322,9 @@ struct nfc_dev *nfc_get_device(unsigned idx)
  * @supported_protocols: NFC protocols supported by the device
  */
 struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,
-                                       u32 supported_protocols)
+                                       u32 supported_protocols,
+                                       int tx_headroom,
+                                       int tx_tailroom)
 {
        static atomic_t dev_no = ATOMIC_INIT(0);
        struct nfc_dev *dev;
@@ -345,6 +347,8 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,
 
        dev->ops = ops;
        dev->supported_protocols = supported_protocols;
+       dev->tx_headroom = tx_headroom;
+       dev->tx_tailroom = tx_tailroom;
 
        spin_lock_init(&dev->targets_lock);
        nfc_genl_data_init(&dev->genl_data);
index 52de84a..9fd652a 100644 (file)
@@ -123,11 +123,7 @@ error:
 
 static int rawsock_add_header(struct sk_buff *skb)
 {
-
-       if (skb_cow_head(skb, 1))
-               return -ENOMEM;
-
-       *skb_push(skb, 1) = 0;
+       *skb_push(skb, NFC_HEADER_SIZE) = 0;
 
        return 0;
 }
@@ -197,6 +193,7 @@ static int rawsock_sendmsg(struct kiocb *iocb, struct socket *sock,
                                        struct msghdr *msg, size_t len)
 {
        struct sock *sk = sock->sk;
+       struct nfc_dev *dev = nfc_rawsock(sk)->dev;
        struct sk_buff *skb;
        int rc;
 
@@ -208,11 +205,13 @@ static int rawsock_sendmsg(struct kiocb *iocb, struct socket *sock,
        if (sock->state != SS_CONNECTED)
                return -ENOTCONN;
 
-       skb = sock_alloc_send_skb(sk, len, msg->msg_flags & MSG_DONTWAIT,
-                                                                       &rc);
+       skb = sock_alloc_send_skb(sk, len + dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE,
+                                       msg->msg_flags & MSG_DONTWAIT, &rc);
        if (!skb)
                return rc;
 
+       skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE);
+
        rc = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
        if (rc < 0) {
                kfree_skb(skb);