1 // SPDX-License-Identifier: GPL-2.0-only
4 * Copyright (C) ST-Ericsson AB 2011
5 * Author: Sjur Brendeland
8 #define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__
10 #include <linux/module.h>
11 #include <linux/netdevice.h>
12 #include <linux/slab.h>
13 #include <linux/mii.h>
14 #include <linux/usb.h>
15 #include <linux/usb/usbnet.h>
16 #include <linux/etherdevice.h>
17 #include <net/netns/generic.h>
18 #include <net/caif/caif_dev.h>
19 #include <net/caif/caif_layer.h>
20 #include <net/caif/cfpkt.h>
21 #include <net/caif/cfcnfg.h>
23 MODULE_LICENSE("GPL");
25 #define CFUSB_PAD_DESCR_SZ 1 /* Alignment descriptor length */
26 #define CFUSB_ALIGNMENT 4 /* Number of bytes to align. */
27 #define CFUSB_MAX_HEADLEN (CFUSB_PAD_DESCR_SZ + CFUSB_ALIGNMENT-1)
28 #define STE_USB_VID 0x04cc /* USB Product ID for ST-Ericsson */
29 #define STE_USB_PID_CAIF 0x230f /* Product id for CAIF Modems */
33 u8 tx_eth_hdr
[ETH_HLEN
];
36 static bool pack_added
;
38 static int cfusbl_receive(struct cflayer
*layr
, struct cfpkt
*pkt
)
43 cfpkt_extr_head(pkt
, &hpad
, 1);
44 cfpkt_extr_head(pkt
, NULL
, hpad
);
45 return layr
->up
->receive(layr
->up
, pkt
);
48 static int cfusbl_transmit(struct cflayer
*layr
, struct cfpkt
*pkt
)
50 struct caif_payload_info
*info
;
52 u8 zeros
[CFUSB_ALIGNMENT
];
54 struct cfusbl
*usbl
= container_of(layr
, struct cfusbl
, layer
);
56 skb
= cfpkt_tonative(pkt
);
58 skb_reset_network_header(skb
);
59 skb
->protocol
= htons(ETH_P_IP
);
61 info
= cfpkt_info(pkt
);
62 hpad
= (info
->hdr_len
+ CFUSB_PAD_DESCR_SZ
) & (CFUSB_ALIGNMENT
- 1);
64 if (skb_headroom(skb
) < ETH_HLEN
+ CFUSB_PAD_DESCR_SZ
+ hpad
) {
65 pr_warn("Headroom too small\n");
69 memset(zeros
, 0, hpad
);
71 cfpkt_add_head(pkt
, zeros
, hpad
);
72 cfpkt_add_head(pkt
, &hpad
, 1);
73 cfpkt_add_head(pkt
, usbl
->tx_eth_hdr
, sizeof(usbl
->tx_eth_hdr
));
74 return layr
->dn
->transmit(layr
->dn
, pkt
);
77 static void cfusbl_ctrlcmd(struct cflayer
*layr
, enum caif_ctrlcmd ctrl
,
80 if (layr
->up
&& layr
->up
->ctrlcmd
)
81 layr
->up
->ctrlcmd(layr
->up
, ctrl
, layr
->id
);
84 static struct cflayer
*cfusbl_create(int phyid
, u8 ethaddr
[ETH_ALEN
],
87 struct cfusbl
*this = kmalloc(sizeof(struct cfusbl
), GFP_ATOMIC
);
92 caif_assert(offsetof(struct cfusbl
, layer
) == 0);
94 memset(&this->layer
, 0, sizeof(this->layer
));
95 this->layer
.receive
= cfusbl_receive
;
96 this->layer
.transmit
= cfusbl_transmit
;
97 this->layer
.ctrlcmd
= cfusbl_ctrlcmd
;
98 snprintf(this->layer
.name
, CAIF_LAYER_NAME_SZ
, "usb%d", phyid
);
99 this->layer
.id
= phyid
;
102 * Construct TX ethernet header:
103 * 0-5 destination address
104 * 5-11 source address
105 * 12-13 protocol type
107 ether_addr_copy(&this->tx_eth_hdr
[ETH_ALEN
], braddr
);
108 ether_addr_copy(&this->tx_eth_hdr
[ETH_ALEN
], ethaddr
);
109 this->tx_eth_hdr
[12] = cpu_to_be16(ETH_P_802_EX1
) & 0xff;
110 this->tx_eth_hdr
[13] = (cpu_to_be16(ETH_P_802_EX1
) >> 8) & 0xff;
111 pr_debug("caif ethernet TX-header dst:%pM src:%pM type:%02x%02x\n",
112 this->tx_eth_hdr
, this->tx_eth_hdr
+ ETH_ALEN
,
113 this->tx_eth_hdr
[12], this->tx_eth_hdr
[13]);
115 return (struct cflayer
*) this;
118 static struct packet_type caif_usb_type __read_mostly
= {
119 .type
= cpu_to_be16(ETH_P_802_EX1
),
122 static int cfusbl_device_notify(struct notifier_block
*me
, unsigned long what
,
125 struct net_device
*dev
= netdev_notifier_info_to_dev(ptr
);
126 struct caif_dev_common common
;
127 struct cflayer
*layer
, *link_support
;
128 struct usbnet
*usbnet
;
129 struct usb_device
*usbdev
;
131 /* Check whether we have a NCM device, and find its VID/PID. */
132 if (!(dev
->dev
.parent
&& dev
->dev
.parent
->driver
&&
133 strcmp(dev
->dev
.parent
->driver
->name
, "cdc_ncm") == 0))
136 usbnet
= netdev_priv(dev
);
137 usbdev
= usbnet
->udev
;
139 pr_debug("USB CDC NCM device VID:0x%4x PID:0x%4x\n",
140 le16_to_cpu(usbdev
->descriptor
.idVendor
),
141 le16_to_cpu(usbdev
->descriptor
.idProduct
));
143 /* Check for VID/PID that supports CAIF */
144 if (!(le16_to_cpu(usbdev
->descriptor
.idVendor
) == STE_USB_VID
&&
145 le16_to_cpu(usbdev
->descriptor
.idProduct
) == STE_USB_PID_CAIF
))
148 if (what
== NETDEV_UNREGISTER
)
149 module_put(THIS_MODULE
);
151 if (what
!= NETDEV_REGISTER
)
154 __module_get(THIS_MODULE
);
156 memset(&common
, 0, sizeof(common
));
157 common
.use_frag
= false;
158 common
.use_fcs
= false;
159 common
.use_stx
= false;
160 common
.link_select
= CAIF_LINK_HIGH_BANDW
;
161 common
.flowctrl
= NULL
;
163 link_support
= cfusbl_create(dev
->ifindex
, dev
->dev_addr
,
169 if (dev
->num_tx_queues
> 1)
170 pr_warn("USB device uses more than one tx queue\n");
172 caif_enroll_dev(dev
, &common
, link_support
, CFUSB_MAX_HEADLEN
,
173 &layer
, &caif_usb_type
.func
);
175 dev_add_pack(&caif_usb_type
);
178 strlcpy(layer
->name
, dev
->name
, sizeof(layer
->name
));
183 static struct notifier_block caif_device_notifier
= {
184 .notifier_call
= cfusbl_device_notify
,
188 static int __init
cfusbl_init(void)
190 return register_netdevice_notifier(&caif_device_notifier
);
193 static void __exit
cfusbl_exit(void)
195 unregister_netdevice_notifier(&caif_device_notifier
);
196 dev_remove_pack(&caif_usb_type
);
199 module_init(cfusbl_init
);
200 module_exit(cfusbl_exit
);