|
@@ -226,7 +226,7 @@ static ssize_t dbgfs_frame(struct file *file, char __user *user_buf,
|
|
|
"Tx data (Len: %d):\n", cfspi->tx_cpck_len);
|
|
|
|
|
|
len += print_frame((buf + len), (DEBUGFS_BUF_SIZE - len),
|
|
|
- cfspi->xfer.va_tx,
|
|
|
+ cfspi->xfer.va_tx[0],
|
|
|
(cfspi->tx_cpck_len + SPI_CMD_SZ), 100);
|
|
|
|
|
|
len += snprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
|
|
@@ -599,48 +599,11 @@ static int cfspi_close(struct net_device *dev)
|
|
|
netif_stop_queue(dev);
|
|
|
return 0;
|
|
|
}
|
|
|
-static const struct net_device_ops cfspi_ops = {
|
|
|
- .ndo_open = cfspi_open,
|
|
|
- .ndo_stop = cfspi_close,
|
|
|
- .ndo_start_xmit = cfspi_xmit
|
|
|
-};
|
|
|
|
|
|
-static void cfspi_setup(struct net_device *dev)
|
|
|
+static int cfspi_init(struct net_device *dev)
|
|
|
{
|
|
|
+ int res = 0;
|
|
|
struct cfspi *cfspi = netdev_priv(dev);
|
|
|
- dev->features = 0;
|
|
|
- dev->netdev_ops = &cfspi_ops;
|
|
|
- dev->type = ARPHRD_CAIF;
|
|
|
- dev->flags = IFF_NOARP | IFF_POINTOPOINT;
|
|
|
- dev->tx_queue_len = 0;
|
|
|
- dev->mtu = SPI_MAX_PAYLOAD_SIZE;
|
|
|
- dev->destructor = free_netdev;
|
|
|
- skb_queue_head_init(&cfspi->qhead);
|
|
|
- skb_queue_head_init(&cfspi->chead);
|
|
|
- cfspi->cfdev.link_select = CAIF_LINK_HIGH_BANDW;
|
|
|
- cfspi->cfdev.use_frag = false;
|
|
|
- cfspi->cfdev.use_stx = false;
|
|
|
- cfspi->cfdev.use_fcs = false;
|
|
|
- cfspi->ndev = dev;
|
|
|
-}
|
|
|
-
|
|
|
-int cfspi_spi_probe(struct platform_device *pdev)
|
|
|
-{
|
|
|
- struct cfspi *cfspi = NULL;
|
|
|
- struct net_device *ndev;
|
|
|
- struct cfspi_dev *dev;
|
|
|
- int res;
|
|
|
- dev = (struct cfspi_dev *)pdev->dev.platform_data;
|
|
|
-
|
|
|
- ndev = alloc_netdev(sizeof(struct cfspi),
|
|
|
- "cfspi%d", cfspi_setup);
|
|
|
- if (!ndev)
|
|
|
- return -ENOMEM;
|
|
|
-
|
|
|
- cfspi = netdev_priv(ndev);
|
|
|
- netif_stop_queue(ndev);
|
|
|
- cfspi->ndev = ndev;
|
|
|
- cfspi->pdev = pdev;
|
|
|
|
|
|
/* Set flow info. */
|
|
|
cfspi->flow_off_sent = 0;
|
|
@@ -656,16 +619,11 @@ int cfspi_spi_probe(struct platform_device *pdev)
|
|
|
cfspi->slave_talked = false;
|
|
|
}
|
|
|
|
|
|
- /* Assign the SPI device. */
|
|
|
- cfspi->dev = dev;
|
|
|
- /* Assign the device ifc to this SPI interface. */
|
|
|
- dev->ifc = &cfspi->ifc;
|
|
|
-
|
|
|
/* Allocate DMA buffers. */
|
|
|
- cfspi->xfer.va_tx = dma_alloc(&cfspi->xfer.pa_tx);
|
|
|
- if (!cfspi->xfer.va_tx) {
|
|
|
+ cfspi->xfer.va_tx[0] = dma_alloc(&cfspi->xfer.pa_tx[0]);
|
|
|
+ if (!cfspi->xfer.va_tx[0]) {
|
|
|
res = -ENODEV;
|
|
|
- goto err_dma_alloc_tx;
|
|
|
+ goto err_dma_alloc_tx_0;
|
|
|
}
|
|
|
|
|
|
cfspi->xfer.va_rx = dma_alloc(&cfspi->xfer.pa_rx);
|
|
@@ -714,6 +672,87 @@ int cfspi_spi_probe(struct platform_device *pdev)
|
|
|
/* Schedule the work queue. */
|
|
|
queue_work(cfspi->wq, &cfspi->work);
|
|
|
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ err_create_wq:
|
|
|
+ dma_free(cfspi->xfer.va_rx, cfspi->xfer.pa_rx);
|
|
|
+ err_dma_alloc_rx:
|
|
|
+ dma_free(cfspi->xfer.va_tx[0], cfspi->xfer.pa_tx[0]);
|
|
|
+ err_dma_alloc_tx_0:
|
|
|
+ return res;
|
|
|
+}
|
|
|
+
|
|
|
+static void cfspi_uninit(struct net_device *dev)
|
|
|
+{
|
|
|
+ struct cfspi *cfspi = netdev_priv(dev);
|
|
|
+
|
|
|
+ /* Remove from list. */
|
|
|
+ spin_lock(&cfspi_list_lock);
|
|
|
+ list_del(&cfspi->list);
|
|
|
+ spin_unlock(&cfspi_list_lock);
|
|
|
+
|
|
|
+ cfspi->ndev = NULL;
|
|
|
+ /* Free DMA buffers. */
|
|
|
+ dma_free(cfspi->xfer.va_rx, cfspi->xfer.pa_rx);
|
|
|
+ dma_free(cfspi->xfer.va_tx[0], cfspi->xfer.pa_tx[0]);
|
|
|
+ set_bit(SPI_TERMINATE, &cfspi->state);
|
|
|
+ wake_up_interruptible(&cfspi->wait);
|
|
|
+ destroy_workqueue(cfspi->wq);
|
|
|
+ /* Destroy debugfs directory and files. */
|
|
|
+ dev_debugfs_rem(cfspi);
|
|
|
+ return;
|
|
|
+}
|
|
|
+
|
|
|
+static const struct net_device_ops cfspi_ops = {
|
|
|
+ .ndo_open = cfspi_open,
|
|
|
+ .ndo_stop = cfspi_close,
|
|
|
+ .ndo_init = cfspi_init,
|
|
|
+ .ndo_uninit = cfspi_uninit,
|
|
|
+ .ndo_start_xmit = cfspi_xmit
|
|
|
+};
|
|
|
+
|
|
|
+static void cfspi_setup(struct net_device *dev)
|
|
|
+{
|
|
|
+ struct cfspi *cfspi = netdev_priv(dev);
|
|
|
+ dev->features = 0;
|
|
|
+ dev->netdev_ops = &cfspi_ops;
|
|
|
+ dev->type = ARPHRD_CAIF;
|
|
|
+ dev->flags = IFF_NOARP | IFF_POINTOPOINT;
|
|
|
+ dev->tx_queue_len = 0;
|
|
|
+ dev->mtu = SPI_MAX_PAYLOAD_SIZE;
|
|
|
+ dev->destructor = free_netdev;
|
|
|
+ skb_queue_head_init(&cfspi->qhead);
|
|
|
+ skb_queue_head_init(&cfspi->chead);
|
|
|
+ cfspi->cfdev.link_select = CAIF_LINK_HIGH_BANDW;
|
|
|
+ cfspi->cfdev.use_frag = false;
|
|
|
+ cfspi->cfdev.use_stx = false;
|
|
|
+ cfspi->cfdev.use_fcs = false;
|
|
|
+ cfspi->ndev = dev;
|
|
|
+}
|
|
|
+
|
|
|
+int cfspi_spi_probe(struct platform_device *pdev)
|
|
|
+{
|
|
|
+ struct cfspi *cfspi = NULL;
|
|
|
+ struct net_device *ndev;
|
|
|
+ struct cfspi_dev *dev;
|
|
|
+ int res;
|
|
|
+ dev = (struct cfspi_dev *)pdev->dev.platform_data;
|
|
|
+
|
|
|
+ ndev = alloc_netdev(sizeof(struct cfspi),
|
|
|
+ "cfspi%d", cfspi_setup);
|
|
|
+ if (!dev)
|
|
|
+ return -ENODEV;
|
|
|
+
|
|
|
+ cfspi = netdev_priv(ndev);
|
|
|
+ netif_stop_queue(ndev);
|
|
|
+ cfspi->ndev = ndev;
|
|
|
+ cfspi->pdev = pdev;
|
|
|
+
|
|
|
+ /* Assign the SPI device. */
|
|
|
+ cfspi->dev = dev;
|
|
|
+ /* Assign the device ifc to this SPI interface. */
|
|
|
+ dev->ifc = &cfspi->ifc;
|
|
|
+
|
|
|
/* Register network device. */
|
|
|
res = register_netdev(ndev);
|
|
|
if (res) {
|
|
@@ -723,15 +762,6 @@ int cfspi_spi_probe(struct platform_device *pdev)
|
|
|
return res;
|
|
|
|
|
|
err_net_reg:
|
|
|
- dev_debugfs_rem(cfspi);
|
|
|
- set_bit(SPI_TERMINATE, &cfspi->state);
|
|
|
- wake_up_interruptible(&cfspi->wait);
|
|
|
- destroy_workqueue(cfspi->wq);
|
|
|
- err_create_wq:
|
|
|
- dma_free(cfspi->xfer.va_rx, cfspi->xfer.pa_rx);
|
|
|
- err_dma_alloc_rx:
|
|
|
- dma_free(cfspi->xfer.va_tx, cfspi->xfer.pa_tx);
|
|
|
- err_dma_alloc_tx:
|
|
|
free_netdev(ndev);
|
|
|
|
|
|
return res;
|
|
@@ -739,34 +769,8 @@ int cfspi_spi_probe(struct platform_device *pdev)
|
|
|
|
|
|
int cfspi_spi_remove(struct platform_device *pdev)
|
|
|
{
|
|
|
- struct list_head *list_node;
|
|
|
- struct list_head *n;
|
|
|
- struct cfspi *cfspi = NULL;
|
|
|
- struct cfspi_dev *dev;
|
|
|
-
|
|
|
- dev = (struct cfspi_dev *)pdev->dev.platform_data;
|
|
|
- spin_lock(&cfspi_list_lock);
|
|
|
- list_for_each_safe(list_node, n, &cfspi_list) {
|
|
|
- cfspi = list_entry(list_node, struct cfspi, list);
|
|
|
- /* Find the corresponding device. */
|
|
|
- if (cfspi->dev == dev) {
|
|
|
- /* Remove from list. */
|
|
|
- list_del(list_node);
|
|
|
- /* Free DMA buffers. */
|
|
|
- dma_free(cfspi->xfer.va_rx, cfspi->xfer.pa_rx);
|
|
|
- dma_free(cfspi->xfer.va_tx, cfspi->xfer.pa_tx);
|
|
|
- set_bit(SPI_TERMINATE, &cfspi->state);
|
|
|
- wake_up_interruptible(&cfspi->wait);
|
|
|
- destroy_workqueue(cfspi->wq);
|
|
|
- /* Destroy debugfs directory and files. */
|
|
|
- dev_debugfs_rem(cfspi);
|
|
|
- unregister_netdev(cfspi->ndev);
|
|
|
- spin_unlock(&cfspi_list_lock);
|
|
|
- return 0;
|
|
|
- }
|
|
|
- }
|
|
|
- spin_unlock(&cfspi_list_lock);
|
|
|
- return -ENODEV;
|
|
|
+ /* Everything is done in cfspi_uninit(). */
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
static void __exit cfspi_exit_module(void)
|
|
@@ -777,7 +781,7 @@ static void __exit cfspi_exit_module(void)
|
|
|
|
|
|
list_for_each_safe(list_node, n, &cfspi_list) {
|
|
|
cfspi = list_entry(list_node, struct cfspi, list);
|
|
|
- platform_device_unregister(cfspi->pdev);
|
|
|
+ unregister_netdev(cfspi->ndev);
|
|
|
}
|
|
|
|
|
|
/* Destroy sysfs files. */
|