aboutsummaryrefslogtreecommitdiff
path: root/drivers/staging/fwserial/fwserial.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/fwserial/fwserial.c')
-rw-r--r--drivers/staging/fwserial/fwserial.c372
1 files changed, 153 insertions, 219 deletions
diff --git a/drivers/staging/fwserial/fwserial.c b/drivers/staging/fwserial/fwserial.c
index 5a6fb44f38a..384758b11e3 100644
--- a/drivers/staging/fwserial/fwserial.c
+++ b/drivers/staging/fwserial/fwserial.c
@@ -12,12 +12,10 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/device.h>
@@ -101,13 +99,16 @@ struct fwtty_transaction {
};
#define to_device(a, b) (a->b)
-#define fwtty_err(p, s, v...) dev_err(to_device(p, device), s, ##v)
-#define fwtty_info(p, s, v...) dev_info(to_device(p, device), s, ##v)
-#define fwtty_notice(p, s, v...) dev_notice(to_device(p, device), s, ##v)
-#define fwtty_dbg(p, s, v...) \
- dev_dbg(to_device(p, device), "%s: " s, __func__, ##v)
-#define fwtty_err_ratelimited(p, s, v...) \
- dev_err_ratelimited(to_device(p, device), s, ##v)
+#define fwtty_err(p, fmt, ...) \
+ dev_err(to_device(p, device), fmt, ##__VA_ARGS__)
+#define fwtty_info(p, fmt, ...) \
+ dev_info(to_device(p, device), fmt, ##__VA_ARGS__)
+#define fwtty_notice(p, fmt, ...) \
+ dev_notice(to_device(p, device), fmt, ##__VA_ARGS__)
+#define fwtty_dbg(p, fmt, ...) \
+ dev_dbg(to_device(p, device), "%s: " fmt, __func__, ##__VA_ARGS__)
+#define fwtty_err_ratelimited(p, fmt, ...) \
+ dev_err_ratelimited(to_device(p, device), fmt, ##__VA_ARGS__)
#ifdef DEBUG
static inline void debug_short_write(struct fwtty_port *port, int c, int n)
@@ -118,7 +119,7 @@ static inline void debug_short_write(struct fwtty_port *port, int c, int n)
spin_lock_bh(&port->lock);
avail = dma_fifo_avail(&port->tx_fifo);
spin_unlock_bh(&port->lock);
- fwtty_dbg(port, "short write: avail:%d req:%d wrote:%d",
+ fwtty_dbg(port, "short write: avail:%d req:%d wrote:%d\n",
avail, c, n);
}
}
@@ -131,14 +132,14 @@ static struct fwtty_peer *__fwserial_peer_by_node_id(struct fw_card *card,
#ifdef FWTTY_PROFILING
-static void profile_fifo_avail(struct fwtty_port *port, unsigned *stat)
+static void fwtty_profile_fifo(struct fwtty_port *port, unsigned *stat)
{
spin_lock_bh(&port->lock);
- profile_size_distrib(stat, dma_fifo_avail(&port->tx_fifo));
+ fwtty_profile_data(stat, dma_fifo_avail(&port->tx_fifo));
spin_unlock_bh(&port->lock);
}
-static void dump_profile(struct seq_file *m, struct stats *stats)
+static void fwtty_dump_profile(struct seq_file *m, struct stats *stats)
{
/* for each stat, print sum of 0 to 2^k, then individually */
int k = 4;
@@ -178,8 +179,8 @@ static void dump_profile(struct seq_file *m, struct stats *stats)
}
#else
-#define profile_fifo_avail(port, stat)
-#define dump_profile(m, stats)
+#define fwtty_profile_fifo(port, stat)
+#define fwtty_dump_profile(m, stats)
#endif
/*
@@ -197,22 +198,22 @@ static void fwtty_log_tx_error(struct fwtty_port *port, int rcode)
{
switch (rcode) {
case RCODE_SEND_ERROR:
- fwtty_err_ratelimited(port, "card busy");
+ fwtty_err_ratelimited(port, "card busy\n");
break;
case RCODE_ADDRESS_ERROR:
- fwtty_err_ratelimited(port, "bad unit addr or write length");
+ fwtty_err_ratelimited(port, "bad unit addr or write length\n");
break;
case RCODE_DATA_ERROR:
- fwtty_err_ratelimited(port, "failed rx");
+ fwtty_err_ratelimited(port, "failed rx\n");
break;
case RCODE_NO_ACK:
- fwtty_err_ratelimited(port, "missing ack");
+ fwtty_err_ratelimited(port, "missing ack\n");
break;
case RCODE_BUSY:
- fwtty_err_ratelimited(port, "remote busy");
+ fwtty_err_ratelimited(port, "remote busy\n");
break;
default:
- fwtty_err_ratelimited(port, "failed tx: %d", rcode);
+ fwtty_err_ratelimited(port, "failed tx: %d\n", rcode);
}
}
@@ -287,7 +288,7 @@ static void __fwtty_restart_tx(struct fwtty_port *port)
schedule_delayed_work(&port->drain, 0);
avail = dma_fifo_avail(&port->tx_fifo);
- fwtty_dbg(port, "fifo len: %d avail: %d", len, avail);
+ fwtty_dbg(port, "fifo len: %d avail: %d\n", len, avail);
}
static void fwtty_restart_tx(struct fwtty_port *port)
@@ -323,7 +324,7 @@ static void fwtty_update_port_status(struct fwtty_port *port, unsigned status)
if (delta & TIOCM_CTS)
++port->icount.cts;
- fwtty_dbg(port, "status: %x delta: %x", status, delta);
+ fwtty_dbg(port, "status: %x delta: %x\n", status, delta);
if (delta & TIOCM_CAR) {
tty = tty_port_tty_get(&port->port);
@@ -451,16 +452,27 @@ static int fwtty_write_port_status(struct fwtty_port *port)
return err;
}
-static void __fwtty_throttle(struct fwtty_port *port, struct tty_struct *tty)
+static void fwtty_throttle_port(struct fwtty_port *port)
{
+ struct tty_struct *tty;
unsigned old;
+ tty = tty_port_tty_get(&port->port);
+ if (!tty)
+ return;
+
+ spin_lock_bh(&port->lock);
+
old = port->mctrl;
port->mctrl |= OOB_RX_THROTTLE;
if (C_CRTSCTS(tty))
port->mctrl &= ~TIOCM_RTS;
if (~old & OOB_RX_THROTTLE)
__fwtty_write_port_status(port);
+
+ spin_unlock_bh(&port->lock);
+
+ tty_kref_put(tty);
}
/**
@@ -509,12 +521,12 @@ static void fwtty_emit_breaks(struct work_struct *work)
n = (elapsed * port->cps) / HZ + 1;
port->break_last = now;
- fwtty_dbg(port, "sending %d brks", n);
+ fwtty_dbg(port, "sending %d brks\n", n);
while (n) {
t = min(n, 16);
c = tty_insert_flip_string_fixed_flag(&port->port, buf,
- TTY_BREAK, t);
+ TTY_BREAK, t);
n -= c;
brk += c;
if (c < t)
@@ -527,80 +539,14 @@ static void fwtty_emit_breaks(struct work_struct *work)
port->icount.brk += brk;
}
-static void fwtty_pushrx(struct work_struct *work)
-{
- struct fwtty_port *port = to_port(work, push);
- struct tty_struct *tty;
- struct buffered_rx *buf, *next;
- int n, c = 0;
-
- spin_lock_bh(&port->lock);
- list_for_each_entry_safe(buf, next, &port->buf_list, list) {
- n = tty_insert_flip_string_fixed_flag(&port->port, buf->data,
- TTY_NORMAL, buf->n);
- c += n;
- port->buffered -= n;
- if (n < buf->n) {
- if (n > 0) {
- memmove(buf->data, buf->data + n, buf->n - n);
- buf->n -= n;
- }
- tty = tty_port_tty_get(&port->port);
- if (tty) {
- __fwtty_throttle(port, tty);
- tty_kref_put(tty);
- }
- break;
- } else {
- list_del(&buf->list);
- kfree(buf);
- }
- }
- if (c > 0)
- tty_flip_buffer_push(&port->port);
-
- if (list_empty(&port->buf_list))
- clear_bit(BUFFERING_RX, &port->flags);
- spin_unlock_bh(&port->lock);
-}
-
-static int fwtty_buffer_rx(struct fwtty_port *port, unsigned char *d, size_t n)
-{
- struct buffered_rx *buf;
- size_t size = (n + sizeof(struct buffered_rx) + 0xFF) & ~0xFF;
-
- if (port->buffered + n > HIGH_WATERMARK) {
- fwtty_err_ratelimited(port, "overflowed rx buffer: buffered: %d new: %zu wtrmk: %d",
- port->buffered, n, HIGH_WATERMARK);
- return 0;
- }
- buf = kmalloc(size, GFP_ATOMIC);
- if (!buf)
- return 0;
- INIT_LIST_HEAD(&buf->list);
- buf->n = n;
- memcpy(buf->data, d, n);
-
- spin_lock_bh(&port->lock);
- list_add_tail(&buf->list, &port->buf_list);
- port->buffered += n;
- if (port->buffered > port->stats.watermark)
- port->stats.watermark = port->buffered;
- set_bit(BUFFERING_RX, &port->flags);
- spin_unlock_bh(&port->lock);
-
- return n;
-}
-
static int fwtty_rx(struct fwtty_port *port, unsigned char *data, size_t len)
{
- struct tty_struct *tty;
int c, n = len;
unsigned lsr;
int err = 0;
- fwtty_dbg(port, "%d", n);
- profile_size_distrib(port->stats.reads, n);
+ fwtty_dbg(port, "%d\n", n);
+ fwtty_profile_data(port->stats.reads, n);
if (port->write_only) {
n = 0;
@@ -631,31 +577,24 @@ static int fwtty_rx(struct fwtty_port *port, unsigned char *data, size_t len)
goto out;
}
- if (!test_bit(BUFFERING_RX, &port->flags)) {
- c = tty_insert_flip_string_fixed_flag(&port->port, data,
- TTY_NORMAL, n);
- if (c > 0)
- tty_flip_buffer_push(&port->port);
- n -= c;
-
- if (n) {
- /* start buffering and throttling */
- n -= fwtty_buffer_rx(port, &data[c], n);
-
- tty = tty_port_tty_get(&port->port);
- if (tty) {
- spin_lock_bh(&port->lock);
- __fwtty_throttle(port, tty);
- spin_unlock_bh(&port->lock);
- tty_kref_put(tty);
- }
- }
- } else
- n -= fwtty_buffer_rx(port, data, n);
+ c = tty_insert_flip_string_fixed_flag(&port->port, data, TTY_NORMAL, n);
+ if (c > 0)
+ tty_flip_buffer_push(&port->port);
+ n -= c;
if (n) {
port->overrun = true;
err = -EIO;
+ fwtty_err_ratelimited(port, "flip buffer overrun\n");
+
+ } else {
+ /* throttle the sender if remaining flip buffer space has
+ * reached high watermark to avoid losing data which may be
+ * in-flight. Since the AR request context is 32k, that much
+ * data may have _already_ been acked.
+ */
+ if (tty_buffer_space_avail(&port->port) < HIGH_WATERMARK)
+ fwtty_throttle_port(port);
}
out:
@@ -689,15 +628,15 @@ static void fwtty_port_handler(struct fw_card *card,
rcu_read_unlock();
if (!peer || peer != rcu_access_pointer(port->peer)) {
rcode = RCODE_ADDRESS_ERROR;
- fwtty_err_ratelimited(port, "ignoring unauthenticated data");
+ fwtty_err_ratelimited(port, "ignoring unauthenticated data\n");
goto respond;
}
switch (tcode) {
case TCODE_WRITE_QUADLET_REQUEST:
- if (addr != port->rx_handler.offset || len != 4)
+ if (addr != port->rx_handler.offset || len != 4) {
rcode = RCODE_ADDRESS_ERROR;
- else {
+ } else {
fwtty_update_port_status(port, *(unsigned *)data);
rcode = RCODE_COMPLETE;
}
@@ -744,10 +683,9 @@ static void fwtty_tx_complete(struct fw_card *card, int rcode,
struct fwtty_transaction *txn)
{
struct fwtty_port *port = txn->port;
- struct tty_struct *tty;
int len;
- fwtty_dbg(port, "rcode: %d", rcode);
+ fwtty_dbg(port, "rcode: %d\n", rcode);
switch (rcode) {
case RCODE_COMPLETE:
@@ -769,13 +707,8 @@ static void fwtty_tx_complete(struct fw_card *card, int rcode,
port->stats.dropped += txn->dma_pended.len;
}
- if (len < WAKEUP_CHARS) {
- tty = tty_port_tty_get(&port->port);
- if (tty) {
- tty_wakeup(tty);
- tty_kref_put(tty);
- }
- }
+ if (len < WAKEUP_CHARS)
+ tty_port_tty_wakeup(&port->port);
}
static int fwtty_tx(struct fwtty_port *port, bool drain)
@@ -804,7 +737,7 @@ static int fwtty_tx(struct fwtty_port *port, bool drain)
/* try to write as many dma transactions out as possible */
n = -EAGAIN;
while (!tty->stopped && !tty->hw_stopped &&
- !test_bit(STOP_TX, &port->flags)) {
+ !test_bit(STOP_TX, &port->flags)) {
txn = kmem_cache_alloc(fwtty_txn_cache, GFP_ATOMIC);
if (!txn) {
n = -ENOMEM;
@@ -815,22 +748,23 @@ static int fwtty_tx(struct fwtty_port *port, bool drain)
n = dma_fifo_out_pend(&port->tx_fifo, &txn->dma_pended);
spin_unlock_bh(&port->lock);
- fwtty_dbg(port, "out: %u rem: %d", txn->dma_pended.len, n);
+ fwtty_dbg(port, "out: %u rem: %d\n", txn->dma_pended.len, n);
if (n < 0) {
kmem_cache_free(fwtty_txn_cache, txn);
- if (n == -EAGAIN)
+ if (n == -EAGAIN) {
++port->stats.tx_stall;
- else if (n == -ENODATA)
- profile_size_distrib(port->stats.txns, 0);
- else {
+ } else if (n == -ENODATA) {
+ fwtty_profile_data(port->stats.txns, 0);
+ } else {
++port->stats.fifo_errs;
- fwtty_err_ratelimited(port, "fifo err: %d", n);
+ fwtty_err_ratelimited(port, "fifo err: %d\n",
+ n);
}
break;
}
- profile_size_distrib(port->stats.txns, txn->dma_pended.len);
+ fwtty_profile_data(port->stats.txns, txn->dma_pended.len);
fwtty_send_txn_async(peer, txn, TCODE_WRITE_BLOCK_REQUEST,
peer->fifo_addr, txn->dma_pended.data,
@@ -883,7 +817,7 @@ static void fwtty_write_xchar(struct fwtty_port *port, char ch)
++port->stats.xchars;
- fwtty_dbg(port, "%02x", ch);
+ fwtty_dbg(port, "%02x\n", ch);
rcu_read_lock();
peer = rcu_dereference(port->peer);
@@ -946,7 +880,7 @@ static void fwserial_destroy(struct kref *kref)
for (j = 0; j < num_ports; ++i, ++j) {
port_table_corrupt |= port_table[i] != ports[j];
WARN_ONCE(port_table_corrupt, "port_table[%d]: %p != ports[%d]: %p",
- i, port_table[i], j, ports[j]);
+ i, port_table[i], j, ports[j]);
port_table[i] = NULL;
}
@@ -970,7 +904,7 @@ static void fwtty_port_dtr_rts(struct tty_port *tty_port, int on)
{
struct fwtty_port *port = to_port(tty_port, port);
- fwtty_dbg(port, "on/off: %d", on);
+ fwtty_dbg(port, "on/off: %d\n", on);
spin_lock_bh(&port->lock);
/* Don't change carrier state if this is a console */
@@ -998,7 +932,7 @@ static int fwtty_port_carrier_raised(struct tty_port *tty_port)
rc = (port->mstatus & TIOCM_CAR);
- fwtty_dbg(port, "%d", rc);
+ fwtty_dbg(port, "%d\n", rc);
return rc;
}
@@ -1101,20 +1035,13 @@ static int fwtty_port_activate(struct tty_port *tty_port,
static void fwtty_port_shutdown(struct tty_port *tty_port)
{
struct fwtty_port *port = to_port(tty_port, port);
- struct buffered_rx *buf, *next;
/* TODO: cancel outstanding transactions */
cancel_delayed_work_sync(&port->emit_breaks);
cancel_delayed_work_sync(&port->drain);
- cancel_work_sync(&port->push);
spin_lock_bh(&port->lock);
- list_for_each_entry_safe(buf, next, &port->buf_list, list) {
- list_del(&buf->list);
- kfree(buf);
- }
- port->buffered = 0;
port->flags = 0;
port->break_ctl = 0;
port->overrun = 0;
@@ -1183,8 +1110,8 @@ static int fwtty_write(struct tty_struct *tty, const unsigned char *buf, int c)
struct fwtty_port *port = tty->driver_data;
int n, len;
- fwtty_dbg(port, "%d", c);
- profile_size_distrib(port->stats.writes, c);
+ fwtty_dbg(port, "%d\n", c);
+ fwtty_profile_data(port->stats.writes, c);
spin_lock_bh(&port->lock);
n = dma_fifo_in(&port->tx_fifo, buf, c);
@@ -1210,7 +1137,7 @@ static int fwtty_write_room(struct tty_struct *tty)
n = dma_fifo_avail(&port->tx_fifo);
spin_unlock_bh(&port->lock);
- fwtty_dbg(port, "%d", n);
+ fwtty_dbg(port, "%d\n", n);
return n;
}
@@ -1224,7 +1151,7 @@ static int fwtty_chars_in_buffer(struct tty_struct *tty)
n = dma_fifo_level(&port->tx_fifo);
spin_unlock_bh(&port->lock);
- fwtty_dbg(port, "%d", n);
+ fwtty_dbg(port, "%d\n", n);
return n;
}
@@ -1233,7 +1160,7 @@ static void fwtty_send_xchar(struct tty_struct *tty, char ch)
{
struct fwtty_port *port = tty->driver_data;
- fwtty_dbg(port, "%02x", ch);
+ fwtty_dbg(port, "%02x\n", ch);
fwtty_write_xchar(port, ch);
}
@@ -1260,11 +1187,9 @@ static void fwtty_unthrottle(struct tty_struct *tty)
{
struct fwtty_port *port = tty->driver_data;
- fwtty_dbg(port, "CRTSCTS: %d", (C_CRTSCTS(tty) != 0));
-
- profile_fifo_avail(port, port->stats.unthrottle);
+ fwtty_dbg(port, "CRTSCTS: %d\n", (C_CRTSCTS(tty) != 0));
- schedule_work(&port->push);
+ fwtty_profile_fifo(port, port->stats.unthrottle);
spin_lock_bh(&port->lock);
port->mctrl &= ~OOB_RX_THROTTLE;
@@ -1328,15 +1253,16 @@ static int set_serial_info(struct fwtty_port *port,
return -EFAULT;
if (tmp.irq != 0 || tmp.port != 0 || tmp.custom_divisor != 0 ||
- tmp.baud_base != 400000000)
+ tmp.baud_base != 400000000)
return -EPERM;
if (!capable(CAP_SYS_ADMIN)) {
if (((tmp.flags & ~ASYNC_USR_MASK) !=
(port->port.flags & ~ASYNC_USR_MASK)))
return -EPERM;
- } else
+ } else {
port->port.close_delay = tmp.close_delay * HZ / 100;
+ }
return 0;
}
@@ -1379,9 +1305,9 @@ static void fwtty_set_termios(struct tty_struct *tty, struct ktermios *old)
spin_lock_bh(&port->lock);
baud = set_termios(port, tty);
- if ((baud == 0) && (old->c_cflag & CBAUD))
+ if ((baud == 0) && (old->c_cflag & CBAUD)) {
port->mctrl &= ~(TIOCM_DTR | TIOCM_RTS);
- else if ((baud != 0) && !(old->c_cflag & CBAUD)) {
+ } else if ((baud != 0) && !(old->c_cflag & CBAUD)) {
if (C_CRTSCTS(tty) || !test_bit(TTY_THROTTLED, &tty->flags))
port->mctrl |= TIOCM_DTR | TIOCM_RTS;
else
@@ -1415,7 +1341,7 @@ static int fwtty_break_ctl(struct tty_struct *tty, int state)
struct fwtty_port *port = tty->driver_data;
long ret;
- fwtty_dbg(port, "%d", state);
+ fwtty_dbg(port, "%d\n", state);
if (state == -1) {
set_bit(STOP_TX, &port->flags);
@@ -1452,7 +1378,7 @@ static int fwtty_tiocmget(struct tty_struct *tty)
tiocm = (port->mctrl & MCTRL_MASK) | (port->mstatus & ~MCTRL_MASK);
spin_unlock_bh(&port->lock);
- fwtty_dbg(port, "%x", tiocm);
+ fwtty_dbg(port, "%x\n", tiocm);
return tiocm;
}
@@ -1461,7 +1387,7 @@ static int fwtty_tiocmset(struct tty_struct *tty, unsigned set, unsigned clear)
{
struct fwtty_port *port = tty->driver_data;
- fwtty_dbg(port, "set: %x clear: %x", set, clear);
+ fwtty_dbg(port, "set: %x clear: %x\n", set, clear);
/* TODO: simulate loopback if TIOCM_LOOP set */
@@ -1523,15 +1449,14 @@ static void fwtty_debugfs_show_port(struct seq_file *m, struct fwtty_port *port)
seq_printf(m, " dr:%d st:%d err:%d lost:%d", stats.dropped,
stats.tx_stall, stats.fifo_errs, stats.lost);
- seq_printf(m, " pkts:%d thr:%d wtrmk:%d", stats.sent, stats.throttled,
- stats.watermark);
+ seq_printf(m, " pkts:%d thr:%d", stats.sent, stats.throttled);
if (port->port.console) {
- seq_printf(m, "\n ");
+ seq_puts(m, "\n ");
(*port->fwcon_ops->proc_show)(m, port->con_data);
}
- dump_profile(m, &port->stats);
+ fwtty_dump_profile(m, &port->stats);
}
static void fwtty_debugfs_show_peer(struct seq_file *m, struct fwtty_peer *peer)
@@ -1559,7 +1484,7 @@ static int fwtty_proc_show(struct seq_file *m, void *v)
if (capable(CAP_SYS_ADMIN))
fwtty_proc_show_port(m, port);
fwtty_port_put(port);
- seq_printf(m, "\n");
+ seq_puts(m, "\n");
}
return 0;
}
@@ -1577,7 +1502,7 @@ static int fwtty_debugfs_stats_show(struct seq_file *m, void *v)
fwtty_proc_show_port(m, port);
fwtty_debugfs_show_port(m, port);
fwtty_port_put(port);
- seq_printf(m, "\n");
+ seq_puts(m, "\n");
}
}
return 0;
@@ -1781,7 +1706,7 @@ static void fwserial_virt_plug_complete(struct fwtty_peer *peer,
if (port->port.console && port->fwcon_ops->notify != NULL)
(*port->fwcon_ops->notify)(FWCON_NOTIFY_ATTACH, port->con_data);
- fwtty_info(&peer->unit, "peer (guid:%016llx) connected on %s",
+ fwtty_info(&peer->unit, "peer (guid:%016llx) connected on %s\n",
(unsigned long long)peer->guid, dev_name(port->device));
}
@@ -1803,10 +1728,11 @@ static inline int fwserial_send_mgmt_sync(struct fwtty_peer *peer,
pkt, be16_to_cpu(pkt->hdr.len));
if (rcode == RCODE_BUSY || rcode == RCODE_SEND_ERROR ||
rcode == RCODE_GENERATION) {
- fwtty_dbg(&peer->unit, "mgmt write error: %d", rcode);
+ fwtty_dbg(&peer->unit, "mgmt write error: %d\n", rcode);
continue;
- } else
+ } else {
break;
+ }
} while (--tries > 0);
return rcode;
}
@@ -1881,7 +1807,7 @@ static void fwserial_release_port(struct fwtty_port *port, bool reset)
port->max_payload = link_speed_to_max_payload(SCODE_100);
dma_fifo_change_tx_limit(&port->tx_fifo, port->max_payload);
- rcu_assign_pointer(port->peer, NULL);
+ RCU_INIT_POINTER(port->peer, NULL);
spin_unlock_bh(&port->lock);
if (port->port.console && port->fwcon_ops->notify != NULL)
@@ -1890,7 +1816,7 @@ static void fwserial_release_port(struct fwtty_port *port, bool reset)
static void fwserial_plug_timeout(unsigned long data)
{
- struct fwtty_peer *peer = (struct fwtty_peer *) data;
+ struct fwtty_peer *peer = (struct fwtty_peer *)data;
struct fwtty_port *port;
spin_lock_bh(&peer->lock);
@@ -1924,7 +1850,7 @@ static int fwserial_connect_peer(struct fwtty_peer *peer)
port = fwserial_find_port(peer);
if (!port) {
- fwtty_err(&peer->unit, "avail ports in use");
+ fwtty_err(&peer->unit, "avail ports in use\n");
err = -EBUSY;
goto free_pkt;
}
@@ -2062,7 +1988,7 @@ static struct fwtty_peer *__fwserial_peer_by_node_id(struct fw_card *card,
* has created its remote unit device before this driver has
* been probed for any unit devices...
*/
- fwtty_err(card, "unknown card (guid %016llx)",
+ fwtty_err(card, "unknown card (guid %016llx)\n",
(unsigned long long) card->guid);
return NULL;
}
@@ -2090,8 +2016,8 @@ static void __dump_peer_list(struct fw_card *card)
list_for_each_entry_rcu(peer, &serial->peer_list, list) {
int g = peer->generation;
smp_rmb();
- fwtty_dbg(card, "peer(%d:%x) guid: %016llx\n", g,
- peer->node_id, (unsigned long long) peer->guid);
+ fwtty_dbg(card, "peer(%d:%x) guid: %016llx\n",
+ g, peer->node_id, (unsigned long long) peer->guid);
}
}
#else
@@ -2108,6 +2034,13 @@ static void fwserial_auto_connect(struct work_struct *work)
schedule_delayed_work(&peer->connect, CONNECT_RETRY_DELAY);
}
+static void fwserial_peer_workfn(struct work_struct *work)
+{
+ struct fwtty_peer *peer = to_peer(work, work);
+
+ peer->workfn(work);
+}
+
/**
* fwserial_add_peer - add a newly probed 'serial' unit device as a 'peer'
* @serial: aggregate representing the specific fw_card to add the peer to
@@ -2172,14 +2105,14 @@ static int fwserial_add_peer(struct fw_serial *serial, struct fw_unit *unit)
peer->port = NULL;
init_timer(&peer->timer);
- INIT_WORK(&peer->work, NULL);
+ INIT_WORK(&peer->work, fwserial_peer_workfn);
INIT_DELAYED_WORK(&peer->connect, fwserial_auto_connect);
/* associate peer with specific fw_card */
peer->serial = serial;
list_add_rcu(&peer->list, &serial->peer_list);
- fwtty_info(&peer->unit, "peer added (guid:%016llx)",
+ fwtty_info(&peer->unit, "peer added (guid:%016llx)\n",
(unsigned long long)peer->guid);
/* identify the local unit & virt cable to loopback port */
@@ -2242,7 +2175,7 @@ static void fwserial_remove_peer(struct fwtty_peer *peer)
list_del_rcu(&peer->list);
- fwtty_info(&peer->unit, "peer removed (guid:%016llx)",
+ fwtty_info(&peer->unit, "peer removed (guid:%016llx)\n",
(unsigned long long)peer->guid);
spin_unlock_bh(&peer->lock);
@@ -2297,18 +2230,17 @@ static int fwserial_create(struct fw_unit *unit)
port->index = FWTTY_INVALID_INDEX;
port->port.ops = &fwtty_port_ops;
port->serial = serial;
+ tty_buffer_set_limit(&port->port, 128 * 1024);
spin_lock_init(&port->lock);
INIT_DELAYED_WORK(&port->drain, fwtty_drain_tx);
INIT_DELAYED_WORK(&port->emit_breaks, fwtty_emit_breaks);
INIT_WORK(&port->hangup, fwtty_do_hangup);
- INIT_WORK(&port->push, fwtty_pushrx);
- INIT_LIST_HEAD(&port->buf_list);
init_waitqueue_head(&port->wait_tx);
port->max_payload = link_speed_to_max_payload(SCODE_100);
dma_fifo_init(&port->tx_fifo);
- rcu_assign_pointer(port->peer, NULL);
+ RCU_INIT_POINTER(port->peer, NULL);
serial->ports[i] = port;
/* get unique bus addr region for port's status & recv fifo */
@@ -2330,7 +2262,7 @@ static int fwserial_create(struct fw_unit *unit)
err = fwtty_ports_add(serial);
if (err) {
- fwtty_err(&unit, "no space in port table");
+ fwtty_err(&unit, "no space in port table\n");
goto free_ports;
}
@@ -2341,7 +2273,8 @@ static int fwserial_create(struct fw_unit *unit)
card->device);
if (IS_ERR(tty_dev)) {
err = PTR_ERR(tty_dev);
- fwtty_err(&unit, "register tty device error (%d)", err);
+ fwtty_err(&unit, "register tty device error (%d)\n",
+ err);
goto unregister_ttys;
}
@@ -2358,7 +2291,8 @@ static int fwserial_create(struct fw_unit *unit)
card->device);
if (IS_ERR(loop_dev)) {
err = PTR_ERR(loop_dev);
- fwtty_err(&unit, "create loop device failed (%d)", err);
+ fwtty_err(&unit, "create loop device failed (%d)\n",
+ err);
goto unregister_ttys;
}
serial->ports[j]->device = loop_dev;
@@ -2378,21 +2312,22 @@ static int fwserial_create(struct fw_unit *unit)
list_add_rcu(&serial->list, &fwserial_list);
- fwtty_notice(&unit, "TTY over FireWire on device %s (guid %016llx)",
+ fwtty_notice(&unit, "TTY over FireWire on device %s (guid %016llx)\n",
dev_name(card->device), (unsigned long long) card->guid);
err = fwserial_add_peer(serial, unit);
if (!err)
return 0;
- fwtty_err(&unit, "unable to add peer unit device (%d)", err);
+ fwtty_err(&unit, "unable to add peer unit device (%d)\n", err);
/* fall-through to error processing */
debugfs_remove_recursive(serial->debugfs);
list_del_rcu(&serial->list);
if (create_loop_dev)
- tty_unregister_device(fwloop_driver, loop_idx(serial->ports[j]));
+ tty_unregister_device(fwloop_driver,
+ loop_idx(serial->ports[j]));
unregister_ttys:
for (--j; j >= 0; --j)
tty_unregister_device(fwtty_driver, serial->ports[j]->index);
@@ -2444,9 +2379,9 @@ free_ports:
* last peer for a given fw_card triggering the destruction of the same
* fw_serial for the same fw_card.
*/
-static int fwserial_probe(struct device *dev)
+static int fwserial_probe(struct fw_unit *unit,
+ const struct ieee1394_device_id *id)
{
- struct fw_unit *unit = fw_unit(dev);
struct fw_serial *serial;
int err;
@@ -2468,9 +2403,9 @@ static int fwserial_probe(struct device *dev)
* specific fw_card). If this is the last peer being removed, then trigger
* the destruction of the underlying TTYs.
*/
-static int fwserial_remove(struct device *dev)
+static void fwserial_remove(struct fw_unit *unit)
{
- struct fwtty_peer *peer = dev_get_drvdata(dev);
+ struct fwtty_peer *peer = dev_get_drvdata(&unit->device);
struct fw_serial *serial = peer->serial;
int i;
@@ -2490,8 +2425,6 @@ static int fwserial_remove(struct device *dev)
kref_put(&serial->kref, fwserial_destroy);
}
mutex_unlock(&fwserial_list_mutex);
-
- return 0;
}
/**
@@ -2536,10 +2469,10 @@ static struct fw_driver fwserial_driver = {
.owner = THIS_MODULE,
.name = KBUILD_MODNAME,
.bus = &fw_bus_type,
- .probe = fwserial_probe,
- .remove = fwserial_remove,
},
+ .probe = fwserial_probe,
.update = fwserial_update,
+ .remove = fwserial_remove,
.id_table = fwserial_id_table,
};
@@ -2627,7 +2560,7 @@ static void fwserial_handle_plug_req(struct work_struct *work)
switch (peer->state) {
case FWPS_NOT_ATTACHED:
if (!port) {
- fwtty_err(&peer->unit, "no more ports avail");
+ fwtty_err(&peer->unit, "no more ports avail\n");
fill_plug_rsp_nack(pkt);
} else {
peer->port = port;
@@ -2669,7 +2602,7 @@ static void fwserial_handle_plug_req(struct work_struct *work)
fwtty_write_port_status(tmp);
spin_lock_bh(&peer->lock);
} else {
- fwtty_err(&peer->unit, "PLUG_RSP error (%d)", rcode);
+ fwtty_err(&peer->unit, "PLUG_RSP error (%d)\n", rcode);
port = peer_revert_state(peer);
}
}
@@ -2721,7 +2654,8 @@ static void fwserial_handle_unplug_req(struct work_struct *work)
spin_lock_bh(&peer->lock);
if (peer->state == FWPS_UNPLUG_RESPONDING) {
if (rcode != RCODE_COMPLETE)
- fwtty_err(&peer->unit, "UNPLUG_RSP error (%d)", rcode);
+ fwtty_err(&peer->unit, "UNPLUG_RSP error (%d)\n",
+ rcode);
port = peer_revert_state(peer);
}
cleanup:
@@ -2756,24 +2690,24 @@ static int fwserial_parse_mgmt_write(struct fwtty_peer *peer,
* already removed from the bus -- and the removal was
* processed before we rec'd this transaction
*/
- fwtty_err(&peer->unit, "peer already removed");
+ fwtty_err(&peer->unit, "peer already removed\n");
spin_unlock_bh(&peer->lock);
return RCODE_ADDRESS_ERROR;
}
rcode = RCODE_COMPLETE;
- fwtty_dbg(&peer->unit, "mgmt: hdr.code: %04hx", pkt->hdr.code);
+ fwtty_dbg(&peer->unit, "mgmt: hdr.code: %04hx\n", pkt->hdr.code);
switch (be16_to_cpu(pkt->hdr.code) & FWSC_CODE_MASK) {
case FWSC_VIRT_CABLE_PLUG:
if (work_pending(&peer->work)) {
- fwtty_err(&peer->unit, "plug req: busy");
+ fwtty_err(&peer->unit, "plug req: busy\n");
rcode = RCODE_CONFLICT_ERROR;
} else {
peer->work_params.plug_req = pkt->plug_req;
- PREPARE_WORK(&peer->work, fwserial_handle_plug_req);
+ peer->workfn = fwserial_handle_plug_req;
queue_work(system_unbound_wq, &peer->work);
}
break;
@@ -2783,7 +2717,7 @@ static int fwserial_parse_mgmt_write(struct fwtty_peer *peer,
rcode = RCODE_CONFLICT_ERROR;
} else if (be16_to_cpu(pkt->hdr.code) & FWSC_RSP_NACK) {
- fwtty_notice(&peer->unit, "NACK plug rsp");
+ fwtty_notice(&peer->unit, "NACK plug rsp\n");
port = peer_revert_state(peer);
} else {
@@ -2799,27 +2733,27 @@ static int fwserial_parse_mgmt_write(struct fwtty_peer *peer,
case FWSC_VIRT_CABLE_UNPLUG:
if (work_pending(&peer->work)) {
- fwtty_err(&peer->unit, "unplug req: busy");
+ fwtty_err(&peer->unit, "unplug req: busy\n");
rcode = RCODE_CONFLICT_ERROR;
} else {
- PREPARE_WORK(&peer->work, fwserial_handle_unplug_req);
+ peer->workfn = fwserial_handle_unplug_req;
queue_work(system_unbound_wq, &peer->work);
}
break;
case FWSC_VIRT_CABLE_UNPLUG_RSP:
- if (peer->state != FWPS_UNPLUG_PENDING)
+ if (peer->state != FWPS_UNPLUG_PENDING) {
rcode = RCODE_CONFLICT_ERROR;
- else {
+ } else {
if (be16_to_cpu(pkt->hdr.code) & FWSC_RSP_NACK)
- fwtty_notice(&peer->unit, "NACK unplug?");
+ fwtty_notice(&peer->unit, "NACK unplug?\n");
port = peer_revert_state(peer);
reset = true;
}
break;
default:
- fwtty_err(&peer->unit, "unknown mgmt code %d",
+ fwtty_err(&peer->unit, "unknown mgmt code %d\n",
be16_to_cpu(pkt->hdr.code));
rcode = RCODE_DATA_ERROR;
}
@@ -2853,7 +2787,7 @@ static void fwserial_mgmt_handler(struct fw_card *card,
rcu_read_lock();
peer = __fwserial_peer_by_node_id(card, generation, source);
if (!peer) {
- fwtty_dbg(card, "peer(%d:%x) not found", generation, source);
+ fwtty_dbg(card, "peer(%d:%x) not found\n", generation, source);
__dump_peer_list(card);
rcode = RCODE_CONFLICT_ERROR;
@@ -2903,7 +2837,7 @@ static int __init fwserial_init(void)
err = tty_register_driver(fwtty_driver);
if (err) {
- driver_err("register tty driver failed (%d)", err);
+ pr_err("register tty driver failed (%d)\n", err);
goto put_tty;
}
@@ -2928,7 +2862,7 @@ static int __init fwserial_init(void)
err = tty_register_driver(fwloop_driver);
if (err) {
- driver_err("register loop driver failed (%d)", err);
+ pr_err("register loop driver failed (%d)\n", err);
goto put_loop;
}
}
@@ -2954,7 +2888,7 @@ static int __init fwserial_init(void)
err = fw_core_add_address_handler(&fwserial_mgmt_addr_handler,
&fwserial_mgmt_addr_region);
if (err) {
- driver_err("add management handler failed (%d)", err);
+ pr_err("add management handler failed (%d)\n", err);
goto destroy_cache;
}
@@ -2962,13 +2896,13 @@ static int __init fwserial_init(void)
FW_UNIT_ADDRESS(fwserial_mgmt_addr_handler.offset);
err = fw_core_add_descriptor(&fwserial_unit_directory);
if (err) {
- driver_err("add unit descriptor failed (%d)", err);
+ pr_err("add unit descriptor failed (%d)\n", err);
goto remove_handler;
}
err = driver_register(&fwserial_driver.driver);
if (err) {
- driver_err("register fwserial driver failed (%d)", err);
+ pr_err("register fwserial driver failed (%d)\n", err);
goto remove_descriptor;
}