Commit 6fcd61f7bf5d56a83cbf26c14915138d1a64ca4e
Committed by
David S. Miller
1 parent
c69748d1c9
Exists in
master
and in
38 other branches
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>
Showing 1 changed file with 74 additions and 45 deletions Side-by-side Diff
net/iucv/af_iucv.c
... | ... | @@ -42,6 +42,8 @@ |
42 | 42 | .obj_size = sizeof(struct iucv_sock), |
43 | 43 | }; |
44 | 44 | |
45 | +static struct iucv_interface *pr_iucv; | |
46 | + | |
45 | 47 | /* special AF_IUCV IPRM messages */ |
46 | 48 | static const u8 iprm_shutdown[8] = |
47 | 49 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; |
... | ... | @@ -165,7 +167,7 @@ |
165 | 167 | case IUCV_CLOSING: |
166 | 168 | case IUCV_CONNECTED: |
167 | 169 | if (iucv->path) { |
168 | - err = iucv_path_sever(iucv->path, NULL); | |
170 | + err = pr_iucv->path_sever(iucv->path, NULL); | |
169 | 171 | iucv_path_free(iucv->path); |
170 | 172 | iucv->path = NULL; |
171 | 173 | } |
... | ... | @@ -229,7 +231,7 @@ |
229 | 231 | static struct device_driver af_iucv_driver = { |
230 | 232 | .owner = THIS_MODULE, |
231 | 233 | .name = "afiucv", |
232 | - .bus = &iucv_bus, | |
234 | + .bus = NULL, | |
233 | 235 | .pm = &afiucv_pm_ops, |
234 | 236 | }; |
235 | 237 | |
... | ... | @@ -412,7 +414,7 @@ |
412 | 414 | low_nmcpy(user_data, iucv->src_name); |
413 | 415 | high_nmcpy(user_data, iucv->dst_name); |
414 | 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 | 418 | iucv_path_free(iucv->path); |
417 | 419 | iucv->path = NULL; |
418 | 420 | } |
... | ... | @@ -704,8 +706,9 @@ |
704 | 706 | err = -ENOMEM; |
705 | 707 | goto done; |
706 | 708 | } |
707 | - err = iucv_path_connect(iucv->path, &af_iucv_handler, | |
708 | - sa->siucv_user_id, NULL, user_data, sk); | |
709 | + err = pr_iucv->path_connect(iucv->path, &af_iucv_handler, | |
710 | + sa->siucv_user_id, NULL, user_data, | |
711 | + sk); | |
709 | 712 | if (err) { |
710 | 713 | iucv_path_free(iucv->path); |
711 | 714 | iucv->path = NULL; |
... | ... | @@ -738,7 +741,7 @@ |
738 | 741 | } |
739 | 742 | |
740 | 743 | if (err) { |
741 | - iucv_path_sever(iucv->path, NULL); | |
744 | + pr_iucv->path_sever(iucv->path, NULL); | |
742 | 745 | iucv_path_free(iucv->path); |
743 | 746 | iucv->path = NULL; |
744 | 747 | } |
... | ... | @@ -871,7 +874,7 @@ |
871 | 874 | |
872 | 875 | memcpy(prmdata, (void *) skb->data, skb->len); |
873 | 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 | 878 | (void *) prmdata, 8); |
876 | 879 | } |
877 | 880 | |
878 | 881 | |
... | ... | @@ -999,13 +1002,13 @@ |
999 | 1002 | /* this error should never happen since the |
1000 | 1003 | * IUCV_IPRMDATA path flag is set... sever path */ |
1001 | 1004 | if (err == 0x15) { |
1002 | - iucv_path_sever(iucv->path, NULL); | |
1005 | + pr_iucv->path_sever(iucv->path, NULL); | |
1003 | 1006 | skb_unlink(skb, &iucv->send_skb_q); |
1004 | 1007 | err = -EPIPE; |
1005 | 1008 | goto fail; |
1006 | 1009 | } |
1007 | 1010 | } else |
1008 | - err = iucv_message_send(iucv->path, &txmsg, 0, 0, | |
1011 | + err = pr_iucv->message_send(iucv->path, &txmsg, 0, 0, | |
1009 | 1012 | (void *) skb->data, skb->len); |
1010 | 1013 | if (err) { |
1011 | 1014 | if (err == 3) { |
... | ... | @@ -1095,8 +1098,9 @@ |
1095 | 1098 | skb->len = 0; |
1096 | 1099 | } |
1097 | 1100 | } else { |
1098 | - rc = iucv_message_receive(path, msg, msg->flags & IUCV_IPRMDATA, | |
1099 | - skb->data, len, NULL); | |
1101 | + rc = pr_iucv->message_receive(path, msg, | |
1102 | + msg->flags & IUCV_IPRMDATA, | |
1103 | + skb->data, len, NULL); | |
1100 | 1104 | if (rc) { |
1101 | 1105 | kfree_skb(skb); |
1102 | 1106 | return; |
... | ... | @@ -1110,7 +1114,7 @@ |
1110 | 1114 | kfree_skb(skb); |
1111 | 1115 | skb = NULL; |
1112 | 1116 | if (rc) { |
1113 | - iucv_path_sever(path, NULL); | |
1117 | + pr_iucv->path_sever(path, NULL); | |
1114 | 1118 | return; |
1115 | 1119 | } |
1116 | 1120 | skb = skb_dequeue(&iucv_sk(sk)->backlog_skb_q); |
... | ... | @@ -1327,8 +1331,8 @@ |
1327 | 1331 | if (how == SEND_SHUTDOWN || how == SHUTDOWN_MASK) { |
1328 | 1332 | txmsg.class = 0; |
1329 | 1333 | txmsg.tag = 0; |
1330 | - err = iucv_message_send(iucv->path, &txmsg, IUCV_IPRMDATA, 0, | |
1331 | - (void *) iprm_shutdown, 8); | |
1334 | + err = pr_iucv->message_send(iucv->path, &txmsg, IUCV_IPRMDATA, | |
1335 | + 0, (void *) iprm_shutdown, 8); | |
1332 | 1336 | if (err) { |
1333 | 1337 | switch (err) { |
1334 | 1338 | case 1: |
... | ... | @@ -1345,7 +1349,7 @@ |
1345 | 1349 | } |
1346 | 1350 | |
1347 | 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 | 1353 | if (err) |
1350 | 1354 | err = -ENOTCONN; |
1351 | 1355 | |
... | ... | @@ -1372,7 +1376,7 @@ |
1372 | 1376 | |
1373 | 1377 | /* Unregister with IUCV base support */ |
1374 | 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 | 1380 | iucv_path_free(iucv_sk(sk)->path); |
1377 | 1381 | iucv_sk(sk)->path = NULL; |
1378 | 1382 | } |
1379 | 1383 | |
... | ... | @@ -1514,14 +1518,14 @@ |
1514 | 1518 | high_nmcpy(user_data, iucv->dst_name); |
1515 | 1519 | ASCEBC(user_data, sizeof(user_data)); |
1516 | 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 | 1522 | iucv_path_free(path); |
1519 | 1523 | goto fail; |
1520 | 1524 | } |
1521 | 1525 | |
1522 | 1526 | /* Check for backlog size */ |
1523 | 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 | 1529 | iucv_path_free(path); |
1526 | 1530 | goto fail; |
1527 | 1531 | } |
... | ... | @@ -1529,7 +1533,7 @@ |
1529 | 1533 | /* Create the new socket */ |
1530 | 1534 | nsk = iucv_sock_alloc(NULL, sk->sk_type, GFP_ATOMIC); |
1531 | 1535 | if (!nsk) { |
1532 | - err = iucv_path_sever(path, user_data); | |
1536 | + err = pr_iucv->path_sever(path, user_data); | |
1533 | 1537 | iucv_path_free(path); |
1534 | 1538 | goto fail; |
1535 | 1539 | } |
1536 | 1540 | |
... | ... | @@ -1553,9 +1557,9 @@ |
1553 | 1557 | /* set message limit for path based on msglimit of accepting socket */ |
1554 | 1558 | niucv->msglimit = iucv->msglimit; |
1555 | 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 | 1561 | if (err) { |
1558 | - err = iucv_path_sever(path, user_data); | |
1562 | + err = pr_iucv->path_sever(path, user_data); | |
1559 | 1563 | iucv_path_free(path); |
1560 | 1564 | iucv_sock_kill(nsk); |
1561 | 1565 | goto fail; |
... | ... | @@ -1589,7 +1593,7 @@ |
1589 | 1593 | int len; |
1590 | 1594 | |
1591 | 1595 | if (sk->sk_shutdown & RCV_SHUTDOWN) { |
1592 | - iucv_message_reject(path, msg); | |
1596 | + pr_iucv->message_reject(path, msg); | |
1593 | 1597 | return; |
1594 | 1598 | } |
1595 | 1599 | |
... | ... | @@ -1718,6 +1722,41 @@ |
1718 | 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 | 1760 | static int __init afiucv_init(void) |
1722 | 1761 | { |
1723 | 1762 | int err; |
1724 | 1763 | |
1725 | 1764 | |
1726 | 1765 | |
1727 | 1766 | |
1728 | 1767 | |
1729 | 1768 | |
1730 | 1769 | |
... | ... | @@ -1735,44 +1774,33 @@ |
1735 | 1774 | goto out; |
1736 | 1775 | } |
1737 | 1776 | |
1738 | - err = iucv_register(&af_iucv_handler, 0); | |
1739 | - if (err) | |
1777 | + pr_iucv = try_then_request_module(symbol_get(iucv_if), "iucv"); | |
1778 | + if (!pr_iucv) { | |
1779 | + printk(KERN_WARNING "iucv_if lookup failed\n"); | |
1780 | + err = -EPROTONOSUPPORT; | |
1740 | 1781 | goto out; |
1782 | + } | |
1783 | + | |
1741 | 1784 | err = proto_register(&iucv_proto, 0); |
1742 | 1785 | if (err) |
1743 | - goto out_iucv; | |
1786 | + goto out; | |
1744 | 1787 | err = sock_register(&iucv_sock_family_ops); |
1745 | 1788 | if (err) |
1746 | 1789 | goto out_proto; |
1747 | - /* establish dummy device */ | |
1748 | - err = driver_register(&af_iucv_driver); | |
1790 | + | |
1791 | + err = afiucv_iucv_init(); | |
1749 | 1792 | if (err) |
1750 | 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 | 1795 | return 0; |
1766 | 1796 | |
1767 | -out_driver: | |
1768 | - driver_unregister(&af_iucv_driver); | |
1769 | 1797 | out_sock: |
1770 | 1798 | sock_unregister(PF_IUCV); |
1771 | 1799 | out_proto: |
1772 | 1800 | proto_unregister(&iucv_proto); |
1773 | -out_iucv: | |
1774 | - iucv_unregister(&af_iucv_handler, 0); | |
1775 | 1801 | out: |
1802 | + if (pr_iucv) | |
1803 | + symbol_put(iucv_if); | |
1776 | 1804 | return err; |
1777 | 1805 | } |
1778 | 1806 | |
1779 | 1807 | |
... | ... | @@ -1780,9 +1808,10 @@ |
1780 | 1808 | { |
1781 | 1809 | device_unregister(af_iucv_dev); |
1782 | 1810 | driver_unregister(&af_iucv_driver); |
1811 | + pr_iucv->iucv_unregister(&af_iucv_handler, 0); | |
1812 | + symbol_put(iucv_if); | |
1783 | 1813 | sock_unregister(PF_IUCV); |
1784 | 1814 | proto_unregister(&iucv_proto); |
1785 | - iucv_unregister(&af_iucv_handler, 0); | |
1786 | 1815 | } |
1787 | 1816 | |
1788 | 1817 | module_init(afiucv_init); |