提交 6fcd61f7 编写于 作者: F Frank Blaschka 提交者: David S. Miller

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: NFrank Blaschka <frank.blaschka@de.ibm.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 c69748d1
...@@ -42,6 +42,8 @@ static struct proto iucv_proto = { ...@@ -42,6 +42,8 @@ static struct proto iucv_proto = {
.obj_size = sizeof(struct iucv_sock), .obj_size = sizeof(struct iucv_sock),
}; };
static struct iucv_interface *pr_iucv;
/* special AF_IUCV IPRM messages */ /* special AF_IUCV IPRM messages */
static const u8 iprm_shutdown[8] = static const u8 iprm_shutdown[8] =
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
...@@ -165,7 +167,7 @@ static int afiucv_pm_freeze(struct device *dev) ...@@ -165,7 +167,7 @@ static int afiucv_pm_freeze(struct device *dev)
case IUCV_CLOSING: case IUCV_CLOSING:
case IUCV_CONNECTED: case IUCV_CONNECTED:
if (iucv->path) { if (iucv->path) {
err = iucv_path_sever(iucv->path, NULL); err = pr_iucv->path_sever(iucv->path, NULL);
iucv_path_free(iucv->path); iucv_path_free(iucv->path);
iucv->path = NULL; iucv->path = NULL;
} }
...@@ -229,7 +231,7 @@ static const struct dev_pm_ops afiucv_pm_ops = { ...@@ -229,7 +231,7 @@ static const struct dev_pm_ops afiucv_pm_ops = {
static struct device_driver af_iucv_driver = { static struct device_driver af_iucv_driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "afiucv", .name = "afiucv",
.bus = &iucv_bus, .bus = NULL,
.pm = &afiucv_pm_ops, .pm = &afiucv_pm_ops,
}; };
...@@ -412,7 +414,7 @@ static void iucv_sock_close(struct sock *sk) ...@@ -412,7 +414,7 @@ static void iucv_sock_close(struct sock *sk)
low_nmcpy(user_data, iucv->src_name); low_nmcpy(user_data, iucv->src_name);
high_nmcpy(user_data, iucv->dst_name); high_nmcpy(user_data, iucv->dst_name);
ASCEBC(user_data, sizeof(user_data)); ASCEBC(user_data, sizeof(user_data));
iucv_path_sever(iucv->path, user_data); pr_iucv->path_sever(iucv->path, user_data);
iucv_path_free(iucv->path); iucv_path_free(iucv->path);
iucv->path = NULL; iucv->path = NULL;
} }
...@@ -704,8 +706,9 @@ static int iucv_sock_connect(struct socket *sock, struct sockaddr *addr, ...@@ -704,8 +706,9 @@ static int iucv_sock_connect(struct socket *sock, struct sockaddr *addr,
err = -ENOMEM; err = -ENOMEM;
goto done; goto done;
} }
err = iucv_path_connect(iucv->path, &af_iucv_handler, err = pr_iucv->path_connect(iucv->path, &af_iucv_handler,
sa->siucv_user_id, NULL, user_data, sk); sa->siucv_user_id, NULL, user_data,
sk);
if (err) { if (err) {
iucv_path_free(iucv->path); iucv_path_free(iucv->path);
iucv->path = NULL; iucv->path = NULL;
...@@ -738,7 +741,7 @@ static int iucv_sock_connect(struct socket *sock, struct sockaddr *addr, ...@@ -738,7 +741,7 @@ static int iucv_sock_connect(struct socket *sock, struct sockaddr *addr,
} }
if (err) { if (err) {
iucv_path_sever(iucv->path, NULL); pr_iucv->path_sever(iucv->path, NULL);
iucv_path_free(iucv->path); iucv_path_free(iucv->path);
iucv->path = NULL; iucv->path = NULL;
} }
...@@ -871,7 +874,7 @@ static int iucv_send_iprm(struct iucv_path *path, struct iucv_message *msg, ...@@ -871,7 +874,7 @@ static int iucv_send_iprm(struct iucv_path *path, struct iucv_message *msg,
memcpy(prmdata, (void *) skb->data, skb->len); memcpy(prmdata, (void *) skb->data, skb->len);
prmdata[7] = 0xff - (u8) skb->len; prmdata[7] = 0xff - (u8) skb->len;
return iucv_message_send(path, msg, IUCV_IPRMDATA, 0, return pr_iucv->message_send(path, msg, IUCV_IPRMDATA, 0,
(void *) prmdata, 8); (void *) prmdata, 8);
} }
...@@ -999,13 +1002,13 @@ static int iucv_sock_sendmsg(struct kiocb *iocb, struct socket *sock, ...@@ -999,13 +1002,13 @@ static int iucv_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
/* this error should never happen since the /* this error should never happen since the
* IUCV_IPRMDATA path flag is set... sever path */ * IUCV_IPRMDATA path flag is set... sever path */
if (err == 0x15) { if (err == 0x15) {
iucv_path_sever(iucv->path, NULL); pr_iucv->path_sever(iucv->path, NULL);
skb_unlink(skb, &iucv->send_skb_q); skb_unlink(skb, &iucv->send_skb_q);
err = -EPIPE; err = -EPIPE;
goto fail; goto fail;
} }
} else } else
err = iucv_message_send(iucv->path, &txmsg, 0, 0, err = pr_iucv->message_send(iucv->path, &txmsg, 0, 0,
(void *) skb->data, skb->len); (void *) skb->data, skb->len);
if (err) { if (err) {
if (err == 3) { if (err == 3) {
...@@ -1095,8 +1098,9 @@ static void iucv_process_message(struct sock *sk, struct sk_buff *skb, ...@@ -1095,8 +1098,9 @@ static void iucv_process_message(struct sock *sk, struct sk_buff *skb,
skb->len = 0; skb->len = 0;
} }
} else { } else {
rc = iucv_message_receive(path, msg, msg->flags & IUCV_IPRMDATA, rc = pr_iucv->message_receive(path, msg,
skb->data, len, NULL); msg->flags & IUCV_IPRMDATA,
skb->data, len, NULL);
if (rc) { if (rc) {
kfree_skb(skb); kfree_skb(skb);
return; return;
...@@ -1110,7 +1114,7 @@ static void iucv_process_message(struct sock *sk, struct sk_buff *skb, ...@@ -1110,7 +1114,7 @@ static void iucv_process_message(struct sock *sk, struct sk_buff *skb,
kfree_skb(skb); kfree_skb(skb);
skb = NULL; skb = NULL;
if (rc) { if (rc) {
iucv_path_sever(path, NULL); pr_iucv->path_sever(path, NULL);
return; return;
} }
skb = skb_dequeue(&iucv_sk(sk)->backlog_skb_q); skb = skb_dequeue(&iucv_sk(sk)->backlog_skb_q);
...@@ -1327,8 +1331,8 @@ static int iucv_sock_shutdown(struct socket *sock, int how) ...@@ -1327,8 +1331,8 @@ static int iucv_sock_shutdown(struct socket *sock, int how)
if (how == SEND_SHUTDOWN || how == SHUTDOWN_MASK) { if (how == SEND_SHUTDOWN || how == SHUTDOWN_MASK) {
txmsg.class = 0; txmsg.class = 0;
txmsg.tag = 0; txmsg.tag = 0;
err = iucv_message_send(iucv->path, &txmsg, IUCV_IPRMDATA, 0, err = pr_iucv->message_send(iucv->path, &txmsg, IUCV_IPRMDATA,
(void *) iprm_shutdown, 8); 0, (void *) iprm_shutdown, 8);
if (err) { if (err) {
switch (err) { switch (err) {
case 1: case 1:
...@@ -1345,7 +1349,7 @@ static int iucv_sock_shutdown(struct socket *sock, int how) ...@@ -1345,7 +1349,7 @@ static int iucv_sock_shutdown(struct socket *sock, int how)
} }
if (how == RCV_SHUTDOWN || how == SHUTDOWN_MASK) { if (how == RCV_SHUTDOWN || how == SHUTDOWN_MASK) {
err = iucv_path_quiesce(iucv_sk(sk)->path, NULL); err = pr_iucv->path_quiesce(iucv->path, NULL);
if (err) if (err)
err = -ENOTCONN; err = -ENOTCONN;
...@@ -1372,7 +1376,7 @@ static int iucv_sock_release(struct socket *sock) ...@@ -1372,7 +1376,7 @@ static int iucv_sock_release(struct socket *sock)
/* Unregister with IUCV base support */ /* Unregister with IUCV base support */
if (iucv_sk(sk)->path) { if (iucv_sk(sk)->path) {
iucv_path_sever(iucv_sk(sk)->path, NULL); pr_iucv->path_sever(iucv_sk(sk)->path, NULL);
iucv_path_free(iucv_sk(sk)->path); iucv_path_free(iucv_sk(sk)->path);
iucv_sk(sk)->path = NULL; iucv_sk(sk)->path = NULL;
} }
...@@ -1514,14 +1518,14 @@ static int iucv_callback_connreq(struct iucv_path *path, ...@@ -1514,14 +1518,14 @@ static int iucv_callback_connreq(struct iucv_path *path,
high_nmcpy(user_data, iucv->dst_name); high_nmcpy(user_data, iucv->dst_name);
ASCEBC(user_data, sizeof(user_data)); ASCEBC(user_data, sizeof(user_data));
if (sk->sk_state != IUCV_LISTEN) { if (sk->sk_state != IUCV_LISTEN) {
err = iucv_path_sever(path, user_data); err = pr_iucv->path_sever(path, user_data);
iucv_path_free(path); iucv_path_free(path);
goto fail; goto fail;
} }
/* Check for backlog size */ /* Check for backlog size */
if (sk_acceptq_is_full(sk)) { if (sk_acceptq_is_full(sk)) {
err = iucv_path_sever(path, user_data); err = pr_iucv->path_sever(path, user_data);
iucv_path_free(path); iucv_path_free(path);
goto fail; goto fail;
} }
...@@ -1529,7 +1533,7 @@ static int iucv_callback_connreq(struct iucv_path *path, ...@@ -1529,7 +1533,7 @@ static int iucv_callback_connreq(struct iucv_path *path,
/* Create the new socket */ /* Create the new socket */
nsk = iucv_sock_alloc(NULL, sk->sk_type, GFP_ATOMIC); nsk = iucv_sock_alloc(NULL, sk->sk_type, GFP_ATOMIC);
if (!nsk) { if (!nsk) {
err = iucv_path_sever(path, user_data); err = pr_iucv->path_sever(path, user_data);
iucv_path_free(path); iucv_path_free(path);
goto fail; goto fail;
} }
...@@ -1553,9 +1557,9 @@ static int iucv_callback_connreq(struct iucv_path *path, ...@@ -1553,9 +1557,9 @@ static int iucv_callback_connreq(struct iucv_path *path,
/* set message limit for path based on msglimit of accepting socket */ /* set message limit for path based on msglimit of accepting socket */
niucv->msglimit = iucv->msglimit; niucv->msglimit = iucv->msglimit;
path->msglim = iucv->msglimit; path->msglim = iucv->msglimit;
err = iucv_path_accept(path, &af_iucv_handler, nuser_data, nsk); err = pr_iucv->path_accept(path, &af_iucv_handler, nuser_data, nsk);
if (err) { if (err) {
err = iucv_path_sever(path, user_data); err = pr_iucv->path_sever(path, user_data);
iucv_path_free(path); iucv_path_free(path);
iucv_sock_kill(nsk); iucv_sock_kill(nsk);
goto fail; goto fail;
...@@ -1589,7 +1593,7 @@ static void iucv_callback_rx(struct iucv_path *path, struct iucv_message *msg) ...@@ -1589,7 +1593,7 @@ static void iucv_callback_rx(struct iucv_path *path, struct iucv_message *msg)
int len; int len;
if (sk->sk_shutdown & RCV_SHUTDOWN) { if (sk->sk_shutdown & RCV_SHUTDOWN) {
iucv_message_reject(path, msg); pr_iucv->message_reject(path, msg);
return; return;
} }
...@@ -1718,6 +1722,41 @@ static const struct net_proto_family iucv_sock_family_ops = { ...@@ -1718,6 +1722,41 @@ static const struct net_proto_family iucv_sock_family_ops = {
.create = iucv_sock_create, .create = iucv_sock_create,
}; };
static int __init afiucv_iucv_init(void)
{
int err;
err = pr_iucv->iucv_register(&af_iucv_handler, 0);
if (err)
goto out;
/* establish dummy device */
af_iucv_driver.bus = pr_iucv->bus;
err = driver_register(&af_iucv_driver);
if (err)
goto out_iucv;
af_iucv_dev = kzalloc(sizeof(struct device), GFP_KERNEL);
if (!af_iucv_dev) {
err = -ENOMEM;
goto out_driver;
}
dev_set_name(af_iucv_dev, "af_iucv");
af_iucv_dev->bus = pr_iucv->bus;
af_iucv_dev->parent = pr_iucv->root;
af_iucv_dev->release = (void (*)(struct device *))kfree;
af_iucv_dev->driver = &af_iucv_driver;
err = device_register(af_iucv_dev);
if (err)
goto out_driver;
return 0;
out_driver:
driver_unregister(&af_iucv_driver);
out_iucv:
pr_iucv->iucv_unregister(&af_iucv_handler, 0);
out:
return err;
}
static int __init afiucv_init(void) static int __init afiucv_init(void)
{ {
int err; int err;
...@@ -1735,44 +1774,33 @@ static int __init afiucv_init(void) ...@@ -1735,44 +1774,33 @@ static int __init afiucv_init(void)
goto out; goto out;
} }
err = iucv_register(&af_iucv_handler, 0); pr_iucv = try_then_request_module(symbol_get(iucv_if), "iucv");
if (err) if (!pr_iucv) {
printk(KERN_WARNING "iucv_if lookup failed\n");
err = -EPROTONOSUPPORT;
goto out; goto out;
}
err = proto_register(&iucv_proto, 0); err = proto_register(&iucv_proto, 0);
if (err) if (err)
goto out_iucv; goto out;
err = sock_register(&iucv_sock_family_ops); err = sock_register(&iucv_sock_family_ops);
if (err) if (err)
goto out_proto; goto out_proto;
/* establish dummy device */
err = driver_register(&af_iucv_driver); err = afiucv_iucv_init();
if (err) if (err)
goto out_sock; goto out_sock;
af_iucv_dev = kzalloc(sizeof(struct device), GFP_KERNEL);
if (!af_iucv_dev) {
err = -ENOMEM;
goto out_driver;
}
dev_set_name(af_iucv_dev, "af_iucv");
af_iucv_dev->bus = &iucv_bus;
af_iucv_dev->parent = iucv_root;
af_iucv_dev->release = (void (*)(struct device *))kfree;
af_iucv_dev->driver = &af_iucv_driver;
err = device_register(af_iucv_dev);
if (err)
goto out_driver;
return 0; return 0;
out_driver:
driver_unregister(&af_iucv_driver);
out_sock: out_sock:
sock_unregister(PF_IUCV); sock_unregister(PF_IUCV);
out_proto: out_proto:
proto_unregister(&iucv_proto); proto_unregister(&iucv_proto);
out_iucv:
iucv_unregister(&af_iucv_handler, 0);
out: out:
if (pr_iucv)
symbol_put(iucv_if);
return err; return err;
} }
...@@ -1780,9 +1808,10 @@ static void __exit afiucv_exit(void) ...@@ -1780,9 +1808,10 @@ static void __exit afiucv_exit(void)
{ {
device_unregister(af_iucv_dev); device_unregister(af_iucv_dev);
driver_unregister(&af_iucv_driver); driver_unregister(&af_iucv_driver);
pr_iucv->iucv_unregister(&af_iucv_handler, 0);
symbol_put(iucv_if);
sock_unregister(PF_IUCV); sock_unregister(PF_IUCV);
proto_unregister(&iucv_proto); proto_unregister(&iucv_proto);
iucv_unregister(&af_iucv_handler, 0);
} }
module_init(afiucv_init); module_init(afiucv_init);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册