diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2012-05-24 01:13:01 -0700 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2012-05-24 01:13:01 -0700 |
commit | e644dae645e167d154c0526358940986682a72b0 (patch) | |
tree | 972993c6568085b8d407fc7e13de10f4b93c651d /drivers/net/caif | |
parent | 899c612d74d4a242158a4db20367388d6299c028 (diff) | |
parent | 86809173ce32ef03bd4d0389dfc72df0c805e9c4 (diff) |
Merge branch 'next' into for-linus
Diffstat (limited to 'drivers/net/caif')
-rw-r--r-- | drivers/net/caif/caif_hsi.c | 147 | ||||
-rw-r--r-- | drivers/net/caif/caif_spi.c | 10 |
2 files changed, 106 insertions, 51 deletions
diff --git a/drivers/net/caif/caif_hsi.c b/drivers/net/caif/caif_hsi.c index 0a4fc62a381..9a66e2a910a 100644 --- a/drivers/net/caif/caif_hsi.c +++ b/drivers/net/caif/caif_hsi.c @@ -426,6 +426,35 @@ static int cfhsi_rx_desc(struct cfhsi_desc *desc, struct cfhsi *cfhsi) return xfer_sz; } +static int cfhsi_rx_desc_len(struct cfhsi_desc *desc) +{ + int xfer_sz = 0; + int nfrms = 0; + u16 *plen; + + if ((desc->header & ~CFHSI_PIGGY_DESC) || + (desc->offset > CFHSI_MAX_EMB_FRM_SZ)) { + + pr_err("Invalid descriptor. %x %x\n", desc->header, + desc->offset); + return -EPROTO; + } + + /* Calculate transfer length. */ + plen = desc->cffrm_len; + while (nfrms < CFHSI_MAX_PKTS && *plen) { + xfer_sz += *plen; + plen++; + nfrms++; + } + + if (xfer_sz % 4) { + pr_err("Invalid payload len: %d, ignored.\n", xfer_sz); + return -EPROTO; + } + return xfer_sz; +} + static int cfhsi_rx_pld(struct cfhsi_desc *desc, struct cfhsi *cfhsi) { int rx_sz = 0; @@ -517,8 +546,10 @@ static int cfhsi_rx_pld(struct cfhsi_desc *desc, struct cfhsi *cfhsi) static void cfhsi_rx_done(struct cfhsi *cfhsi) { int res; - int desc_pld_len = 0; + int desc_pld_len = 0, rx_len, rx_state; struct cfhsi_desc *desc = NULL; + u8 *rx_ptr, *rx_buf; + struct cfhsi_desc *piggy_desc = NULL; desc = (struct cfhsi_desc *)cfhsi->rx_buf; @@ -534,65 +565,71 @@ static void cfhsi_rx_done(struct cfhsi *cfhsi) spin_unlock_bh(&cfhsi->lock); if (cfhsi->rx_state.state == CFHSI_RX_STATE_DESC) { - desc_pld_len = cfhsi_rx_desc(desc, cfhsi); - if (desc_pld_len == -ENOMEM) - goto restart; - if (desc_pld_len == -EPROTO) + desc_pld_len = cfhsi_rx_desc_len(desc); + + if (desc_pld_len < 0) goto out_of_sync; + + rx_buf = cfhsi->rx_buf; + rx_len = desc_pld_len; + if (desc_pld_len > 0 && (desc->header & CFHSI_PIGGY_DESC)) + rx_len += CFHSI_DESC_SZ; + if (desc_pld_len == 0) + rx_buf = cfhsi->rx_flip_buf; } else { - int pld_len; + rx_buf = cfhsi->rx_flip_buf; - if (!cfhsi->rx_state.piggy_desc) { - pld_len = cfhsi_rx_pld(desc, cfhsi); - if (pld_len == -ENOMEM) - goto restart; - if (pld_len == -EPROTO) - goto out_of_sync; - cfhsi->rx_state.pld_len = pld_len; - } else { - pld_len = cfhsi->rx_state.pld_len; - } + rx_len = CFHSI_DESC_SZ; + if (cfhsi->rx_state.pld_len > 0 && + (desc->header & CFHSI_PIGGY_DESC)) { - if ((pld_len > 0) && (desc->header & CFHSI_PIGGY_DESC)) { - struct cfhsi_desc *piggy_desc; piggy_desc = (struct cfhsi_desc *) (desc->emb_frm + CFHSI_MAX_EMB_FRM_SZ + - pld_len); + cfhsi->rx_state.pld_len); + cfhsi->rx_state.piggy_desc = true; - /* Extract piggy-backed descriptor. */ - desc_pld_len = cfhsi_rx_desc(piggy_desc, cfhsi); - if (desc_pld_len == -ENOMEM) - goto restart; + /* Extract payload len from piggy-backed descriptor. */ + desc_pld_len = cfhsi_rx_desc_len(piggy_desc); + if (desc_pld_len < 0) + goto out_of_sync; + + if (desc_pld_len > 0) + rx_len = desc_pld_len; + + if (desc_pld_len > 0 && + (piggy_desc->header & CFHSI_PIGGY_DESC)) + rx_len += CFHSI_DESC_SZ; /* * Copy needed information from the piggy-backed * descriptor to the descriptor in the start. */ - memcpy((u8 *)desc, (u8 *)piggy_desc, + memcpy(rx_buf, (u8 *)piggy_desc, CFHSI_DESC_SHORT_SZ); - + /* Mark no embedded frame here */ + piggy_desc->offset = 0; if (desc_pld_len == -EPROTO) goto out_of_sync; } } - memset(&cfhsi->rx_state, 0, sizeof(cfhsi->rx_state)); if (desc_pld_len) { - cfhsi->rx_state.state = CFHSI_RX_STATE_PAYLOAD; - cfhsi->rx_ptr = cfhsi->rx_buf + CFHSI_DESC_SZ; - cfhsi->rx_len = desc_pld_len; + rx_state = CFHSI_RX_STATE_PAYLOAD; + rx_ptr = rx_buf + CFHSI_DESC_SZ; } else { - cfhsi->rx_state.state = CFHSI_RX_STATE_DESC; - cfhsi->rx_ptr = cfhsi->rx_buf; - cfhsi->rx_len = CFHSI_DESC_SZ; + rx_state = CFHSI_RX_STATE_DESC; + rx_ptr = rx_buf; + rx_len = CFHSI_DESC_SZ; } + /* Initiate next read */ if (test_bit(CFHSI_AWAKE, &cfhsi->bits)) { /* Set up new transfer. */ dev_dbg(&cfhsi->ndev->dev, "%s: Start RX.\n", - __func__); - res = cfhsi->dev->cfhsi_rx(cfhsi->rx_ptr, cfhsi->rx_len, + __func__); + + res = cfhsi->dev->cfhsi_rx(rx_ptr, rx_len, cfhsi->dev); if (WARN_ON(res < 0)) { dev_err(&cfhsi->ndev->dev, "%s: RX error %d.\n", @@ -601,16 +638,32 @@ static void cfhsi_rx_done(struct cfhsi *cfhsi) cfhsi->ndev->stats.rx_dropped++; } } - return; -restart: - if (++cfhsi->rx_state.retries > CFHSI_MAX_RX_RETRIES) { - dev_err(&cfhsi->ndev->dev, "%s: No memory available " - "in %d iterations.\n", - __func__, CFHSI_MAX_RX_RETRIES); - BUG(); + if (cfhsi->rx_state.state == CFHSI_RX_STATE_DESC) { + /* Extract payload from descriptor */ + if (cfhsi_rx_desc(desc, cfhsi) < 0) + goto out_of_sync; + } else { + /* Extract payload */ + if (cfhsi_rx_pld(desc, cfhsi) < 0) + goto out_of_sync; + if (piggy_desc) { + /* Extract any payload in piggyback descriptor. */ + if (cfhsi_rx_desc(piggy_desc, cfhsi) < 0) + goto out_of_sync; + } } - mod_timer(&cfhsi->rx_slowpath_timer, jiffies + 1); + + /* Update state info */ + memset(&cfhsi->rx_state, 0, sizeof(cfhsi->rx_state)); + cfhsi->rx_state.state = rx_state; + cfhsi->rx_ptr = rx_ptr; + cfhsi->rx_len = rx_len; + cfhsi->rx_state.pld_len = desc_pld_len; + cfhsi->rx_state.piggy_desc = desc->header & CFHSI_PIGGY_DESC; + + if (rx_buf != cfhsi->rx_buf) + swap(cfhsi->rx_buf, cfhsi->rx_flip_buf); return; out_of_sync: @@ -978,7 +1031,7 @@ static void cfhsi_setup(struct net_device *dev) dev->netdev_ops = &cfhsi_ops; dev->type = ARPHRD_CAIF; dev->flags = IFF_POINTOPOINT | IFF_NOARP; - dev->mtu = CFHSI_MAX_PAYLOAD_SZ; + dev->mtu = CFHSI_MAX_CAIF_FRAME_SZ; dev->tx_queue_len = 0; dev->destructor = free_netdev; skb_queue_head_init(&cfhsi->qhead); @@ -1040,6 +1093,12 @@ int cfhsi_probe(struct platform_device *pdev) goto err_alloc_rx; } + cfhsi->rx_flip_buf = kzalloc(CFHSI_BUF_SZ_RX, GFP_KERNEL); + if (!cfhsi->rx_flip_buf) { + res = -ENODEV; + goto err_alloc_rx_flip; + } + /* Pre-calculate inactivity timeout. */ if (inactivity_timeout != -1) { cfhsi->inactivity_timeout = @@ -1138,6 +1197,8 @@ int cfhsi_probe(struct platform_device *pdev) err_activate: destroy_workqueue(cfhsi->wq); err_create_wq: + kfree(cfhsi->rx_flip_buf); + err_alloc_rx_flip: kfree(cfhsi->rx_buf); err_alloc_rx: kfree(cfhsi->tx_buf); diff --git a/drivers/net/caif/caif_spi.c b/drivers/net/caif/caif_spi.c index 96391c36fa7..b71ce9bf0af 100644 --- a/drivers/net/caif/caif_spi.c +++ b/drivers/net/caif/caif_spi.c @@ -127,12 +127,6 @@ static inline void dev_debugfs_rem(struct cfspi *cfspi) debugfs_remove(cfspi->dbgfs_dir); } -static int dbgfs_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - static ssize_t dbgfs_state(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -243,13 +237,13 @@ static ssize_t dbgfs_frame(struct file *file, char __user *user_buf, } static const struct file_operations dbgfs_state_fops = { - .open = dbgfs_open, + .open = simple_open, .read = dbgfs_state, .owner = THIS_MODULE }; static const struct file_operations dbgfs_frame_fops = { - .open = dbgfs_open, + .open = simple_open, .read = dbgfs_frame, .owner = THIS_MODULE }; |