246 #include <linux/netdevice.h>
247 #include <linux/slab.h>
248 #include <linux/export.h>
252 #define D_SUBMODULE tx
293 #define TAIL_FULL ((void *)~(unsigned long)NULL)
438 size_t room, tail_room, needed_size;
443 if (room < needed_size) {
444 d_printf(2, dev,
"fifo push %zu/%zu: no space\n",
449 tail_room = __i2400m_tx_tail_room(i2400m);
450 if (!try_head && tail_room < needed_size) {
464 if (room - tail_room >= needed_size) {
465 d_printf(2, dev,
"fifo push %zu/%zu: tail full\n",
469 d_printf(2, dev,
"fifo push %zu/%zu: no head space\n",
475 d_printf(2, dev,
"fifo push %zu/%zu: at @%zu\n", size, padding,
505 void i2400m_tx_skip_tail(
struct i2400m *i2400m)
507 struct device *dev = i2400m_dev(i2400m);
509 size_t tail_room = __i2400m_tx_tail_room(i2400m);
513 BUG_ON(tail_room <
sizeof(*msg));
515 d_printf(2, dev,
"skip tail: skipping %zu bytes @%zu\n",
517 i2400m->
tx_in += tail_room;
535 unsigned i2400m_tx_fits(
struct i2400m *i2400m)
561 void i2400m_tx_new(
struct i2400m *i2400m)
563 struct device *dev = i2400m_dev(i2400m);
565 bool try_head =
false;
581 i2400m_tx_skip_tail(i2400m);
582 d_printf(2, dev,
"new TX message: tail full, trying head\n");
590 d_printf(2, dev,
"new TX message: %p @%zu\n",
591 tx_msg, (
void *) tx_msg - i2400m->
tx_buf);
613 void i2400m_tx_close(
struct i2400m *i2400m)
615 struct device *dev = i2400m_dev(i2400m);
643 hdr_size =
sizeof(*tx_msg)
647 tx_msg_moved = (
void *) tx_msg + tx_msg->
offset;
648 memmove(tx_msg_moved, tx_msg, hdr_size);
655 padding = aligned_size - tx_msg_moved->
size;
657 pad_buf = i2400m_tx_fifo_push(i2400m, padding, 0, 0);
664 "SW BUG! Possible data leakage from memory the "
665 "device should not read for padding - "
666 "size %lu aligned_size %zu tx_buf %p in "
668 (
unsigned long) tx_msg_moved->
size,
676 if (tx_msg != tx_msg_moved)
719 struct device *dev = i2400m_dev(i2400m);
723 bool try_head =
false;
727 d_fnstart(3, dev,
"(i2400m %p skb %p [%zu bytes] pt %u)\n",
728 i2400m, buf, buf_len, pl_type);
730 d_printf(5, dev,
"padded_len %zd buf_len %zd\n", padded_len, buf_len);
742 i2400m_tx_new(i2400m);
743 else if (
unlikely(!i2400m_tx_fits(i2400m)
744 || (is_singleton && i2400m->
tx_msg->num_pls != 0))) {
745 d_printf(2, dev,
"closing TX message (fits %u singleton "
746 "%u num_pls %u)\n", i2400m_tx_fits(i2400m),
747 is_singleton, i2400m->
tx_msg->num_pls);
748 i2400m_tx_close(i2400m);
749 i2400m_tx_new(i2400m);
760 d_printf(2, dev,
"TX: message too big, going new\n");
761 i2400m_tx_close(i2400m);
762 i2400m_tx_new(i2400m);
768 ptr = i2400m_tx_fifo_push(i2400m, padded_len,
771 d_printf(2, dev,
"pl append: tail full\n");
772 i2400m_tx_close(i2400m);
773 i2400m_tx_skip_tail(i2400m);
776 }
else if (ptr ==
NULL) {
778 d_printf(2, dev,
"pl append: all full\n");
782 memcpy(ptr, buf, buf_len);
783 memset(ptr + buf_len, 0
xad, padded_len - buf_len);
784 i2400m_pld_set(&tx_msg->
pld[num_pls], buf_len, pl_type);
785 d_printf(3, dev,
"pld 0x%08x (type 0x%1x len 0x%04zx\n",
789 tx_msg->
size += padded_len;
790 d_printf(2, dev,
"TX: appended %zu b (up to %u b) pl #%u\n",
791 padded_len, tx_msg->
size, num_pls+1);
793 "TX: appended hdr @%zu %zu b pl #%u @%zu %zu/%zu b\n",
794 (
void *)tx_msg - i2400m->
tx_buf, (
size_t)tx_msg->
size,
795 num_pls+1, ptr - i2400m->
tx_buf, buf_len, padded_len);
798 i2400m_tx_close(i2400m);
801 spin_unlock_irqrestore(&i2400m->
tx_lock, flags);
806 d_fnend(3, dev,
"(i2400m %p skb %p [%zu bytes] pt %u) = %d\n",
807 i2400m, buf, buf_len, pl_type, result);
842 struct device *dev = i2400m_dev(i2400m);
844 unsigned long flags, pls;
846 d_fnstart(3, dev,
"(i2400m %p bus_size %p)\n", i2400m, bus_size);
856 d_printf(2, dev,
"TX: FIFO empty: resetting\n");
861 d_printf(2, dev,
"TX: skip: msg @%zu (%zu b)\n",
869 if (tx_msg == i2400m->
tx_msg) {
871 "TX: FIFO empty: open msg w/o payloads @%zu\n",
872 (
void *) tx_msg - i2400m->
tx_buf);
877 "TX: skip msg w/o payloads @%zu (%zu b)\n",
878 (
void *) tx_msg - i2400m->
tx_buf,
879 (
size_t) tx_msg->
size);
884 if (tx_msg == i2400m->
tx_msg)
885 i2400m_tx_close(i2400m);
888 tx_msg_moved = (
void *) tx_msg + tx_msg->
offset;
890 *bus_size = tx_msg_moved->
size;
891 d_printf(2, dev,
"TX: pid %d msg hdr at @%zu offset +@%zu "
892 "size %zu bus_size %zu\n",
903 if (pls < i2400m->tx_pl_min)
907 if (*bus_size < i2400m->tx_size_min)
912 spin_unlock_irqrestore(&i2400m->
tx_lock, flags);
913 d_fnstart(3, dev,
"(i2400m %p bus_size %p [%zu]) = %p\n",
914 i2400m, bus_size, *bus_size, tx_msg_moved);
936 struct device *dev = i2400m_dev(i2400m);
938 d_fnstart(3, dev,
"(i2400m %p)\n", i2400m);
951 spin_unlock_irqrestore(&i2400m->
tx_lock, flags);
952 d_fnend(3, dev,
"(i2400m %p) = void\n", i2400m);
977 if (tx_buf ==
NULL) {
994 spin_unlock_irqrestore(&i2400m->
tx_lock, flags);
1008 unsigned long flags;
1012 spin_unlock_irqrestore(&i2400m->
tx_lock, flags);