403 lines · c
1// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause2/*3 * Copyright (c) 2011, 2012, Qualcomm Atheros Communications Inc.4 * Copyright (c) 2017, I2SE GmbH5 */6 7/* This module implements the Qualcomm Atheros UART protocol for8 * kernel-based UART device; it is essentially an Ethernet-to-UART9 * serial converter;10 */11 12#include <linux/device.h>13#include <linux/errno.h>14#include <linux/etherdevice.h>15#include <linux/if_arp.h>16#include <linux/if_ether.h>17#include <linux/jiffies.h>18#include <linux/kernel.h>19#include <linux/module.h>20#include <linux/netdevice.h>21#include <linux/of.h>22#include <linux/of_net.h>23#include <linux/sched.h>24#include <linux/serdev.h>25#include <linux/skbuff.h>26#include <linux/types.h>27 28#include "qca_7k_common.h"29 30#define QCAUART_DRV_VERSION "0.1.0"31#define QCAUART_DRV_NAME "qcauart"32#define QCAUART_TX_TIMEOUT (1 * HZ)33 34struct qcauart {35 struct net_device *net_dev;36 spinlock_t lock; /* transmit lock */37 struct work_struct tx_work; /* Flushes transmit buffer */38 39 struct serdev_device *serdev;40 struct qcafrm_handle frm_handle;41 struct sk_buff *rx_skb;42 43 unsigned char *tx_head; /* pointer to next XMIT byte */44 int tx_left; /* bytes left in XMIT queue */45 unsigned char *tx_buffer;46};47 48static size_t49qca_tty_receive(struct serdev_device *serdev, const u8 *data, size_t count)50{51 struct qcauart *qca = serdev_device_get_drvdata(serdev);52 struct net_device *netdev = qca->net_dev;53 struct net_device_stats *n_stats = &netdev->stats;54 size_t i;55 56 if (!qca->rx_skb) {57 qca->rx_skb = netdev_alloc_skb_ip_align(netdev,58 netdev->mtu +59 VLAN_ETH_HLEN);60 if (!qca->rx_skb) {61 n_stats->rx_errors++;62 n_stats->rx_dropped++;63 return 0;64 }65 }66 67 for (i = 0; i < count; i++) {68 s32 retcode;69 70 retcode = qcafrm_fsm_decode(&qca->frm_handle,71 qca->rx_skb->data,72 skb_tailroom(qca->rx_skb),73 data[i]);74 75 switch (retcode) {76 case QCAFRM_GATHER:77 case QCAFRM_NOHEAD:78 break;79 case QCAFRM_NOTAIL:80 netdev_dbg(netdev, "recv: no RX tail\n");81 n_stats->rx_errors++;82 n_stats->rx_dropped++;83 break;84 case QCAFRM_INVLEN:85 netdev_dbg(netdev, "recv: invalid RX length\n");86 n_stats->rx_errors++;87 n_stats->rx_dropped++;88 break;89 default:90 n_stats->rx_packets++;91 n_stats->rx_bytes += retcode;92 skb_put(qca->rx_skb, retcode);93 qca->rx_skb->protocol = eth_type_trans(94 qca->rx_skb, qca->rx_skb->dev);95 skb_checksum_none_assert(qca->rx_skb);96 netif_rx(qca->rx_skb);97 qca->rx_skb = netdev_alloc_skb_ip_align(netdev,98 netdev->mtu +99 VLAN_ETH_HLEN);100 if (!qca->rx_skb) {101 netdev_dbg(netdev, "recv: out of RX resources\n");102 n_stats->rx_errors++;103 return i;104 }105 }106 }107 108 return i;109}110 111/* Write out any remaining transmit buffer. Scheduled when tty is writable */112static void qcauart_transmit(struct work_struct *work)113{114 struct qcauart *qca = container_of(work, struct qcauart, tx_work);115 struct net_device_stats *n_stats = &qca->net_dev->stats;116 int written;117 118 spin_lock_bh(&qca->lock);119 120 /* First make sure we're connected. */121 if (!netif_running(qca->net_dev)) {122 spin_unlock_bh(&qca->lock);123 return;124 }125 126 if (qca->tx_left <= 0) {127 /* Now serial buffer is almost free & we can start128 * transmission of another packet129 */130 n_stats->tx_packets++;131 spin_unlock_bh(&qca->lock);132 netif_wake_queue(qca->net_dev);133 return;134 }135 136 written = serdev_device_write_buf(qca->serdev, qca->tx_head,137 qca->tx_left);138 if (written > 0) {139 qca->tx_left -= written;140 qca->tx_head += written;141 }142 spin_unlock_bh(&qca->lock);143}144 145/* Called by the driver when there's room for more data.146 * Schedule the transmit.147 */148static void qca_tty_wakeup(struct serdev_device *serdev)149{150 struct qcauart *qca = serdev_device_get_drvdata(serdev);151 152 schedule_work(&qca->tx_work);153}154 155static const struct serdev_device_ops qca_serdev_ops = {156 .receive_buf = qca_tty_receive,157 .write_wakeup = qca_tty_wakeup,158};159 160static int qcauart_netdev_open(struct net_device *dev)161{162 struct qcauart *qca = netdev_priv(dev);163 164 netif_start_queue(qca->net_dev);165 166 return 0;167}168 169static int qcauart_netdev_close(struct net_device *dev)170{171 struct qcauart *qca = netdev_priv(dev);172 173 netif_stop_queue(dev);174 flush_work(&qca->tx_work);175 176 spin_lock_bh(&qca->lock);177 qca->tx_left = 0;178 spin_unlock_bh(&qca->lock);179 180 return 0;181}182 183static netdev_tx_t184qcauart_netdev_xmit(struct sk_buff *skb, struct net_device *dev)185{186 struct net_device_stats *n_stats = &dev->stats;187 struct qcauart *qca = netdev_priv(dev);188 u8 pad_len = 0;189 int written;190 u8 *pos;191 192 spin_lock(&qca->lock);193 194 WARN_ON(qca->tx_left);195 196 if (!netif_running(dev)) {197 spin_unlock(&qca->lock);198 netdev_warn(qca->net_dev, "xmit: iface is down\n");199 goto out;200 }201 202 pos = qca->tx_buffer;203 204 if (skb->len < QCAFRM_MIN_LEN)205 pad_len = QCAFRM_MIN_LEN - skb->len;206 207 pos += qcafrm_create_header(pos, skb->len + pad_len);208 209 memcpy(pos, skb->data, skb->len);210 pos += skb->len;211 212 if (pad_len) {213 memset(pos, 0, pad_len);214 pos += pad_len;215 }216 217 pos += qcafrm_create_footer(pos);218 219 netif_stop_queue(qca->net_dev);220 221 written = serdev_device_write_buf(qca->serdev, qca->tx_buffer,222 pos - qca->tx_buffer);223 if (written > 0) {224 qca->tx_left = (pos - qca->tx_buffer) - written;225 qca->tx_head = qca->tx_buffer + written;226 n_stats->tx_bytes += written;227 }228 spin_unlock(&qca->lock);229 230 netif_trans_update(dev);231out:232 dev_kfree_skb_any(skb);233 return NETDEV_TX_OK;234}235 236static void qcauart_netdev_tx_timeout(struct net_device *dev, unsigned int txqueue)237{238 struct qcauart *qca = netdev_priv(dev);239 240 netdev_info(qca->net_dev, "Transmit timeout at %ld, latency %ld\n",241 jiffies, dev_trans_start(dev));242 dev->stats.tx_errors++;243 dev->stats.tx_dropped++;244}245 246static int qcauart_netdev_init(struct net_device *dev)247{248 struct qcauart *qca = netdev_priv(dev);249 size_t len;250 251 /* Finish setting up the device info. */252 dev->mtu = QCAFRM_MAX_MTU;253 dev->type = ARPHRD_ETHER;254 255 len = QCAFRM_HEADER_LEN + QCAFRM_MAX_LEN + QCAFRM_FOOTER_LEN;256 qca->tx_buffer = devm_kmalloc(&qca->serdev->dev, len, GFP_KERNEL);257 if (!qca->tx_buffer)258 return -ENOMEM;259 260 qca->rx_skb = netdev_alloc_skb_ip_align(qca->net_dev,261 qca->net_dev->mtu +262 VLAN_ETH_HLEN);263 if (!qca->rx_skb)264 return -ENOBUFS;265 266 return 0;267}268 269static void qcauart_netdev_uninit(struct net_device *dev)270{271 struct qcauart *qca = netdev_priv(dev);272 273 dev_kfree_skb(qca->rx_skb);274}275 276static const struct net_device_ops qcauart_netdev_ops = {277 .ndo_init = qcauart_netdev_init,278 .ndo_uninit = qcauart_netdev_uninit,279 .ndo_open = qcauart_netdev_open,280 .ndo_stop = qcauart_netdev_close,281 .ndo_start_xmit = qcauart_netdev_xmit,282 .ndo_set_mac_address = eth_mac_addr,283 .ndo_tx_timeout = qcauart_netdev_tx_timeout,284 .ndo_validate_addr = eth_validate_addr,285};286 287static void qcauart_netdev_setup(struct net_device *dev)288{289 dev->netdev_ops = &qcauart_netdev_ops;290 dev->watchdog_timeo = QCAUART_TX_TIMEOUT;291 dev->priv_flags &= ~IFF_TX_SKB_SHARING;292 dev->tx_queue_len = 100;293 294 /* MTU range: 46 - 1500 */295 dev->min_mtu = QCAFRM_MIN_MTU;296 dev->max_mtu = QCAFRM_MAX_MTU;297}298 299static const struct of_device_id qca_uart_of_match[] = {300 {301 .compatible = "qca,qca7000",302 },303 {}304};305MODULE_DEVICE_TABLE(of, qca_uart_of_match);306 307static int qca_uart_probe(struct serdev_device *serdev)308{309 struct net_device *qcauart_dev = alloc_etherdev(sizeof(struct qcauart));310 struct qcauart *qca;311 u32 speed = 115200;312 int ret;313 314 if (!qcauart_dev)315 return -ENOMEM;316 317 qcauart_netdev_setup(qcauart_dev);318 SET_NETDEV_DEV(qcauart_dev, &serdev->dev);319 320 qca = netdev_priv(qcauart_dev);321 if (!qca) {322 pr_err("qca_uart: Fail to retrieve private structure\n");323 ret = -ENOMEM;324 goto free;325 }326 qca->net_dev = qcauart_dev;327 qca->serdev = serdev;328 qcafrm_fsm_init_uart(&qca->frm_handle);329 330 spin_lock_init(&qca->lock);331 INIT_WORK(&qca->tx_work, qcauart_transmit);332 333 of_property_read_u32(serdev->dev.of_node, "current-speed", &speed);334 335 ret = of_get_ethdev_address(serdev->dev.of_node, qca->net_dev);336 if (ret) {337 eth_hw_addr_random(qca->net_dev);338 dev_info(&serdev->dev, "Using random MAC address: %pM\n",339 qca->net_dev->dev_addr);340 }341 342 netif_carrier_on(qca->net_dev);343 serdev_device_set_drvdata(serdev, qca);344 serdev_device_set_client_ops(serdev, &qca_serdev_ops);345 346 ret = serdev_device_open(serdev);347 if (ret) {348 dev_err(&serdev->dev, "Unable to open device %s\n",349 qcauart_dev->name);350 goto free;351 }352 353 speed = serdev_device_set_baudrate(serdev, speed);354 dev_info(&serdev->dev, "Using baudrate: %u\n", speed);355 356 serdev_device_set_flow_control(serdev, false);357 358 ret = register_netdev(qcauart_dev);359 if (ret) {360 dev_err(&serdev->dev, "Unable to register net device %s\n",361 qcauart_dev->name);362 serdev_device_close(serdev);363 cancel_work_sync(&qca->tx_work);364 goto free;365 }366 367 return 0;368 369free:370 free_netdev(qcauart_dev);371 return ret;372}373 374static void qca_uart_remove(struct serdev_device *serdev)375{376 struct qcauart *qca = serdev_device_get_drvdata(serdev);377 378 unregister_netdev(qca->net_dev);379 380 /* Flush any pending characters in the driver. */381 serdev_device_close(serdev);382 cancel_work_sync(&qca->tx_work);383 384 free_netdev(qca->net_dev);385}386 387static struct serdev_device_driver qca_uart_driver = {388 .probe = qca_uart_probe,389 .remove = qca_uart_remove,390 .driver = {391 .name = QCAUART_DRV_NAME,392 .of_match_table = qca_uart_of_match,393 },394};395 396module_serdev_device_driver(qca_uart_driver);397 398MODULE_DESCRIPTION("Qualcomm Atheros QCA7000 UART Driver");399MODULE_AUTHOR("Qualcomm Atheros Communications");400MODULE_AUTHOR("Stefan Wahren <wahrenst@gmx.net>");401MODULE_LICENSE("Dual BSD/GPL");402MODULE_VERSION(QCAUART_DRV_VERSION);403