diff options
| author | Sjur Brændeland <sjur.brandeland@stericsson.com> | 2010-11-01 07:52:48 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2010-11-03 21:50:03 -0400 |
| commit | 2c24a5d1b4f48900f3ed1b1ad70c51f1983df822 (patch) | |
| tree | c40f3756a0b64af118e64dd8f345c6e6649e66a8 | |
| parent | f2527ec436fd675f08a8e7434f6e940688cb96d0 (diff) | |
caif: SPI-driver bugfix - incorrect padding.
Signed-off-by: Sjur Braendeland <sjur.brandeland@stericsson.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | drivers/net/caif/caif_spi.c | 57 | ||||
| -rw-r--r-- | drivers/net/caif/caif_spi_slave.c | 13 | ||||
| -rw-r--r-- | include/net/caif/caif_spi.h | 2 |
3 files changed, 53 insertions, 19 deletions
diff --git a/drivers/net/caif/caif_spi.c b/drivers/net/caif/caif_spi.c index 8427533fe313..8b4cea57a6c5 100644 --- a/drivers/net/caif/caif_spi.c +++ b/drivers/net/caif/caif_spi.c | |||
| @@ -33,6 +33,9 @@ MODULE_LICENSE("GPL"); | |||
| 33 | MODULE_AUTHOR("Daniel Martensson<daniel.martensson@stericsson.com>"); | 33 | MODULE_AUTHOR("Daniel Martensson<daniel.martensson@stericsson.com>"); |
| 34 | MODULE_DESCRIPTION("CAIF SPI driver"); | 34 | MODULE_DESCRIPTION("CAIF SPI driver"); |
| 35 | 35 | ||
| 36 | /* Returns the number of padding bytes for alignment. */ | ||
| 37 | #define PAD_POW2(x, pow) ((((x)&((pow)-1))==0) ? 0 : (((pow)-((x)&((pow)-1))))) | ||
| 38 | |||
| 36 | static int spi_loop; | 39 | static int spi_loop; |
| 37 | module_param(spi_loop, bool, S_IRUGO); | 40 | module_param(spi_loop, bool, S_IRUGO); |
| 38 | MODULE_PARM_DESC(spi_loop, "SPI running in loopback mode."); | 41 | MODULE_PARM_DESC(spi_loop, "SPI running in loopback mode."); |
| @@ -41,7 +44,10 @@ MODULE_PARM_DESC(spi_loop, "SPI running in loopback mode."); | |||
| 41 | module_param(spi_frm_align, int, S_IRUGO); | 44 | module_param(spi_frm_align, int, S_IRUGO); |
| 42 | MODULE_PARM_DESC(spi_frm_align, "SPI frame alignment."); | 45 | MODULE_PARM_DESC(spi_frm_align, "SPI frame alignment."); |
| 43 | 46 | ||
| 44 | /* SPI padding options. */ | 47 | /* |
| 48 | * SPI padding options. | ||
| 49 | * Warning: must be a base of 2 (& operation used) and can not be zero ! | ||
| 50 | */ | ||
| 45 | module_param(spi_up_head_align, int, S_IRUGO); | 51 | module_param(spi_up_head_align, int, S_IRUGO); |
| 46 | MODULE_PARM_DESC(spi_up_head_align, "SPI uplink head alignment."); | 52 | MODULE_PARM_DESC(spi_up_head_align, "SPI uplink head alignment."); |
| 47 | 53 | ||
| @@ -240,15 +246,13 @@ static ssize_t dbgfs_frame(struct file *file, char __user *user_buf, | |||
| 240 | static const struct file_operations dbgfs_state_fops = { | 246 | static const struct file_operations dbgfs_state_fops = { |
| 241 | .open = dbgfs_open, | 247 | .open = dbgfs_open, |
| 242 | .read = dbgfs_state, | 248 | .read = dbgfs_state, |
| 243 | .owner = THIS_MODULE, | 249 | .owner = THIS_MODULE |
| 244 | .llseek = default_llseek, | ||
| 245 | }; | 250 | }; |
| 246 | 251 | ||
| 247 | static const struct file_operations dbgfs_frame_fops = { | 252 | static const struct file_operations dbgfs_frame_fops = { |
| 248 | .open = dbgfs_open, | 253 | .open = dbgfs_open, |
| 249 | .read = dbgfs_frame, | 254 | .read = dbgfs_frame, |
| 250 | .owner = THIS_MODULE, | 255 | .owner = THIS_MODULE |
| 251 | .llseek = default_llseek, | ||
| 252 | }; | 256 | }; |
| 253 | 257 | ||
| 254 | static inline void dev_debugfs_add(struct cfspi *cfspi) | 258 | static inline void dev_debugfs_add(struct cfspi *cfspi) |
| @@ -337,6 +341,9 @@ int cfspi_xmitfrm(struct cfspi *cfspi, u8 *buf, size_t len) | |||
| 337 | u8 *dst = buf; | 341 | u8 *dst = buf; |
| 338 | caif_assert(buf); | 342 | caif_assert(buf); |
| 339 | 343 | ||
| 344 | if (cfspi->slave && !cfspi->slave_talked) | ||
| 345 | cfspi->slave_talked = true; | ||
| 346 | |||
| 340 | do { | 347 | do { |
| 341 | struct sk_buff *skb; | 348 | struct sk_buff *skb; |
| 342 | struct caif_payload_info *info; | 349 | struct caif_payload_info *info; |
| @@ -357,8 +364,8 @@ int cfspi_xmitfrm(struct cfspi *cfspi, u8 *buf, size_t len) | |||
| 357 | * Compute head offset i.e. number of bytes to add to | 364 | * Compute head offset i.e. number of bytes to add to |
| 358 | * get the start of the payload aligned. | 365 | * get the start of the payload aligned. |
| 359 | */ | 366 | */ |
| 360 | if (spi_up_head_align) { | 367 | if (spi_up_head_align > 1) { |
| 361 | spad = 1 + ((info->hdr_len + 1) & spi_up_head_align); | 368 | spad = 1 + PAD_POW2((info->hdr_len + 1), spi_up_head_align); |
| 362 | *dst = (u8)(spad - 1); | 369 | *dst = (u8)(spad - 1); |
| 363 | dst += spad; | 370 | dst += spad; |
| 364 | } | 371 | } |
| @@ -373,7 +380,7 @@ int cfspi_xmitfrm(struct cfspi *cfspi, u8 *buf, size_t len) | |||
| 373 | * Compute tail offset i.e. number of bytes to add to | 380 | * Compute tail offset i.e. number of bytes to add to |
| 374 | * get the complete CAIF frame aligned. | 381 | * get the complete CAIF frame aligned. |
| 375 | */ | 382 | */ |
| 376 | epad = (skb->len + spad) & spi_up_tail_align; | 383 | epad = PAD_POW2((skb->len + spad), spi_up_tail_align); |
| 377 | dst += epad; | 384 | dst += epad; |
| 378 | 385 | ||
| 379 | dev_kfree_skb(skb); | 386 | dev_kfree_skb(skb); |
| @@ -417,14 +424,14 @@ int cfspi_xmitlen(struct cfspi *cfspi) | |||
| 417 | * Compute head offset i.e. number of bytes to add to | 424 | * Compute head offset i.e. number of bytes to add to |
| 418 | * get the start of the payload aligned. | 425 | * get the start of the payload aligned. |
| 419 | */ | 426 | */ |
| 420 | if (spi_up_head_align) | 427 | if (spi_up_head_align > 1) |
| 421 | spad = 1 + ((info->hdr_len + 1) & spi_up_head_align); | 428 | spad = 1 + PAD_POW2((info->hdr_len + 1), spi_up_head_align); |
| 422 | 429 | ||
| 423 | /* | 430 | /* |
| 424 | * Compute tail offset i.e. number of bytes to add to | 431 | * Compute tail offset i.e. number of bytes to add to |
| 425 | * get the complete CAIF frame aligned. | 432 | * get the complete CAIF frame aligned. |
| 426 | */ | 433 | */ |
| 427 | epad = (skb->len + spad) & spi_up_tail_align; | 434 | epad = PAD_POW2((skb->len + spad), spi_up_tail_align); |
| 428 | 435 | ||
| 429 | if ((skb->len + spad + epad + frm_len) <= CAIF_MAX_SPI_FRAME) { | 436 | if ((skb->len + spad + epad + frm_len) <= CAIF_MAX_SPI_FRAME) { |
| 430 | skb_queue_tail(&cfspi->chead, skb); | 437 | skb_queue_tail(&cfspi->chead, skb); |
| @@ -433,6 +440,7 @@ int cfspi_xmitlen(struct cfspi *cfspi) | |||
| 433 | } else { | 440 | } else { |
| 434 | /* Put back packet. */ | 441 | /* Put back packet. */ |
| 435 | skb_queue_head(&cfspi->qhead, skb); | 442 | skb_queue_head(&cfspi->qhead, skb); |
| 443 | break; | ||
| 436 | } | 444 | } |
| 437 | } while (pkts <= CAIF_MAX_SPI_PKTS); | 445 | } while (pkts <= CAIF_MAX_SPI_PKTS); |
| 438 | 446 | ||
| @@ -453,6 +461,15 @@ static void cfspi_ss_cb(bool assert, struct cfspi_ifc *ifc) | |||
| 453 | { | 461 | { |
| 454 | struct cfspi *cfspi = (struct cfspi *)ifc->priv; | 462 | struct cfspi *cfspi = (struct cfspi *)ifc->priv; |
| 455 | 463 | ||
| 464 | /* | ||
| 465 | * The slave device is the master on the link. Interrupts before the | ||
| 466 | * slave has transmitted are considered spurious. | ||
| 467 | */ | ||
| 468 | if (cfspi->slave && !cfspi->slave_talked) { | ||
| 469 | printk(KERN_WARNING "CFSPI: Spurious SS interrupt.\n"); | ||
| 470 | return; | ||
| 471 | } | ||
| 472 | |||
| 456 | if (!in_interrupt()) | 473 | if (!in_interrupt()) |
| 457 | spin_lock(&cfspi->lock); | 474 | spin_lock(&cfspi->lock); |
| 458 | if (assert) { | 475 | if (assert) { |
| @@ -465,7 +482,8 @@ static void cfspi_ss_cb(bool assert, struct cfspi_ifc *ifc) | |||
| 465 | spin_unlock(&cfspi->lock); | 482 | spin_unlock(&cfspi->lock); |
| 466 | 483 | ||
| 467 | /* Wake up the xfer thread. */ | 484 | /* Wake up the xfer thread. */ |
| 468 | wake_up_interruptible(&cfspi->wait); | 485 | if (assert) |
| 486 | wake_up_interruptible(&cfspi->wait); | ||
| 469 | } | 487 | } |
| 470 | 488 | ||
| 471 | static void cfspi_xfer_done_cb(struct cfspi_ifc *ifc) | 489 | static void cfspi_xfer_done_cb(struct cfspi_ifc *ifc) |
| @@ -523,7 +541,7 @@ int cfspi_rxfrm(struct cfspi *cfspi, u8 *buf, size_t len) | |||
| 523 | * Compute head offset i.e. number of bytes added to | 541 | * Compute head offset i.e. number of bytes added to |
| 524 | * get the start of the payload aligned. | 542 | * get the start of the payload aligned. |
| 525 | */ | 543 | */ |
| 526 | if (spi_down_head_align) { | 544 | if (spi_down_head_align > 1) { |
| 527 | spad = 1 + *src; | 545 | spad = 1 + *src; |
| 528 | src += spad; | 546 | src += spad; |
| 529 | } | 547 | } |
| @@ -564,7 +582,7 @@ int cfspi_rxfrm(struct cfspi *cfspi, u8 *buf, size_t len) | |||
| 564 | * Compute tail offset i.e. number of bytes added to | 582 | * Compute tail offset i.e. number of bytes added to |
| 565 | * get the complete CAIF frame aligned. | 583 | * get the complete CAIF frame aligned. |
| 566 | */ | 584 | */ |
| 567 | epad = (pkt_len + spad) & spi_down_tail_align; | 585 | epad = PAD_POW2((pkt_len + spad), spi_down_tail_align); |
| 568 | src += epad; | 586 | src += epad; |
| 569 | } while ((src - buf) < len); | 587 | } while ((src - buf) < len); |
| 570 | 588 | ||
| @@ -625,11 +643,20 @@ int cfspi_spi_probe(struct platform_device *pdev) | |||
| 625 | cfspi->ndev = ndev; | 643 | cfspi->ndev = ndev; |
| 626 | cfspi->pdev = pdev; | 644 | cfspi->pdev = pdev; |
| 627 | 645 | ||
| 628 | /* Set flow info */ | 646 | /* Set flow info. */ |
| 629 | cfspi->flow_off_sent = 0; | 647 | cfspi->flow_off_sent = 0; |
| 630 | cfspi->qd_low_mark = LOW_WATER_MARK; | 648 | cfspi->qd_low_mark = LOW_WATER_MARK; |
| 631 | cfspi->qd_high_mark = HIGH_WATER_MARK; | 649 | cfspi->qd_high_mark = HIGH_WATER_MARK; |
| 632 | 650 | ||
| 651 | /* Set slave info. */ | ||
| 652 | if (!strncmp(cfspi_spi_driver.driver.name, "cfspi_sspi", 10)) { | ||
| 653 | cfspi->slave = true; | ||
| 654 | cfspi->slave_talked = false; | ||
| 655 | } else { | ||
| 656 | cfspi->slave = false; | ||
| 657 | cfspi->slave_talked = false; | ||
| 658 | } | ||
| 659 | |||
| 633 | /* Assign the SPI device. */ | 660 | /* Assign the SPI device. */ |
| 634 | cfspi->dev = dev; | 661 | cfspi->dev = dev; |
| 635 | /* Assign the device ifc to this SPI interface. */ | 662 | /* Assign the device ifc to this SPI interface. */ |
diff --git a/drivers/net/caif/caif_spi_slave.c b/drivers/net/caif/caif_spi_slave.c index 2111dbfea6fe..1b9943a4edab 100644 --- a/drivers/net/caif/caif_spi_slave.c +++ b/drivers/net/caif/caif_spi_slave.c | |||
| @@ -36,10 +36,15 @@ static inline int forward_to_spi_cmd(struct cfspi *cfspi) | |||
| 36 | #endif | 36 | #endif |
| 37 | 37 | ||
| 38 | int spi_frm_align = 2; | 38 | int spi_frm_align = 2; |
| 39 | int spi_up_head_align = 1; | 39 | |
| 40 | int spi_up_tail_align; | 40 | /* |
| 41 | int spi_down_head_align = 3; | 41 | * SPI padding options. |
| 42 | int spi_down_tail_align = 1; | 42 | * Warning: must be a base of 2 (& operation used) and can not be zero ! |
| 43 | */ | ||
| 44 | int spi_up_head_align = 1 << 1; | ||
| 45 | int spi_up_tail_align = 1 << 0; | ||
| 46 | int spi_down_head_align = 1 << 2; | ||
| 47 | int spi_down_tail_align = 1 << 1; | ||
| 43 | 48 | ||
| 44 | #ifdef CONFIG_DEBUG_FS | 49 | #ifdef CONFIG_DEBUG_FS |
| 45 | static inline void debugfs_store_prev(struct cfspi *cfspi) | 50 | static inline void debugfs_store_prev(struct cfspi *cfspi) |
diff --git a/include/net/caif/caif_spi.h b/include/net/caif/caif_spi.h index ce4570dff020..87c3d11b8e55 100644 --- a/include/net/caif/caif_spi.h +++ b/include/net/caif/caif_spi.h | |||
| @@ -121,6 +121,8 @@ struct cfspi { | |||
| 121 | wait_queue_head_t wait; | 121 | wait_queue_head_t wait; |
| 122 | spinlock_t lock; | 122 | spinlock_t lock; |
| 123 | bool flow_stop; | 123 | bool flow_stop; |
| 124 | bool slave; | ||
| 125 | bool slave_talked; | ||
| 124 | #ifdef CONFIG_DEBUG_FS | 126 | #ifdef CONFIG_DEBUG_FS |
| 125 | enum cfspi_state dbg_state; | 127 | enum cfspi_state dbg_state; |
| 126 | u16 pcmd; | 128 | u16 pcmd; |
