diff options
author | Frank Blaschka <frank.blaschka@de.ibm.com> | 2011-08-07 21:33:51 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-08-13 04:10:16 -0400 |
commit | 6fcd61f7bf5d56a83cbf26c14915138d1a64ca4e (patch) | |
tree | 5efef0bc1c28fb5e9707bcab7bad9b9cd405ef3d /net/iucv | |
parent | c69748d1c9b5c2db8daae7a1eb55c46932e4376a (diff) |
af_iucv: use loadable iucv interface
For future af_iucv extensions the module should be able to run in LPAR
mode too. For this we use the new dynamic loading iucv interface.
Signed-off-by: Frank Blaschka <frank.blaschka@de.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/iucv')
-rw-r--r-- | net/iucv/af_iucv.c | 119 |
1 files changed, 74 insertions, 45 deletions
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index e2013e434d03..2270e25a0298 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c | |||
@@ -42,6 +42,8 @@ static struct proto iucv_proto = { | |||
42 | .obj_size = sizeof(struct iucv_sock), | 42 | .obj_size = sizeof(struct iucv_sock), |
43 | }; | 43 | }; |
44 | 44 | ||
45 | static struct iucv_interface *pr_iucv; | ||
46 | |||
45 | /* special AF_IUCV IPRM messages */ | 47 | /* special AF_IUCV IPRM messages */ |
46 | static const u8 iprm_shutdown[8] = | 48 | static const u8 iprm_shutdown[8] = |
47 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; | 49 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; |
@@ -165,7 +167,7 @@ static int afiucv_pm_freeze(struct device *dev) | |||
165 | case IUCV_CLOSING: | 167 | case IUCV_CLOSING: |
166 | case IUCV_CONNECTED: | 168 | case IUCV_CONNECTED: |
167 | if (iucv->path) { | 169 | if (iucv->path) { |
168 | err = iucv_path_sever(iucv->path, NULL); | 170 | err = pr_iucv->path_sever(iucv->path, NULL); |
169 | iucv_path_free(iucv->path); | 171 | iucv_path_free(iucv->path); |
170 | iucv->path = NULL; | 172 | iucv->path = NULL; |
171 | } | 173 | } |
@@ -229,7 +231,7 @@ static const struct dev_pm_ops afiucv_pm_ops = { | |||
229 | static struct device_driver af_iucv_driver = { | 231 | static struct device_driver af_iucv_driver = { |
230 | .owner = THIS_MODULE, | 232 | .owner = THIS_MODULE, |
231 | .name = "afiucv", | 233 | .name = "afiucv", |
232 | .bus = &iucv_bus, | 234 | .bus = NULL, |
233 | .pm = &afiucv_pm_ops, | 235 | .pm = &afiucv_pm_ops, |
234 | }; | 236 | }; |
235 | 237 | ||
@@ -412,7 +414,7 @@ static void iucv_sock_close(struct sock *sk) | |||
412 | low_nmcpy(user_data, iucv->src_name); | 414 | low_nmcpy(user_data, iucv->src_name); |
413 | high_nmcpy(user_data, iucv->dst_name); | 415 | high_nmcpy(user_data, iucv->dst_name); |
414 | ASCEBC(user_data, sizeof(user_data)); | 416 | ASCEBC(user_data, sizeof(user_data)); |
415 | iucv_path_sever(iucv->path, user_data); | 417 | pr_iucv->path_sever(iucv->path, user_data); |
416 | iucv_path_free(iucv->path); | 418 | iucv_path_free(iucv->path); |
417 | iucv->path = NULL; | 419 | iucv->path = NULL; |
418 | } | 420 | } |
@@ -704,8 +706,9 @@ static int iucv_sock_connect(struct socket *sock, struct sockaddr *addr, | |||
704 | err = -ENOMEM; | 706 | err = -ENOMEM; |
705 | goto done; | 707 | goto done; |
706 | } | 708 | } |
707 | err = iucv_path_connect(iucv->path, &af_iucv_handler, | 709 | err = pr_iucv->path_connect(iucv->path, &af_iucv_handler, |
708 | sa->siucv_user_id, NULL, user_data, sk); | 710 | sa->siucv_user_id, NULL, user_data, |
711 | sk); | ||
709 | if (err) { | 712 | if (err) { |
710 | iucv_path_free(iucv->path); | 713 | iucv_path_free(iucv->path); |
711 | iucv->path = NULL; | 714 | iucv->path = NULL; |
@@ -738,7 +741,7 @@ static int iucv_sock_connect(struct socket *sock, struct sockaddr *addr, | |||
738 | } | 741 | } |
739 | 742 | ||
740 | if (err) { | 743 | if (err) { |
741 | iucv_path_sever(iucv->path, NULL); | 744 | pr_iucv->path_sever(iucv->path, NULL); |
742 | iucv_path_free(iucv->path); | 745 | iucv_path_free(iucv->path); |
743 | iucv->path = NULL; | 746 | iucv->path = NULL; |
744 | } | 747 | } |
@@ -871,7 +874,7 @@ static int iucv_send_iprm(struct iucv_path *path, struct iucv_message *msg, | |||
871 | 874 | ||
872 | memcpy(prmdata, (void *) skb->data, skb->len); | 875 | memcpy(prmdata, (void *) skb->data, skb->len); |
873 | prmdata[7] = 0xff - (u8) skb->len; | 876 | prmdata[7] = 0xff - (u8) skb->len; |
874 | return iucv_message_send(path, msg, IUCV_IPRMDATA, 0, | 877 | return pr_iucv->message_send(path, msg, IUCV_IPRMDATA, 0, |
875 | (void *) prmdata, 8); | 878 | (void *) prmdata, 8); |
876 | } | 879 | } |
877 | 880 | ||
@@ -999,13 +1002,13 @@ static int iucv_sock_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
999 | /* this error should never happen since the | 1002 | /* this error should never happen since the |
1000 | * IUCV_IPRMDATA path flag is set... sever path */ | 1003 | * IUCV_IPRMDATA path flag is set... sever path */ |
1001 | if (err == 0x15) { | 1004 | if (err == 0x15) { |
1002 | iucv_path_sever(iucv->path, NULL); | 1005 | pr_iucv->path_sever(iucv->path, NULL); |
1003 | skb_unlink(skb, &iucv->send_skb_q); | 1006 | skb_unlink(skb, &iucv->send_skb_q); |
1004 | err = -EPIPE; | 1007 | err = -EPIPE; |
1005 | goto fail; | 1008 | goto fail; |
1006 | } | 1009 | } |
1007 | } else | 1010 | } else |
1008 | err = iucv_message_send(iucv->path, &txmsg, 0, 0, | 1011 | err = pr_iucv->message_send(iucv->path, &txmsg, 0, 0, |
1009 | (void *) skb->data, skb->len); | 1012 | (void *) skb->data, skb->len); |
1010 | if (err) { | 1013 | if (err) { |
1011 | if (err == 3) { | 1014 | if (err == 3) { |
@@ -1095,8 +1098,9 @@ static void iucv_process_message(struct sock *sk, struct sk_buff *skb, | |||
1095 | skb->len = 0; | 1098 | skb->len = 0; |
1096 | } | 1099 | } |
1097 | } else { | 1100 | } else { |
1098 | rc = iucv_message_receive(path, msg, msg->flags & IUCV_IPRMDATA, | 1101 | rc = pr_iucv->message_receive(path, msg, |
1099 | skb->data, len, NULL); | 1102 | msg->flags & IUCV_IPRMDATA, |
1103 | skb->data, len, NULL); | ||
1100 | if (rc) { | 1104 | if (rc) { |
1101 | kfree_skb(skb); | 1105 | kfree_skb(skb); |
1102 | return; | 1106 | return; |
@@ -1110,7 +1114,7 @@ static void iucv_process_message(struct sock *sk, struct sk_buff *skb, | |||
1110 | kfree_skb(skb); | 1114 | kfree_skb(skb); |
1111 | skb = NULL; | 1115 | skb = NULL; |
1112 | if (rc) { | 1116 | if (rc) { |
1113 | iucv_path_sever(path, NULL); | 1117 | pr_iucv->path_sever(path, NULL); |
1114 | return; | 1118 | return; |
1115 | } | 1119 | } |
1116 | skb = skb_dequeue(&iucv_sk(sk)->backlog_skb_q); | 1120 | skb = skb_dequeue(&iucv_sk(sk)->backlog_skb_q); |
@@ -1327,8 +1331,8 @@ static int iucv_sock_shutdown(struct socket *sock, int how) | |||
1327 | if (how == SEND_SHUTDOWN || how == SHUTDOWN_MASK) { | 1331 | if (how == SEND_SHUTDOWN || how == SHUTDOWN_MASK) { |
1328 | txmsg.class = 0; | 1332 | txmsg.class = 0; |
1329 | txmsg.tag = 0; | 1333 | txmsg.tag = 0; |
1330 | err = iucv_message_send(iucv->path, &txmsg, IUCV_IPRMDATA, 0, | 1334 | err = pr_iucv->message_send(iucv->path, &txmsg, IUCV_IPRMDATA, |
1331 | (void *) iprm_shutdown, 8); | 1335 | 0, (void *) iprm_shutdown, 8); |
1332 | if (err) { | 1336 | if (err) { |
1333 | switch (err) { | 1337 | switch (err) { |
1334 | case 1: | 1338 | case 1: |
@@ -1345,7 +1349,7 @@ static int iucv_sock_shutdown(struct socket *sock, int how) | |||
1345 | } | 1349 | } |
1346 | 1350 | ||
1347 | if (how == RCV_SHUTDOWN || how == SHUTDOWN_MASK) { | 1351 | if (how == RCV_SHUTDOWN || how == SHUTDOWN_MASK) { |
1348 | err = iucv_path_quiesce(iucv_sk(sk)->path, NULL); | 1352 | err = pr_iucv->path_quiesce(iucv->path, NULL); |
1349 | if (err) | 1353 | if (err) |
1350 | err = -ENOTCONN; | 1354 | err = -ENOTCONN; |
1351 | 1355 | ||
@@ -1372,7 +1376,7 @@ static int iucv_sock_release(struct socket *sock) | |||
1372 | 1376 | ||
1373 | /* Unregister with IUCV base support */ | 1377 | /* Unregister with IUCV base support */ |
1374 | if (iucv_sk(sk)->path) { | 1378 | if (iucv_sk(sk)->path) { |
1375 | iucv_path_sever(iucv_sk(sk)->path, NULL); | 1379 | pr_iucv->path_sever(iucv_sk(sk)->path, NULL); |
1376 | iucv_path_free(iucv_sk(sk)->path); | 1380 | iucv_path_free(iucv_sk(sk)->path); |
1377 | iucv_sk(sk)->path = NULL; | 1381 | iucv_sk(sk)->path = NULL; |
1378 | } | 1382 | } |
@@ -1514,14 +1518,14 @@ static int iucv_callback_connreq(struct iucv_path *path, | |||
1514 | high_nmcpy(user_data, iucv->dst_name); | 1518 | high_nmcpy(user_data, iucv->dst_name); |
1515 | ASCEBC(user_data, sizeof(user_data)); | 1519 | ASCEBC(user_data, sizeof(user_data)); |
1516 | if (sk->sk_state != IUCV_LISTEN) { | 1520 | if (sk->sk_state != IUCV_LISTEN) { |
1517 | err = iucv_path_sever(path, user_data); | 1521 | err = pr_iucv->path_sever(path, user_data); |
1518 | iucv_path_free(path); | 1522 | iucv_path_free(path); |
1519 | goto fail; | 1523 | goto fail; |
1520 | } | 1524 | } |
1521 | 1525 | ||
1522 | /* Check for backlog size */ | 1526 | /* Check for backlog size */ |
1523 | if (sk_acceptq_is_full(sk)) { | 1527 | if (sk_acceptq_is_full(sk)) { |
1524 | err = iucv_path_sever(path, user_data); | 1528 | err = pr_iucv->path_sever(path, user_data); |
1525 | iucv_path_free(path); | 1529 | iucv_path_free(path); |
1526 | goto fail; | 1530 | goto fail; |
1527 | } | 1531 | } |
@@ -1529,7 +1533,7 @@ static int iucv_callback_connreq(struct iucv_path *path, | |||
1529 | /* Create the new socket */ | 1533 | /* Create the new socket */ |
1530 | nsk = iucv_sock_alloc(NULL, sk->sk_type, GFP_ATOMIC); | 1534 | nsk = iucv_sock_alloc(NULL, sk->sk_type, GFP_ATOMIC); |
1531 | if (!nsk) { | 1535 | if (!nsk) { |
1532 | err = iucv_path_sever(path, user_data); | 1536 | err = pr_iucv->path_sever(path, user_data); |
1533 | iucv_path_free(path); | 1537 | iucv_path_free(path); |
1534 | goto fail; | 1538 | goto fail; |
1535 | } | 1539 | } |
@@ -1553,9 +1557,9 @@ static int iucv_callback_connreq(struct iucv_path *path, | |||
1553 | /* set message limit for path based on msglimit of accepting socket */ | 1557 | /* set message limit for path based on msglimit of accepting socket */ |
1554 | niucv->msglimit = iucv->msglimit; | 1558 | niucv->msglimit = iucv->msglimit; |
1555 | path->msglim = iucv->msglimit; | 1559 | path->msglim = iucv->msglimit; |
1556 | err = iucv_path_accept(path, &af_iucv_handler, nuser_data, nsk); | 1560 | err = pr_iucv->path_accept(path, &af_iucv_handler, nuser_data, nsk); |
1557 | if (err) { | 1561 | if (err) { |
1558 | err = iucv_path_sever(path, user_data); | 1562 | err = pr_iucv->path_sever(path, user_data); |
1559 | iucv_path_free(path); | 1563 | iucv_path_free(path); |
1560 | iucv_sock_kill(nsk); | 1564 | iucv_sock_kill(nsk); |
1561 | goto fail; | 1565 | goto fail; |
@@ -1589,7 +1593,7 @@ static void iucv_callback_rx(struct iucv_path *path, struct iucv_message *msg) | |||
1589 | int len; | 1593 | int len; |
1590 | 1594 | ||
1591 | if (sk->sk_shutdown & RCV_SHUTDOWN) { | 1595 | if (sk->sk_shutdown & RCV_SHUTDOWN) { |
1592 | iucv_message_reject(path, msg); | 1596 | pr_iucv->message_reject(path, msg); |
1593 | return; | 1597 | return; |
1594 | } | 1598 | } |
1595 | 1599 | ||
@@ -1718,6 +1722,41 @@ static const struct net_proto_family iucv_sock_family_ops = { | |||
1718 | .create = iucv_sock_create, | 1722 | .create = iucv_sock_create, |
1719 | }; | 1723 | }; |
1720 | 1724 | ||
1725 | static int __init afiucv_iucv_init(void) | ||
1726 | { | ||
1727 | int err; | ||
1728 | |||
1729 | err = pr_iucv->iucv_register(&af_iucv_handler, 0); | ||
1730 | if (err) | ||
1731 | goto out; | ||
1732 | /* establish dummy device */ | ||
1733 | af_iucv_driver.bus = pr_iucv->bus; | ||
1734 | err = driver_register(&af_iucv_driver); | ||
1735 | if (err) | ||
1736 | goto out_iucv; | ||
1737 | af_iucv_dev = kzalloc(sizeof(struct device), GFP_KERNEL); | ||
1738 | if (!af_iucv_dev) { | ||
1739 | err = -ENOMEM; | ||
1740 | goto out_driver; | ||
1741 | } | ||
1742 | dev_set_name(af_iucv_dev, "af_iucv"); | ||
1743 | af_iucv_dev->bus = pr_iucv->bus; | ||
1744 | af_iucv_dev->parent = pr_iucv->root; | ||
1745 | af_iucv_dev->release = (void (*)(struct device *))kfree; | ||
1746 | af_iucv_dev->driver = &af_iucv_driver; | ||
1747 | err = device_register(af_iucv_dev); | ||
1748 | if (err) | ||
1749 | goto out_driver; | ||
1750 | return 0; | ||
1751 | |||
1752 | out_driver: | ||
1753 | driver_unregister(&af_iucv_driver); | ||
1754 | out_iucv: | ||
1755 | pr_iucv->iucv_unregister(&af_iucv_handler, 0); | ||
1756 | out: | ||
1757 | return err; | ||
1758 | } | ||
1759 | |||
1721 | static int __init afiucv_init(void) | 1760 | static int __init afiucv_init(void) |
1722 | { | 1761 | { |
1723 | int err; | 1762 | int err; |
@@ -1735,44 +1774,33 @@ static int __init afiucv_init(void) | |||
1735 | goto out; | 1774 | goto out; |
1736 | } | 1775 | } |
1737 | 1776 | ||
1738 | err = iucv_register(&af_iucv_handler, 0); | 1777 | pr_iucv = try_then_request_module(symbol_get(iucv_if), "iucv"); |
1739 | if (err) | 1778 | if (!pr_iucv) { |
1779 | printk(KERN_WARNING "iucv_if lookup failed\n"); | ||
1780 | err = -EPROTONOSUPPORT; | ||
1740 | goto out; | 1781 | goto out; |
1782 | } | ||
1783 | |||
1741 | err = proto_register(&iucv_proto, 0); | 1784 | err = proto_register(&iucv_proto, 0); |
1742 | if (err) | 1785 | if (err) |
1743 | goto out_iucv; | 1786 | goto out; |
1744 | err = sock_register(&iucv_sock_family_ops); | 1787 | err = sock_register(&iucv_sock_family_ops); |
1745 | if (err) | 1788 | if (err) |
1746 | goto out_proto; | 1789 | goto out_proto; |
1747 | /* establish dummy device */ | 1790 | |
1748 | err = driver_register(&af_iucv_driver); | 1791 | err = afiucv_iucv_init(); |
1749 | if (err) | 1792 | if (err) |
1750 | goto out_sock; | 1793 | goto out_sock; |
1751 | af_iucv_dev = kzalloc(sizeof(struct device), GFP_KERNEL); | ||
1752 | if (!af_iucv_dev) { | ||
1753 | err = -ENOMEM; | ||
1754 | goto out_driver; | ||
1755 | } | ||
1756 | dev_set_name(af_iucv_dev, "af_iucv"); | ||
1757 | af_iucv_dev->bus = &iucv_bus; | ||
1758 | af_iucv_dev->parent = iucv_root; | ||
1759 | af_iucv_dev->release = (void (*)(struct device *))kfree; | ||
1760 | af_iucv_dev->driver = &af_iucv_driver; | ||
1761 | err = device_register(af_iucv_dev); | ||
1762 | if (err) | ||
1763 | goto out_driver; | ||
1764 | 1794 | ||
1765 | return 0; | 1795 | return 0; |
1766 | 1796 | ||
1767 | out_driver: | ||
1768 | driver_unregister(&af_iucv_driver); | ||
1769 | out_sock: | 1797 | out_sock: |
1770 | sock_unregister(PF_IUCV); | 1798 | sock_unregister(PF_IUCV); |
1771 | out_proto: | 1799 | out_proto: |
1772 | proto_unregister(&iucv_proto); | 1800 | proto_unregister(&iucv_proto); |
1773 | out_iucv: | ||
1774 | iucv_unregister(&af_iucv_handler, 0); | ||
1775 | out: | 1801 | out: |
1802 | if (pr_iucv) | ||
1803 | symbol_put(iucv_if); | ||
1776 | return err; | 1804 | return err; |
1777 | } | 1805 | } |
1778 | 1806 | ||
@@ -1780,9 +1808,10 @@ static void __exit afiucv_exit(void) | |||
1780 | { | 1808 | { |
1781 | device_unregister(af_iucv_dev); | 1809 | device_unregister(af_iucv_dev); |
1782 | driver_unregister(&af_iucv_driver); | 1810 | driver_unregister(&af_iucv_driver); |
1811 | pr_iucv->iucv_unregister(&af_iucv_handler, 0); | ||
1812 | symbol_put(iucv_if); | ||
1783 | sock_unregister(PF_IUCV); | 1813 | sock_unregister(PF_IUCV); |
1784 | proto_unregister(&iucv_proto); | 1814 | proto_unregister(&iucv_proto); |
1785 | iucv_unregister(&af_iucv_handler, 0); | ||
1786 | } | 1815 | } |
1787 | 1816 | ||
1788 | module_init(afiucv_init); | 1817 | module_init(afiucv_init); |