.. | .. |
---|
19 | 19 | |
---|
20 | 20 | #include "fwserial.h" |
---|
21 | 21 | |
---|
22 | | -#define be32_to_u64(hi, lo) ((u64)be32_to_cpu(hi) << 32 | be32_to_cpu(lo)) |
---|
| 22 | +inline u64 be32_to_u64(__be32 hi, __be32 lo) |
---|
| 23 | +{ |
---|
| 24 | + return ((u64)be32_to_cpu(hi) << 32 | be32_to_cpu(lo)); |
---|
| 25 | +} |
---|
23 | 26 | |
---|
24 | 27 | #define LINUX_VENDOR_ID 0xd00d1eU /* same id used in card root directory */ |
---|
25 | 28 | #define FWSERIAL_VERSION 0x00e81cU /* must be unique within LINUX_VENDOR_ID */ |
---|
.. | .. |
---|
463 | 466 | * fwtty_do_hangup - wait for ldisc to deliver all pending rx; only then hangup |
---|
464 | 467 | * |
---|
465 | 468 | * When the remote has finished tx, and all in-flight rx has been received and |
---|
466 | | - * and pushed to the flip buffer, the remote may close its device. This will |
---|
| 469 | + * pushed to the flip buffer, the remote may close its device. This will |
---|
467 | 470 | * drop DTR on the remote which will drop carrier here. Typically, the tty is |
---|
468 | 471 | * hung up when carrier is dropped or lost. |
---|
469 | 472 | * |
---|
.. | .. |
---|
1209 | 1212 | check_msr_delta(port, mask, &prev)); |
---|
1210 | 1213 | } |
---|
1211 | 1214 | |
---|
1212 | | -static int get_serial_info(struct fwtty_port *port, |
---|
1213 | | - struct serial_struct __user *info) |
---|
| 1215 | +static int get_serial_info(struct tty_struct *tty, |
---|
| 1216 | + struct serial_struct *ss) |
---|
1214 | 1217 | { |
---|
1215 | | - struct serial_struct tmp; |
---|
| 1218 | + struct fwtty_port *port = tty->driver_data; |
---|
1216 | 1219 | |
---|
1217 | | - memset(&tmp, 0, sizeof(tmp)); |
---|
| 1220 | + mutex_lock(&port->port.mutex); |
---|
| 1221 | + ss->line = port->index; |
---|
| 1222 | + ss->baud_base = 400000000; |
---|
| 1223 | + ss->close_delay = jiffies_to_msecs(port->port.close_delay) / 10; |
---|
| 1224 | + ss->closing_wait = 3000; |
---|
| 1225 | + mutex_unlock(&port->port.mutex); |
---|
1218 | 1226 | |
---|
1219 | | - tmp.type = PORT_UNKNOWN; |
---|
1220 | | - tmp.line = port->port.tty->index; |
---|
1221 | | - tmp.flags = port->port.flags; |
---|
1222 | | - tmp.xmit_fifo_size = FWTTY_PORT_TXFIFO_LEN; |
---|
1223 | | - tmp.baud_base = 400000000; |
---|
1224 | | - tmp.close_delay = port->port.close_delay; |
---|
1225 | | - |
---|
1226 | | - return (copy_to_user(info, &tmp, sizeof(*info))) ? -EFAULT : 0; |
---|
| 1227 | + return 0; |
---|
1227 | 1228 | } |
---|
1228 | 1229 | |
---|
1229 | | -static int set_serial_info(struct fwtty_port *port, |
---|
1230 | | - struct serial_struct __user *info) |
---|
| 1230 | +static int set_serial_info(struct tty_struct *tty, |
---|
| 1231 | + struct serial_struct *ss) |
---|
1231 | 1232 | { |
---|
1232 | | - struct serial_struct tmp; |
---|
| 1233 | + struct fwtty_port *port = tty->driver_data; |
---|
| 1234 | + unsigned int cdelay; |
---|
1233 | 1235 | |
---|
1234 | | - if (copy_from_user(&tmp, info, sizeof(tmp))) |
---|
1235 | | - return -EFAULT; |
---|
| 1236 | + cdelay = msecs_to_jiffies(ss->close_delay * 10); |
---|
1236 | 1237 | |
---|
1237 | | - if (tmp.irq != 0 || tmp.port != 0 || tmp.custom_divisor != 0 || |
---|
1238 | | - tmp.baud_base != 400000000) |
---|
1239 | | - return -EPERM; |
---|
1240 | | - |
---|
| 1238 | + mutex_lock(&port->port.mutex); |
---|
1241 | 1239 | if (!capable(CAP_SYS_ADMIN)) { |
---|
1242 | | - if (((tmp.flags & ~ASYNC_USR_MASK) != |
---|
1243 | | - (port->port.flags & ~ASYNC_USR_MASK))) |
---|
| 1240 | + if (cdelay != port->port.close_delay || |
---|
| 1241 | + ((ss->flags & ~ASYNC_USR_MASK) != |
---|
| 1242 | + (port->port.flags & ~ASYNC_USR_MASK))) { |
---|
| 1243 | + mutex_unlock(&port->port.mutex); |
---|
1244 | 1244 | return -EPERM; |
---|
1245 | | - } else { |
---|
1246 | | - port->port.close_delay = tmp.close_delay * HZ / 100; |
---|
| 1245 | + } |
---|
1247 | 1246 | } |
---|
| 1247 | + port->port.close_delay = cdelay; |
---|
| 1248 | + mutex_unlock(&port->port.mutex); |
---|
1248 | 1249 | |
---|
1249 | 1250 | return 0; |
---|
1250 | 1251 | } |
---|
.. | .. |
---|
1256 | 1257 | int err; |
---|
1257 | 1258 | |
---|
1258 | 1259 | switch (cmd) { |
---|
1259 | | - case TIOCGSERIAL: |
---|
1260 | | - mutex_lock(&port->port.mutex); |
---|
1261 | | - err = get_serial_info(port, (void __user *)arg); |
---|
1262 | | - mutex_unlock(&port->port.mutex); |
---|
1263 | | - break; |
---|
1264 | | - |
---|
1265 | | - case TIOCSSERIAL: |
---|
1266 | | - mutex_lock(&port->port.mutex); |
---|
1267 | | - err = set_serial_info(port, (void __user *)arg); |
---|
1268 | | - mutex_unlock(&port->port.mutex); |
---|
1269 | | - break; |
---|
1270 | | - |
---|
1271 | 1260 | case TIOCMIWAIT: |
---|
1272 | 1261 | err = wait_msr_change(port, arg); |
---|
1273 | 1262 | break; |
---|
.. | .. |
---|
1472 | 1461 | return 0; |
---|
1473 | 1462 | } |
---|
1474 | 1463 | |
---|
1475 | | -static int fwtty_debugfs_stats_show(struct seq_file *m, void *v) |
---|
| 1464 | +static int fwtty_stats_show(struct seq_file *m, void *v) |
---|
1476 | 1465 | { |
---|
1477 | 1466 | struct fw_serial *serial = m->private; |
---|
1478 | 1467 | struct fwtty_port *port; |
---|
.. | .. |
---|
1490 | 1479 | } |
---|
1491 | 1480 | return 0; |
---|
1492 | 1481 | } |
---|
| 1482 | +DEFINE_SHOW_ATTRIBUTE(fwtty_stats); |
---|
1493 | 1483 | |
---|
1494 | | -static int fwtty_debugfs_peers_show(struct seq_file *m, void *v) |
---|
| 1484 | +static int fwtty_peers_show(struct seq_file *m, void *v) |
---|
1495 | 1485 | { |
---|
1496 | 1486 | struct fw_serial *serial = m->private; |
---|
1497 | 1487 | struct fwtty_peer *peer; |
---|
.. | .. |
---|
1505 | 1495 | rcu_read_unlock(); |
---|
1506 | 1496 | return 0; |
---|
1507 | 1497 | } |
---|
1508 | | - |
---|
1509 | | -static int fwtty_stats_open(struct inode *inode, struct file *fp) |
---|
1510 | | -{ |
---|
1511 | | - return single_open(fp, fwtty_debugfs_stats_show, inode->i_private); |
---|
1512 | | -} |
---|
1513 | | - |
---|
1514 | | -static int fwtty_peers_open(struct inode *inode, struct file *fp) |
---|
1515 | | -{ |
---|
1516 | | - return single_open(fp, fwtty_debugfs_peers_show, inode->i_private); |
---|
1517 | | -} |
---|
1518 | | - |
---|
1519 | | -static const struct file_operations fwtty_stats_fops = { |
---|
1520 | | - .owner = THIS_MODULE, |
---|
1521 | | - .open = fwtty_stats_open, |
---|
1522 | | - .read = seq_read, |
---|
1523 | | - .llseek = seq_lseek, |
---|
1524 | | - .release = single_release, |
---|
1525 | | -}; |
---|
1526 | | - |
---|
1527 | | -static const struct file_operations fwtty_peers_fops = { |
---|
1528 | | - .owner = THIS_MODULE, |
---|
1529 | | - .open = fwtty_peers_open, |
---|
1530 | | - .read = seq_read, |
---|
1531 | | - .llseek = seq_lseek, |
---|
1532 | | - .release = single_release, |
---|
1533 | | -}; |
---|
| 1498 | +DEFINE_SHOW_ATTRIBUTE(fwtty_peers); |
---|
1534 | 1499 | |
---|
1535 | 1500 | static const struct tty_port_operations fwtty_port_ops = { |
---|
1536 | 1501 | .dtr_rts = fwtty_port_dtr_rts, |
---|
.. | .. |
---|
1557 | 1522 | .tiocmget = fwtty_tiocmget, |
---|
1558 | 1523 | .tiocmset = fwtty_tiocmset, |
---|
1559 | 1524 | .get_icount = fwtty_get_icount, |
---|
| 1525 | + .set_serial = set_serial_info, |
---|
| 1526 | + .get_serial = get_serial_info, |
---|
1560 | 1527 | .proc_show = fwtty_proc_show, |
---|
1561 | 1528 | }; |
---|
1562 | 1529 | |
---|
.. | .. |
---|
1578 | 1545 | .tiocmget = fwtty_tiocmget, |
---|
1579 | 1546 | .tiocmset = fwtty_tiocmset, |
---|
1580 | 1547 | .get_icount = fwtty_get_icount, |
---|
| 1548 | + .set_serial = set_serial_info, |
---|
| 1549 | + .get_serial = get_serial_info, |
---|
1581 | 1550 | }; |
---|
1582 | 1551 | |
---|
1583 | 1552 | static inline int mgmt_pkt_expected_len(__be16 code) |
---|