3 * Copyright (C) ST-Ericsson AB 2011
4 * Author: Sjur Brendeland
5 * License terms: GNU General Public License (GPL) version 2
9 #define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__
11 #include <linux/module.h>
12 #include <linux/netdevice.h>
13 #include <linux/slab.h>
14 #include <linux/mii.h>
15 #include <linux/usb.h>
16 #include <linux/usb/usbnet.h>
17 #include <linux/etherdevice.h>
18 #include <net/netns/generic.h>
19 #include <net/caif/caif_dev.h>
20 #include <net/caif/caif_layer.h>
21 #include <net/caif/cfpkt.h>
22 #include <net/caif/cfcnfg.h>
24 MODULE_LICENSE("GPL");
26 #define CFUSB_PAD_DESCR_SZ 1 /* Alignment descriptor length */
27 #define CFUSB_ALIGNMENT 4 /* Number of bytes to align. */
28 #define CFUSB_MAX_HEADLEN (CFUSB_PAD_DESCR_SZ + CFUSB_ALIGNMENT-1)
29 #define STE_USB_VID 0x04cc /* USB Product ID for ST-Ericsson */
30 #define STE_USB_PID_CAIF 0x230f /* Product id for CAIF Modems */
34 u8 tx_eth_hdr
[ETH_HLEN
];
37 static bool pack_added
;
39 static int cfusbl_receive(struct cflayer
*layr
, struct cfpkt
*pkt
)
44 cfpkt_extr_head(pkt
, &hpad
, 1);
45 cfpkt_extr_head(pkt
, NULL
, hpad
);
46 return layr
->up
->receive(layr
->up
, pkt
);
49 static int cfusbl_transmit(struct cflayer
*layr
, struct cfpkt
*pkt
)
51 struct caif_payload_info
*info
;
53 u8 zeros
[CFUSB_ALIGNMENT
];
55 struct cfusbl
*usbl
= container_of(layr
, struct cfusbl
, layer
);
57 skb
= cfpkt_tonative(pkt
);
59 skb_reset_network_header(skb
);
60 skb
->protocol
= htons(ETH_P_IP
);
62 info
= cfpkt_info(pkt
);
63 hpad
= (info
->hdr_len
+ CFUSB_PAD_DESCR_SZ
) & (CFUSB_ALIGNMENT
- 1);
65 if (skb_headroom(skb
) < ETH_HLEN
+ CFUSB_PAD_DESCR_SZ
+ hpad
) {
66 pr_warn("Headroom to small\n");
70 memset(zeros
, 0, hpad
);
72 cfpkt_add_head(pkt
, zeros
, hpad
);
73 cfpkt_add_head(pkt
, &hpad
, 1);
74 cfpkt_add_head(pkt
, usbl
->tx_eth_hdr
, sizeof(usbl
->tx_eth_hdr
));
75 return layr
->dn
->transmit(layr
->dn
, pkt
);
78 static void cfusbl_ctrlcmd(struct cflayer
*layr
, enum caif_ctrlcmd ctrl
,
81 if (layr
->up
&& layr
->up
->ctrlcmd
)
82 layr
->up
->ctrlcmd(layr
->up
, ctrl
, layr
->id
);
85 static struct cflayer
*cfusbl_create(int phyid
, u8 ethaddr
[ETH_ALEN
],
88 struct cfusbl
*this = kmalloc(sizeof(struct cfusbl
), GFP_ATOMIC
);
91 pr_warn("Out of memory\n");
94 caif_assert(offsetof(struct cfusbl
, layer
) == 0);
96 memset(this, 0, sizeof(struct cflayer
));
97 this->layer
.receive
= cfusbl_receive
;
98 this->layer
.transmit
= cfusbl_transmit
;
99 this->layer
.ctrlcmd
= cfusbl_ctrlcmd
;
100 snprintf(this->layer
.name
, CAIF_LAYER_NAME_SZ
, "usb%d", phyid
);
101 this->layer
.id
= phyid
;
104 * Construct TX ethernet header:
105 * 0-5 destination address
106 * 5-11 source address
107 * 12-13 protocol type
109 ether_addr_copy(&this->tx_eth_hdr
[ETH_ALEN
], braddr
);
110 ether_addr_copy(&this->tx_eth_hdr
[ETH_ALEN
], ethaddr
);
111 this->tx_eth_hdr
[12] = cpu_to_be16(ETH_P_802_EX1
) & 0xff;
112 this->tx_eth_hdr
[13] = (cpu_to_be16(ETH_P_802_EX1
) >> 8) & 0xff;
113 pr_debug("caif ethernet TX-header dst:%pM src:%pM type:%02x%02x\n",
114 this->tx_eth_hdr
, this->tx_eth_hdr
+ ETH_ALEN
,
115 this->tx_eth_hdr
[12], this->tx_eth_hdr
[13]);
117 return (struct cflayer
*) this;
120 static struct packet_type caif_usb_type __read_mostly
= {
121 .type
= cpu_to_be16(ETH_P_802_EX1
),
124 static int cfusbl_device_notify(struct notifier_block
*me
, unsigned long what
,
127 struct net_device
*dev
= netdev_notifier_info_to_dev(ptr
);
128 struct caif_dev_common common
;
129 struct cflayer
*layer
, *link_support
;
130 struct usbnet
*usbnet
;
131 struct usb_device
*usbdev
;
133 /* Check whether we have a NCM device, and find its VID/PID. */
134 if (!(dev
->dev
.parent
&& dev
->dev
.parent
->driver
&&
135 strcmp(dev
->dev
.parent
->driver
->name
, "cdc_ncm") == 0))
138 usbnet
= netdev_priv(dev
);
139 usbdev
= usbnet
->udev
;
141 pr_debug("USB CDC NCM device VID:0x%4x PID:0x%4x\n",
142 le16_to_cpu(usbdev
->descriptor
.idVendor
),
143 le16_to_cpu(usbdev
->descriptor
.idProduct
));
145 /* Check for VID/PID that supports CAIF */
146 if (!(le16_to_cpu(usbdev
->descriptor
.idVendor
) == STE_USB_VID
&&
147 le16_to_cpu(usbdev
->descriptor
.idProduct
) == STE_USB_PID_CAIF
))
150 if (what
== NETDEV_UNREGISTER
)
151 module_put(THIS_MODULE
);
153 if (what
!= NETDEV_REGISTER
)
156 __module_get(THIS_MODULE
);
158 memset(&common
, 0, sizeof(common
));
159 common
.use_frag
= false;
160 common
.use_fcs
= false;
161 common
.use_stx
= false;
162 common
.link_select
= CAIF_LINK_HIGH_BANDW
;
163 common
.flowctrl
= NULL
;
165 link_support
= cfusbl_create(dev
->ifindex
, dev
->dev_addr
,
171 if (dev
->num_tx_queues
> 1)
172 pr_warn("USB device uses more than one tx queue\n");
174 caif_enroll_dev(dev
, &common
, link_support
, CFUSB_MAX_HEADLEN
,
175 &layer
, &caif_usb_type
.func
);
177 dev_add_pack(&caif_usb_type
);
180 strncpy(layer
->name
, dev
->name
,
181 sizeof(layer
->name
) - 1);
182 layer
->name
[sizeof(layer
->name
) - 1] = 0;
187 static struct notifier_block caif_device_notifier
= {
188 .notifier_call
= cfusbl_device_notify
,
192 static int __init
cfusbl_init(void)
194 return register_netdevice_notifier(&caif_device_notifier
);
197 static void __exit
cfusbl_exit(void)
199 unregister_netdevice_notifier(&caif_device_notifier
);
200 dev_remove_pack(&caif_usb_type
);
203 module_init(cfusbl_init
);
204 module_exit(cfusbl_exit
);