aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/crypto/geode-aes.c2
-rw-r--r--drivers/net/bonding/bond_alb.c4
-rw-r--r--drivers/net/bonding/bond_main.c4
-rw-r--r--drivers/net/slip.c5
-rw-r--r--drivers/net/tg3.c2
-rw-r--r--drivers/s390/char/monreader.c218
-rw-r--r--drivers/s390/char/vmlogrdr.c279
-rw-r--r--drivers/s390/net/Kconfig7
-rw-r--r--drivers/s390/net/Makefile1
-rw-r--r--drivers/s390/net/iucv.c2540
-rw-r--r--drivers/s390/net/iucv.h849
-rw-r--r--drivers/s390/net/netiucv.c1314
-rw-r--r--drivers/s390/net/smsgiucv.c147
13 files changed, 959 insertions, 4413 deletions
diff --git a/drivers/crypto/geode-aes.c b/drivers/crypto/geode-aes.c
index 43a68398656f..31ea405f2eeb 100644
--- a/drivers/crypto/geode-aes.c
+++ b/drivers/crypto/geode-aes.c
@@ -457,7 +457,7 @@ static struct pci_driver geode_aes_driver = {
457static int __init 457static int __init
458geode_aes_init(void) 458geode_aes_init(void)
459{ 459{
460 return pci_module_init(&geode_aes_driver); 460 return pci_register_driver(&geode_aes_driver);
461} 461}
462 462
463static void __exit 463static void __exit
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 32923162179e..217a2eedee0a 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -184,7 +184,7 @@ static int tlb_initialize(struct bonding *bond)
184 184
185 spin_lock_init(&(bond_info->tx_hashtbl_lock)); 185 spin_lock_init(&(bond_info->tx_hashtbl_lock));
186 186
187 new_hashtbl = kmalloc(size, GFP_KERNEL); 187 new_hashtbl = kzalloc(size, GFP_KERNEL);
188 if (!new_hashtbl) { 188 if (!new_hashtbl) {
189 printk(KERN_ERR DRV_NAME 189 printk(KERN_ERR DRV_NAME
190 ": %s: Error: Failed to allocate TLB hash table\n", 190 ": %s: Error: Failed to allocate TLB hash table\n",
@@ -195,8 +195,6 @@ static int tlb_initialize(struct bonding *bond)
195 195
196 bond_info->tx_hashtbl = new_hashtbl; 196 bond_info->tx_hashtbl = new_hashtbl;
197 197
198 memset(bond_info->tx_hashtbl, 0, size);
199
200 for (i = 0; i < TLB_HASH_TABLE_SIZE; i++) { 198 for (i = 0; i < TLB_HASH_TABLE_SIZE; i++) {
201 tlb_init_table_entry(&bond_info->tx_hashtbl[i], 1); 199 tlb_init_table_entry(&bond_info->tx_hashtbl[i], 1);
202 } 200 }
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index d3801a00d3d5..8ce8fec615ba 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1343,14 +1343,12 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
1343 "inaccurate.\n", bond_dev->name, slave_dev->name); 1343 "inaccurate.\n", bond_dev->name, slave_dev->name);
1344 } 1344 }
1345 1345
1346 new_slave = kmalloc(sizeof(struct slave), GFP_KERNEL); 1346 new_slave = kzalloc(sizeof(struct slave), GFP_KERNEL);
1347 if (!new_slave) { 1347 if (!new_slave) {
1348 res = -ENOMEM; 1348 res = -ENOMEM;
1349 goto err_undo_flags; 1349 goto err_undo_flags;
1350 } 1350 }
1351 1351
1352 memset(new_slave, 0, sizeof(struct slave));
1353
1354 /* save slave's original flags before calling 1352 /* save slave's original flags before calling
1355 * netdev_set_master and dev_open 1353 * netdev_set_master and dev_open
1356 */ 1354 */
diff --git a/drivers/net/slip.c b/drivers/net/slip.c
index a0806d262fc6..2f4b1de7a2b4 100644
--- a/drivers/net/slip.c
+++ b/drivers/net/slip.c
@@ -1343,15 +1343,12 @@ static int __init slip_init(void)
1343 printk(KERN_INFO "SLIP linefill/keepalive option.\n"); 1343 printk(KERN_INFO "SLIP linefill/keepalive option.\n");
1344#endif 1344#endif
1345 1345
1346 slip_devs = kmalloc(sizeof(struct net_device *)*slip_maxdev, GFP_KERNEL); 1346 slip_devs = kzalloc(sizeof(struct net_device *)*slip_maxdev, GFP_KERNEL);
1347 if (!slip_devs) { 1347 if (!slip_devs) {
1348 printk(KERN_ERR "SLIP: Can't allocate slip devices array! Uaargh! (-> No SLIP available)\n"); 1348 printk(KERN_ERR "SLIP: Can't allocate slip devices array! Uaargh! (-> No SLIP available)\n");
1349 return -ENOMEM; 1349 return -ENOMEM;
1350 } 1350 }
1351 1351
1352 /* Clear the pointer array, we allocate devices when we need them */
1353 memset(slip_devs, 0, sizeof(struct net_device *)*slip_maxdev);
1354
1355 /* Fill in our line protocol discipline, and register it */ 1352 /* Fill in our line protocol discipline, and register it */
1356 if ((status = tty_register_ldisc(N_SLIP, &sl_ldisc)) != 0) { 1353 if ((status = tty_register_ldisc(N_SLIP, &sl_ldisc)) != 0) {
1357 printk(KERN_ERR "SLIP: can't register line discipline (err = %d)\n", status); 1354 printk(KERN_ERR "SLIP: can't register line discipline (err = %d)\n", status);
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 135c0987deae..e136bae61970 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -3380,7 +3380,7 @@ next_pkt:
3380 } 3380 }
3381next_pkt_nopost: 3381next_pkt_nopost:
3382 sw_idx++; 3382 sw_idx++;
3383 sw_idx %= TG3_RX_RCB_RING_SIZE(tp); 3383 sw_idx &= (TG3_RX_RCB_RING_SIZE(tp) - 1);
3384 3384
3385 /* Refresh hw_idx to see if there is new work */ 3385 /* Refresh hw_idx to see if there is new work */
3386 if (sw_idx == hw_idx) { 3386 if (sw_idx == hw_idx) {
diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c
index a138b1510093..3a1a958fb5f2 100644
--- a/drivers/s390/char/monreader.c
+++ b/drivers/s390/char/monreader.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * Character device driver for reading z/VM *MONITOR service records. 4 * Character device driver for reading z/VM *MONITOR service records.
5 * 5 *
6 * Copyright (C) 2004 IBM Corporation, IBM Deutschland Entwicklung GmbH. 6 * Copyright 2004 IBM Corporation, IBM Deutschland Entwicklung GmbH.
7 * 7 *
8 * Author: Gerald Schaefer <geraldsc@de.ibm.com> 8 * Author: Gerald Schaefer <geraldsc@de.ibm.com>
9 */ 9 */
@@ -22,7 +22,7 @@
22#include <asm/ebcdic.h> 22#include <asm/ebcdic.h>
23#include <asm/extmem.h> 23#include <asm/extmem.h>
24#include <linux/poll.h> 24#include <linux/poll.h>
25#include "../net/iucv.h" 25#include <net/iucv/iucv.h>
26 26
27 27
28//#define MON_DEBUG /* Debug messages on/off */ 28//#define MON_DEBUG /* Debug messages on/off */
@@ -50,14 +50,13 @@ static char mon_dcss_name[9] = "MONDCSS\0";
50struct mon_msg { 50struct mon_msg {
51 u32 pos; 51 u32 pos;
52 u32 mca_offset; 52 u32 mca_offset;
53 iucv_MessagePending local_eib; 53 struct iucv_message msg;
54 char msglim_reached; 54 char msglim_reached;
55 char replied_msglim; 55 char replied_msglim;
56}; 56};
57 57
58struct mon_private { 58struct mon_private {
59 u16 pathid; 59 struct iucv_path *path;
60 iucv_handle_t iucv_handle;
61 struct mon_msg *msg_array[MON_MSGLIM]; 60 struct mon_msg *msg_array[MON_MSGLIM];
62 unsigned int write_index; 61 unsigned int write_index;
63 unsigned int read_index; 62 unsigned int read_index;
@@ -75,8 +74,6 @@ static unsigned long mon_dcss_end;
75static DECLARE_WAIT_QUEUE_HEAD(mon_read_wait_queue); 74static DECLARE_WAIT_QUEUE_HEAD(mon_read_wait_queue);
76static DECLARE_WAIT_QUEUE_HEAD(mon_conn_wait_queue); 75static DECLARE_WAIT_QUEUE_HEAD(mon_conn_wait_queue);
77 76
78static u8 iucv_host[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
79
80static u8 user_data_connect[16] = { 77static u8 user_data_connect[16] = {
81 /* Version code, must be 0x01 for shared mode */ 78 /* Version code, must be 0x01 for shared mode */
82 0x01, 79 0x01,
@@ -100,8 +97,7 @@ static u8 user_data_sever[16] = {
100 * Create the 8 bytes EBCDIC DCSS segment name from 97 * Create the 8 bytes EBCDIC DCSS segment name from
101 * an ASCII name, incl. padding 98 * an ASCII name, incl. padding
102 */ 99 */
103static inline void 100static inline void dcss_mkname(char *ascii_name, char *ebcdic_name)
104dcss_mkname(char *ascii_name, char *ebcdic_name)
105{ 101{
106 int i; 102 int i;
107 103
@@ -119,8 +115,7 @@ dcss_mkname(char *ascii_name, char *ebcdic_name)
119 * print appropriate error message for segment_load()/segment_type() 115 * print appropriate error message for segment_load()/segment_type()
120 * return code 116 * return code
121 */ 117 */
122static void 118static void mon_segment_warn(int rc, char* seg_name)
123mon_segment_warn(int rc, char* seg_name)
124{ 119{
125 switch (rc) { 120 switch (rc) {
126 case -ENOENT: 121 case -ENOENT:
@@ -166,44 +161,37 @@ mon_segment_warn(int rc, char* seg_name)
166 } 161 }
167} 162}
168 163
169static inline unsigned long 164static inline unsigned long mon_mca_start(struct mon_msg *monmsg)
170mon_mca_start(struct mon_msg *monmsg)
171{ 165{
172 return monmsg->local_eib.ln1msg1.iprmmsg1_u32; 166 return *(u32 *) &monmsg->msg.rmmsg;
173} 167}
174 168
175static inline unsigned long 169static inline unsigned long mon_mca_end(struct mon_msg *monmsg)
176mon_mca_end(struct mon_msg *monmsg)
177{ 170{
178 return monmsg->local_eib.ln1msg2.ipbfln1f; 171 return *(u32 *) &monmsg->msg.rmmsg[4];
179} 172}
180 173
181static inline u8 174static inline u8 mon_mca_type(struct mon_msg *monmsg, u8 index)
182mon_mca_type(struct mon_msg *monmsg, u8 index)
183{ 175{
184 return *((u8 *) mon_mca_start(monmsg) + monmsg->mca_offset + index); 176 return *((u8 *) mon_mca_start(monmsg) + monmsg->mca_offset + index);
185} 177}
186 178
187static inline u32 179static inline u32 mon_mca_size(struct mon_msg *monmsg)
188mon_mca_size(struct mon_msg *monmsg)
189{ 180{
190 return mon_mca_end(monmsg) - mon_mca_start(monmsg) + 1; 181 return mon_mca_end(monmsg) - mon_mca_start(monmsg) + 1;
191} 182}
192 183
193static inline u32 184static inline u32 mon_rec_start(struct mon_msg *monmsg)
194mon_rec_start(struct mon_msg *monmsg)
195{ 185{
196 return *((u32 *) (mon_mca_start(monmsg) + monmsg->mca_offset + 4)); 186 return *((u32 *) (mon_mca_start(monmsg) + monmsg->mca_offset + 4));
197} 187}
198 188
199static inline u32 189static inline u32 mon_rec_end(struct mon_msg *monmsg)
200mon_rec_end(struct mon_msg *monmsg)
201{ 190{
202 return *((u32 *) (mon_mca_start(monmsg) + monmsg->mca_offset + 8)); 191 return *((u32 *) (mon_mca_start(monmsg) + monmsg->mca_offset + 8));
203} 192}
204 193
205static inline int 194static inline int mon_check_mca(struct mon_msg *monmsg)
206mon_check_mca(struct mon_msg *monmsg)
207{ 195{
208 if ((mon_rec_end(monmsg) <= mon_rec_start(monmsg)) || 196 if ((mon_rec_end(monmsg) <= mon_rec_start(monmsg)) ||
209 (mon_rec_start(monmsg) < mon_dcss_start) || 197 (mon_rec_start(monmsg) < mon_dcss_start) ||
@@ -221,20 +209,17 @@ mon_check_mca(struct mon_msg *monmsg)
221 return 0; 209 return 0;
222} 210}
223 211
224static inline int 212static inline int mon_send_reply(struct mon_msg *monmsg,
225mon_send_reply(struct mon_msg *monmsg, struct mon_private *monpriv) 213 struct mon_private *monpriv)
226{ 214{
227 u8 prmmsg[8];
228 int rc; 215 int rc;
229 216
230 P_DEBUG("read, REPLY: pathid = 0x%04X, msgid = 0x%08X, trgcls = " 217 P_DEBUG("read, REPLY: pathid = 0x%04X, msgid = 0x%08X, trgcls = "
231 "0x%08X\n\n", 218 "0x%08X\n\n",
232 monmsg->local_eib.ippathid, monmsg->local_eib.ipmsgid, 219 monpriv->path->pathid, monmsg->msg.id, monmsg->msg.class);
233 monmsg->local_eib.iptrgcls); 220
234 rc = iucv_reply_prmmsg(monmsg->local_eib.ippathid, 221 rc = iucv_message_reply(monpriv->path, &monmsg->msg,
235 monmsg->local_eib.ipmsgid, 222 IUCV_IPRMDATA, NULL, 0);
236 monmsg->local_eib.iptrgcls,
237 0, prmmsg);
238 atomic_dec(&monpriv->msglim_count); 223 atomic_dec(&monpriv->msglim_count);
239 if (likely(!monmsg->msglim_reached)) { 224 if (likely(!monmsg->msglim_reached)) {
240 monmsg->pos = 0; 225 monmsg->pos = 0;
@@ -251,10 +236,19 @@ mon_send_reply(struct mon_msg *monmsg, struct mon_private *monpriv)
251 return 0; 236 return 0;
252} 237}
253 238
254static inline struct mon_private * 239static inline void mon_free_mem(struct mon_private *monpriv)
255mon_alloc_mem(void) 240{
241 int i;
242
243 for (i = 0; i < MON_MSGLIM; i++)
244 if (monpriv->msg_array[i])
245 kfree(monpriv->msg_array[i]);
246 kfree(monpriv);
247}
248
249static inline struct mon_private *mon_alloc_mem(void)
256{ 250{
257 int i,j; 251 int i;
258 struct mon_private *monpriv; 252 struct mon_private *monpriv;
259 253
260 monpriv = kzalloc(sizeof(struct mon_private), GFP_KERNEL); 254 monpriv = kzalloc(sizeof(struct mon_private), GFP_KERNEL);
@@ -267,16 +261,15 @@ mon_alloc_mem(void)
267 GFP_KERNEL); 261 GFP_KERNEL);
268 if (!monpriv->msg_array[i]) { 262 if (!monpriv->msg_array[i]) {
269 P_ERROR("open, no memory for msg_array\n"); 263 P_ERROR("open, no memory for msg_array\n");
270 for (j = 0; j < i; j++) 264 mon_free_mem(monpriv);
271 kfree(monpriv->msg_array[j]);
272 return NULL; 265 return NULL;
273 } 266 }
274 } 267 }
275 return monpriv; 268 return monpriv;
276} 269}
277 270
278static inline void 271static inline void mon_read_debug(struct mon_msg *monmsg,
279mon_read_debug(struct mon_msg *monmsg, struct mon_private *monpriv) 272 struct mon_private *monpriv)
280{ 273{
281#ifdef MON_DEBUG 274#ifdef MON_DEBUG
282 u8 msg_type[2], mca_type; 275 u8 msg_type[2], mca_type;
@@ -284,7 +277,7 @@ mon_read_debug(struct mon_msg *monmsg, struct mon_private *monpriv)
284 277
285 records_len = mon_rec_end(monmsg) - mon_rec_start(monmsg) + 1; 278 records_len = mon_rec_end(monmsg) - mon_rec_start(monmsg) + 1;
286 279
287 memcpy(msg_type, &monmsg->local_eib.iptrgcls, 2); 280 memcpy(msg_type, &monmsg->msg.class, 2);
288 EBCASC(msg_type, 2); 281 EBCASC(msg_type, 2);
289 mca_type = mon_mca_type(monmsg, 0); 282 mca_type = mon_mca_type(monmsg, 0);
290 EBCASC(&mca_type, 1); 283 EBCASC(&mca_type, 1);
@@ -292,8 +285,7 @@ mon_read_debug(struct mon_msg *monmsg, struct mon_private *monpriv)
292 P_DEBUG("read, mon_read_index = %i, mon_write_index = %i\n", 285 P_DEBUG("read, mon_read_index = %i, mon_write_index = %i\n",
293 monpriv->read_index, monpriv->write_index); 286 monpriv->read_index, monpriv->write_index);
294 P_DEBUG("read, pathid = 0x%04X, msgid = 0x%08X, trgcls = 0x%08X\n", 287 P_DEBUG("read, pathid = 0x%04X, msgid = 0x%08X, trgcls = 0x%08X\n",
295 monmsg->local_eib.ippathid, monmsg->local_eib.ipmsgid, 288 monpriv->path->pathid, monmsg->msg.id, monmsg->msg.class);
296 monmsg->local_eib.iptrgcls);
297 P_DEBUG("read, msg_type = '%c%c', mca_type = '%c' / 0x%X / 0x%X\n", 289 P_DEBUG("read, msg_type = '%c%c', mca_type = '%c' / 0x%X / 0x%X\n",
298 msg_type[0], msg_type[1], mca_type ? mca_type : 'X', 290 msg_type[0], msg_type[1], mca_type ? mca_type : 'X',
299 mon_mca_type(monmsg, 1), mon_mca_type(monmsg, 2)); 291 mon_mca_type(monmsg, 1), mon_mca_type(monmsg, 2));
@@ -306,8 +298,7 @@ mon_read_debug(struct mon_msg *monmsg, struct mon_private *monpriv)
306#endif 298#endif
307} 299}
308 300
309static inline void 301static inline void mon_next_mca(struct mon_msg *monmsg)
310mon_next_mca(struct mon_msg *monmsg)
311{ 302{
312 if (likely((mon_mca_size(monmsg) - monmsg->mca_offset) == 12)) 303 if (likely((mon_mca_size(monmsg) - monmsg->mca_offset) == 12))
313 return; 304 return;
@@ -316,8 +307,7 @@ mon_next_mca(struct mon_msg *monmsg)
316 monmsg->pos = 0; 307 monmsg->pos = 0;
317} 308}
318 309
319static inline struct mon_msg * 310static inline struct mon_msg *mon_next_message(struct mon_private *monpriv)
320mon_next_message(struct mon_private *monpriv)
321{ 311{
322 struct mon_msg *monmsg; 312 struct mon_msg *monmsg;
323 313
@@ -342,39 +332,37 @@ mon_next_message(struct mon_private *monpriv)
342/****************************************************************************** 332/******************************************************************************
343 * IUCV handler * 333 * IUCV handler *
344 *****************************************************************************/ 334 *****************************************************************************/
345static void 335static void mon_iucv_path_complete(struct iucv_path *path, u8 ipuser[16])
346mon_iucv_ConnectionComplete(iucv_ConnectionComplete *eib, void *pgm_data)
347{ 336{
348 struct mon_private *monpriv = (struct mon_private *) pgm_data; 337 struct mon_private *monpriv = path->private;
349 338
350 P_DEBUG("IUCV connection completed\n"); 339 P_DEBUG("IUCV connection completed\n");
351 P_DEBUG("IUCV ACCEPT (from *MONITOR): Version = 0x%02X, Event = " 340 P_DEBUG("IUCV ACCEPT (from *MONITOR): Version = 0x%02X, Event = "
352 "0x%02X, Sample = 0x%02X\n", 341 "0x%02X, Sample = 0x%02X\n",
353 eib->ipuser[0], eib->ipuser[1], eib->ipuser[2]); 342 ipuser[0], ipuser[1], ipuser[2]);
354 atomic_set(&monpriv->iucv_connected, 1); 343 atomic_set(&monpriv->iucv_connected, 1);
355 wake_up(&mon_conn_wait_queue); 344 wake_up(&mon_conn_wait_queue);
356} 345}
357 346
358static void 347static void mon_iucv_path_severed(struct iucv_path *path, u8 ipuser[16])
359mon_iucv_ConnectionSevered(iucv_ConnectionSevered *eib, void *pgm_data)
360{ 348{
361 struct mon_private *monpriv = (struct mon_private *) pgm_data; 349 struct mon_private *monpriv = path->private;
362 350
363 P_ERROR("IUCV connection severed with rc = 0x%X\n", 351 P_ERROR("IUCV connection severed with rc = 0x%X\n", ipuser[0]);
364 (u8) eib->ipuser[0]); 352 iucv_path_sever(path, NULL);
365 atomic_set(&monpriv->iucv_severed, 1); 353 atomic_set(&monpriv->iucv_severed, 1);
366 wake_up(&mon_conn_wait_queue); 354 wake_up(&mon_conn_wait_queue);
367 wake_up_interruptible(&mon_read_wait_queue); 355 wake_up_interruptible(&mon_read_wait_queue);
368} 356}
369 357
370static void 358static void mon_iucv_message_pending(struct iucv_path *path,
371mon_iucv_MessagePending(iucv_MessagePending *eib, void *pgm_data) 359 struct iucv_message *msg)
372{ 360{
373 struct mon_private *monpriv = (struct mon_private *) pgm_data; 361 struct mon_private *monpriv = path->private;
374 362
375 P_DEBUG("IUCV message pending\n"); 363 P_DEBUG("IUCV message pending\n");
376 memcpy(&monpriv->msg_array[monpriv->write_index]->local_eib, eib, 364 memcpy(&monpriv->msg_array[monpriv->write_index]->msg,
377 sizeof(iucv_MessagePending)); 365 msg, sizeof(*msg));
378 if (atomic_inc_return(&monpriv->msglim_count) == MON_MSGLIM) { 366 if (atomic_inc_return(&monpriv->msglim_count) == MON_MSGLIM) {
379 P_WARNING("IUCV message pending, message limit (%i) reached\n", 367 P_WARNING("IUCV message pending, message limit (%i) reached\n",
380 MON_MSGLIM); 368 MON_MSGLIM);
@@ -385,54 +373,45 @@ mon_iucv_MessagePending(iucv_MessagePending *eib, void *pgm_data)
385 wake_up_interruptible(&mon_read_wait_queue); 373 wake_up_interruptible(&mon_read_wait_queue);
386} 374}
387 375
388static iucv_interrupt_ops_t mon_iucvops = { 376static struct iucv_handler monreader_iucv_handler = {
389 .ConnectionComplete = mon_iucv_ConnectionComplete, 377 .path_complete = mon_iucv_path_complete,
390 .ConnectionSevered = mon_iucv_ConnectionSevered, 378 .path_severed = mon_iucv_path_severed,
391 .MessagePending = mon_iucv_MessagePending, 379 .message_pending = mon_iucv_message_pending,
392}; 380};
393 381
394/****************************************************************************** 382/******************************************************************************
395 * file operations * 383 * file operations *
396 *****************************************************************************/ 384 *****************************************************************************/
397static int 385static int mon_open(struct inode *inode, struct file *filp)
398mon_open(struct inode *inode, struct file *filp)
399{ 386{
400 int rc, i;
401 struct mon_private *monpriv; 387 struct mon_private *monpriv;
388 int rc;
402 389
403 /* 390 /*
404 * only one user allowed 391 * only one user allowed
405 */ 392 */
393 rc = -EBUSY;
406 if (test_and_set_bit(MON_IN_USE, &mon_in_use)) 394 if (test_and_set_bit(MON_IN_USE, &mon_in_use))
407 return -EBUSY; 395 goto out;
408 396
397 rc = -ENOMEM;
409 monpriv = mon_alloc_mem(); 398 monpriv = mon_alloc_mem();
410 if (!monpriv) 399 if (!monpriv)
411 return -ENOMEM; 400 goto out_use;
412 401
413 /* 402 /*
414 * Register with IUCV and connect to *MONITOR service 403 * Connect to *MONITOR service
415 */ 404 */
416 monpriv->iucv_handle = iucv_register_program("my_monreader ", 405 monpriv->path = iucv_path_alloc(MON_MSGLIM, IUCV_IPRMDATA, GFP_KERNEL);
417 MON_SERVICE, 406 if (!monpriv->path)
418 NULL, 407 goto out_priv;
419 &mon_iucvops, 408 rc = iucv_path_connect(monpriv->path, &monreader_iucv_handler,
420 monpriv); 409 MON_SERVICE, NULL, user_data_connect, monpriv);
421 if (!monpriv->iucv_handle) {
422 P_ERROR("failed to register with iucv driver\n");
423 rc = -EIO;
424 goto out_error;
425 }
426 P_INFO("open, registered with IUCV\n");
427
428 rc = iucv_connect(&monpriv->pathid, MON_MSGLIM, user_data_connect,
429 MON_SERVICE, iucv_host, IPRMDATA, NULL, NULL,
430 monpriv->iucv_handle, NULL);
431 if (rc) { 410 if (rc) {
432 P_ERROR("iucv connection to *MONITOR failed with " 411 P_ERROR("iucv connection to *MONITOR failed with "
433 "IPUSER SEVER code = %i\n", rc); 412 "IPUSER SEVER code = %i\n", rc);
434 rc = -EIO; 413 rc = -EIO;
435 goto out_unregister; 414 goto out_path;
436 } 415 }
437 /* 416 /*
438 * Wait for connection confirmation 417 * Wait for connection confirmation
@@ -444,24 +423,23 @@ mon_open(struct inode *inode, struct file *filp)
444 atomic_set(&monpriv->iucv_severed, 0); 423 atomic_set(&monpriv->iucv_severed, 0);
445 atomic_set(&monpriv->iucv_connected, 0); 424 atomic_set(&monpriv->iucv_connected, 0);
446 rc = -EIO; 425 rc = -EIO;
447 goto out_unregister; 426 goto out_path;
448 } 427 }
449 P_INFO("open, established connection to *MONITOR service\n\n"); 428 P_INFO("open, established connection to *MONITOR service\n\n");
450 filp->private_data = monpriv; 429 filp->private_data = monpriv;
451 return nonseekable_open(inode, filp); 430 return nonseekable_open(inode, filp);
452 431
453out_unregister: 432out_path:
454 iucv_unregister_program(monpriv->iucv_handle); 433 kfree(monpriv->path);
455out_error: 434out_priv:
456 for (i = 0; i < MON_MSGLIM; i++) 435 mon_free_mem(monpriv);
457 kfree(monpriv->msg_array[i]); 436out_use:
458 kfree(monpriv);
459 clear_bit(MON_IN_USE, &mon_in_use); 437 clear_bit(MON_IN_USE, &mon_in_use);
438out:
460 return rc; 439 return rc;
461} 440}
462 441
463static int 442static int mon_close(struct inode *inode, struct file *filp)
464mon_close(struct inode *inode, struct file *filp)
465{ 443{
466 int rc, i; 444 int rc, i;
467 struct mon_private *monpriv = filp->private_data; 445 struct mon_private *monpriv = filp->private_data;
@@ -469,18 +447,12 @@ mon_close(struct inode *inode, struct file *filp)
469 /* 447 /*
470 * Close IUCV connection and unregister 448 * Close IUCV connection and unregister
471 */ 449 */
472 rc = iucv_sever(monpriv->pathid, user_data_sever); 450 rc = iucv_path_sever(monpriv->path, user_data_sever);
473 if (rc) 451 if (rc)
474 P_ERROR("close, iucv_sever failed with rc = %i\n", rc); 452 P_ERROR("close, iucv_sever failed with rc = %i\n", rc);
475 else 453 else
476 P_INFO("close, terminated connection to *MONITOR service\n"); 454 P_INFO("close, terminated connection to *MONITOR service\n");
477 455
478 rc = iucv_unregister_program(monpriv->iucv_handle);
479 if (rc)
480 P_ERROR("close, iucv_unregister failed with rc = %i\n", rc);
481 else
482 P_INFO("close, unregistered with IUCV\n");
483
484 atomic_set(&monpriv->iucv_severed, 0); 456 atomic_set(&monpriv->iucv_severed, 0);
485 atomic_set(&monpriv->iucv_connected, 0); 457 atomic_set(&monpriv->iucv_connected, 0);
486 atomic_set(&monpriv->read_ready, 0); 458 atomic_set(&monpriv->read_ready, 0);
@@ -495,8 +467,8 @@ mon_close(struct inode *inode, struct file *filp)
495 return 0; 467 return 0;
496} 468}
497 469
498static ssize_t 470static ssize_t mon_read(struct file *filp, char __user *data,
499mon_read(struct file *filp, char __user *data, size_t count, loff_t *ppos) 471 size_t count, loff_t *ppos)
500{ 472{
501 struct mon_private *monpriv = filp->private_data; 473 struct mon_private *monpriv = filp->private_data;
502 struct mon_msg *monmsg; 474 struct mon_msg *monmsg;
@@ -563,8 +535,7 @@ out_copy:
563 return count; 535 return count;
564} 536}
565 537
566static unsigned int 538static unsigned int mon_poll(struct file *filp, struct poll_table_struct *p)
567mon_poll(struct file *filp, struct poll_table_struct *p)
568{ 539{
569 struct mon_private *monpriv = filp->private_data; 540 struct mon_private *monpriv = filp->private_data;
570 541
@@ -593,8 +564,7 @@ static struct miscdevice mon_dev = {
593/****************************************************************************** 564/******************************************************************************
594 * module init/exit * 565 * module init/exit *
595 *****************************************************************************/ 566 *****************************************************************************/
596static int __init 567static int __init mon_init(void)
597mon_init(void)
598{ 568{
599 int rc; 569 int rc;
600 570
@@ -603,22 +573,34 @@ mon_init(void)
603 return -ENODEV; 573 return -ENODEV;
604 } 574 }
605 575
576 /*
577 * Register with IUCV and connect to *MONITOR service
578 */
579 rc = iucv_register(&monreader_iucv_handler, 1);
580 if (rc) {
581 P_ERROR("failed to register with iucv driver\n");
582 return rc;
583 }
584 P_INFO("open, registered with IUCV\n");
585
606 rc = segment_type(mon_dcss_name); 586 rc = segment_type(mon_dcss_name);
607 if (rc < 0) { 587 if (rc < 0) {
608 mon_segment_warn(rc, mon_dcss_name); 588 mon_segment_warn(rc, mon_dcss_name);
609 return rc; 589 goto out_iucv;
610 } 590 }
611 if (rc != SEG_TYPE_SC) { 591 if (rc != SEG_TYPE_SC) {
612 P_ERROR("segment %s has unsupported type, should be SC\n", 592 P_ERROR("segment %s has unsupported type, should be SC\n",
613 mon_dcss_name); 593 mon_dcss_name);
614 return -EINVAL; 594 rc = -EINVAL;
595 goto out_iucv;
615 } 596 }
616 597
617 rc = segment_load(mon_dcss_name, SEGMENT_SHARED, 598 rc = segment_load(mon_dcss_name, SEGMENT_SHARED,
618 &mon_dcss_start, &mon_dcss_end); 599 &mon_dcss_start, &mon_dcss_end);
619 if (rc < 0) { 600 if (rc < 0) {
620 mon_segment_warn(rc, mon_dcss_name); 601 mon_segment_warn(rc, mon_dcss_name);
621 return -EINVAL; 602 rc = -EINVAL;
603 goto out_iucv;
622 } 604 }
623 dcss_mkname(mon_dcss_name, &user_data_connect[8]); 605 dcss_mkname(mon_dcss_name, &user_data_connect[8]);
624 606
@@ -634,14 +616,16 @@ mon_init(void)
634 616
635out: 617out:
636 segment_unload(mon_dcss_name); 618 segment_unload(mon_dcss_name);
619out_iucv:
620 iucv_unregister(&monreader_iucv_handler, 1);
637 return rc; 621 return rc;
638} 622}
639 623
640static void __exit 624static void __exit mon_exit(void)
641mon_exit(void)
642{ 625{
643 segment_unload(mon_dcss_name); 626 segment_unload(mon_dcss_name);
644 WARN_ON(misc_deregister(&mon_dev) != 0); 627 WARN_ON(misc_deregister(&mon_dev) != 0);
628 iucv_unregister(&monreader_iucv_handler, 1);
645 return; 629 return;
646} 630}
647 631
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index 4f894dc2373b..8432a76b961e 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -3,7 +3,7 @@
3 * character device driver for reading z/VM system service records 3 * character device driver for reading z/VM system service records
4 * 4 *
5 * 5 *
6 * Copyright (C) 2004 IBM Corporation 6 * Copyright 2004 IBM Corporation
7 * character device driver for reading z/VM system service records, 7 * character device driver for reading z/VM system service records,
8 * Version 1.0 8 * Version 1.0
9 * Author(s): Xenia Tkatschow <xenia@us.ibm.com> 9 * Author(s): Xenia Tkatschow <xenia@us.ibm.com>
@@ -21,7 +21,7 @@
21#include <asm/cpcmd.h> 21#include <asm/cpcmd.h>
22#include <asm/debug.h> 22#include <asm/debug.h>
23#include <asm/ebcdic.h> 23#include <asm/ebcdic.h>
24#include "../net/iucv.h" 24#include <net/iucv/iucv.h>
25#include <linux/kmod.h> 25#include <linux/kmod.h>
26#include <linux/cdev.h> 26#include <linux/cdev.h>
27#include <linux/device.h> 27#include <linux/device.h>
@@ -60,12 +60,11 @@ struct vmlogrdr_priv_t {
60 char system_service[8]; 60 char system_service[8];
61 char internal_name[8]; 61 char internal_name[8];
62 char recording_name[8]; 62 char recording_name[8];
63 u16 pathid; 63 struct iucv_path *path;
64 int connection_established; 64 int connection_established;
65 int iucv_path_severed; 65 int iucv_path_severed;
66 iucv_MessagePending local_interrupt_buffer; 66 struct iucv_message local_interrupt_buffer;
67 atomic_t receive_ready; 67 atomic_t receive_ready;
68 iucv_handle_t iucv_handle;
69 int minor_num; 68 int minor_num;
70 char * buffer; 69 char * buffer;
71 char * current_position; 70 char * current_position;
@@ -97,37 +96,19 @@ static struct file_operations vmlogrdr_fops = {
97}; 96};
98 97
99 98
100static u8 iucvMagic[16] = { 99static void vmlogrdr_iucv_path_complete(struct iucv_path *, u8 ipuser[16]);
101 0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 100static void vmlogrdr_iucv_path_severed(struct iucv_path *, u8 ipuser[16]);
102 0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 101static void vmlogrdr_iucv_message_pending(struct iucv_path *,
103}; 102 struct iucv_message *);
104 103
105 104
106static u8 mask[] = { 105static struct iucv_handler vmlogrdr_iucv_handler = {
107 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 106 .path_complete = vmlogrdr_iucv_path_complete,
108 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 107 .path_severed = vmlogrdr_iucv_path_severed,
109 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 108 .message_pending = vmlogrdr_iucv_message_pending,
110 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
111}; 109};
112 110
113 111
114static u8 iucv_host[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
115
116
117static void
118vmlogrdr_iucv_ConnectionComplete(iucv_ConnectionComplete *eib, void *pgm_data);
119static void
120vmlogrdr_iucv_ConnectionSevered(iucv_ConnectionSevered *eib, void *pgm_data);
121static void
122vmlogrdr_iucv_MessagePending(iucv_MessagePending *eib, void *pgm_data);
123
124
125static iucv_interrupt_ops_t vmlogrdr_iucvops = {
126 .ConnectionComplete = vmlogrdr_iucv_ConnectionComplete,
127 .ConnectionSevered = vmlogrdr_iucv_ConnectionSevered,
128 .MessagePending = vmlogrdr_iucv_MessagePending,
129};
130
131static DECLARE_WAIT_QUEUE_HEAD(conn_wait_queue); 112static DECLARE_WAIT_QUEUE_HEAD(conn_wait_queue);
132static DECLARE_WAIT_QUEUE_HEAD(read_wait_queue); 113static DECLARE_WAIT_QUEUE_HEAD(read_wait_queue);
133 114
@@ -176,28 +157,29 @@ static struct cdev *vmlogrdr_cdev = NULL;
176static int recording_class_AB; 157static int recording_class_AB;
177 158
178 159
179static void 160static void vmlogrdr_iucv_path_complete(struct iucv_path *path, u8 ipuser[16])
180vmlogrdr_iucv_ConnectionComplete (iucv_ConnectionComplete * eib,
181 void * pgm_data)
182{ 161{
183 struct vmlogrdr_priv_t * logptr = pgm_data; 162 struct vmlogrdr_priv_t * logptr = path->private;
163
184 spin_lock(&logptr->priv_lock); 164 spin_lock(&logptr->priv_lock);
185 logptr->connection_established = 1; 165 logptr->connection_established = 1;
186 spin_unlock(&logptr->priv_lock); 166 spin_unlock(&logptr->priv_lock);
187 wake_up(&conn_wait_queue); 167 wake_up(&conn_wait_queue);
188 return;
189} 168}
190 169
191 170
192static void 171static void vmlogrdr_iucv_path_severed(struct iucv_path *path, u8 ipuser[16])
193vmlogrdr_iucv_ConnectionSevered (iucv_ConnectionSevered * eib, void * pgm_data)
194{ 172{
195 u8 reason = (u8) eib->ipuser[8]; 173 struct vmlogrdr_priv_t * logptr = path->private;
196 struct vmlogrdr_priv_t * logptr = pgm_data; 174 u8 reason = (u8) ipuser[8];
197 175
198 printk (KERN_ERR "vmlogrdr: connection severed with" 176 printk (KERN_ERR "vmlogrdr: connection severed with"
199 " reason %i\n", reason); 177 " reason %i\n", reason);
200 178
179 iucv_path_sever(path, NULL);
180 kfree(path);
181 logptr->path = NULL;
182
201 spin_lock(&logptr->priv_lock); 183 spin_lock(&logptr->priv_lock);
202 logptr->connection_established = 0; 184 logptr->connection_established = 0;
203 logptr->iucv_path_severed = 1; 185 logptr->iucv_path_severed = 1;
@@ -209,10 +191,10 @@ vmlogrdr_iucv_ConnectionSevered (iucv_ConnectionSevered * eib, void * pgm_data)
209} 191}
210 192
211 193
212static void 194static void vmlogrdr_iucv_message_pending(struct iucv_path *path,
213vmlogrdr_iucv_MessagePending (iucv_MessagePending * eib, void * pgm_data) 195 struct iucv_message *msg)
214{ 196{
215 struct vmlogrdr_priv_t * logptr = pgm_data; 197 struct vmlogrdr_priv_t * logptr = path->private;
216 198
217 /* 199 /*
218 * This function is the bottom half so it should be quick. 200 * This function is the bottom half so it should be quick.
@@ -220,15 +202,15 @@ vmlogrdr_iucv_MessagePending (iucv_MessagePending * eib, void * pgm_data)
220 * the usage count 202 * the usage count
221 */ 203 */
222 spin_lock(&logptr->priv_lock); 204 spin_lock(&logptr->priv_lock);
223 memcpy(&(logptr->local_interrupt_buffer), eib, sizeof(*eib)); 205 memcpy(&logptr->local_interrupt_buffer, msg, sizeof(*msg));
224 atomic_inc(&logptr->receive_ready); 206 atomic_inc(&logptr->receive_ready);
225 spin_unlock(&logptr->priv_lock); 207 spin_unlock(&logptr->priv_lock);
226 wake_up_interruptible(&read_wait_queue); 208 wake_up_interruptible(&read_wait_queue);
227} 209}
228 210
229 211
230static int 212static int vmlogrdr_get_recording_class_AB(void)
231vmlogrdr_get_recording_class_AB(void) { 213{
232 char cp_command[]="QUERY COMMAND RECORDING "; 214 char cp_command[]="QUERY COMMAND RECORDING ";
233 char cp_response[80]; 215 char cp_response[80];
234 char *tail; 216 char *tail;
@@ -258,8 +240,9 @@ vmlogrdr_get_recording_class_AB(void) {
258} 240}
259 241
260 242
261static int 243static int vmlogrdr_recording(struct vmlogrdr_priv_t * logptr,
262vmlogrdr_recording(struct vmlogrdr_priv_t * logptr, int action, int purge) { 244 int action, int purge)
245{
263 246
264 char cp_command[80]; 247 char cp_command[80];
265 char cp_response[160]; 248 char cp_response[160];
@@ -317,8 +300,7 @@ vmlogrdr_recording(struct vmlogrdr_priv_t * logptr, int action, int purge) {
317} 300}
318 301
319 302
320static int 303static int vmlogrdr_open (struct inode *inode, struct file *filp)
321vmlogrdr_open (struct inode *inode, struct file *filp)
322{ 304{
323 int dev_num = 0; 305 int dev_num = 0;
324 struct vmlogrdr_priv_t * logptr = NULL; 306 struct vmlogrdr_priv_t * logptr = NULL;
@@ -328,10 +310,7 @@ vmlogrdr_open (struct inode *inode, struct file *filp)
328 dev_num = iminor(inode); 310 dev_num = iminor(inode);
329 if (dev_num > MAXMINOR) 311 if (dev_num > MAXMINOR)
330 return -ENODEV; 312 return -ENODEV;
331
332 logptr = &sys_ser[dev_num]; 313 logptr = &sys_ser[dev_num];
333 if (logptr == NULL)
334 return -ENODEV;
335 314
336 /* 315 /*
337 * only allow for blocking reads to be open 316 * only allow for blocking reads to be open
@@ -344,52 +323,38 @@ vmlogrdr_open (struct inode *inode, struct file *filp)
344 if (logptr->dev_in_use) { 323 if (logptr->dev_in_use) {
345 spin_unlock_bh(&logptr->priv_lock); 324 spin_unlock_bh(&logptr->priv_lock);
346 return -EBUSY; 325 return -EBUSY;
347 } else {
348 logptr->dev_in_use = 1;
349 spin_unlock_bh(&logptr->priv_lock);
350 } 326 }
351 327 logptr->dev_in_use = 1;
328 logptr->connection_established = 0;
329 logptr->iucv_path_severed = 0;
352 atomic_set(&logptr->receive_ready, 0); 330 atomic_set(&logptr->receive_ready, 0);
353 logptr->buffer_free = 1; 331 logptr->buffer_free = 1;
332 spin_unlock_bh(&logptr->priv_lock);
354 333
355 /* set the file options */ 334 /* set the file options */
356 filp->private_data = logptr; 335 filp->private_data = logptr;
357 filp->f_op = &vmlogrdr_fops; 336 filp->f_op = &vmlogrdr_fops;
358 337
359 /* start recording for this service*/ 338 /* start recording for this service*/
360 ret=0; 339 if (logptr->autorecording) {
361 if (logptr->autorecording)
362 ret = vmlogrdr_recording(logptr,1,logptr->autopurge); 340 ret = vmlogrdr_recording(logptr,1,logptr->autopurge);
363 if (ret) 341 if (ret)
364 printk (KERN_WARNING "vmlogrdr: failed to start " 342 printk (KERN_WARNING "vmlogrdr: failed to start "
365 "recording automatically\n"); 343 "recording automatically\n");
366
367 /* Register with iucv driver */
368 logptr->iucv_handle = iucv_register_program(iucvMagic,
369 logptr->system_service, mask, &vmlogrdr_iucvops,
370 logptr);
371
372 if (logptr->iucv_handle == NULL) {
373 printk (KERN_ERR "vmlogrdr: failed to register with"
374 "iucv driver\n");
375 goto not_registered;
376 } 344 }
377 345
378 /* create connection to the system service */ 346 /* create connection to the system service */
379 spin_lock_bh(&logptr->priv_lock); 347 logptr->path = iucv_path_alloc(10, 0, GFP_KERNEL);
380 logptr->connection_established = 0; 348 if (!logptr->path)
381 logptr->iucv_path_severed = 0; 349 goto out_dev;
382 spin_unlock_bh(&logptr->priv_lock); 350 connect_rc = iucv_path_connect(logptr->path, &vmlogrdr_iucv_handler,
383 351 logptr->system_service, NULL, NULL,
384 connect_rc = iucv_connect (&(logptr->pathid), 10, iucvMagic, 352 logptr);
385 logptr->system_service, iucv_host, 0,
386 NULL, NULL,
387 logptr->iucv_handle, NULL);
388 if (connect_rc) { 353 if (connect_rc) {
389 printk (KERN_ERR "vmlogrdr: iucv connection to %s " 354 printk (KERN_ERR "vmlogrdr: iucv connection to %s "
390 "failed with rc %i \n", logptr->system_service, 355 "failed with rc %i \n", logptr->system_service,
391 connect_rc); 356 connect_rc);
392 goto not_connected; 357 goto out_path;
393 } 358 }
394 359
395 /* We've issued the connect and now we must wait for a 360 /* We've issued the connect and now we must wait for a
@@ -398,35 +363,28 @@ vmlogrdr_open (struct inode *inode, struct file *filp)
398 */ 363 */
399 wait_event(conn_wait_queue, (logptr->connection_established) 364 wait_event(conn_wait_queue, (logptr->connection_established)
400 || (logptr->iucv_path_severed)); 365 || (logptr->iucv_path_severed));
401 if (logptr->iucv_path_severed) { 366 if (logptr->iucv_path_severed)
402 goto not_connected; 367 goto out_record;
403 }
404
405 return nonseekable_open(inode, filp); 368 return nonseekable_open(inode, filp);
406 369
407not_connected: 370out_record:
408 iucv_unregister_program(logptr->iucv_handle);
409 logptr->iucv_handle = NULL;
410not_registered:
411 if (logptr->autorecording) 371 if (logptr->autorecording)
412 vmlogrdr_recording(logptr,0,logptr->autopurge); 372 vmlogrdr_recording(logptr,0,logptr->autopurge);
373out_path:
374 kfree(logptr->path); /* kfree(NULL) is ok. */
375 logptr->path = NULL;
376out_dev:
413 logptr->dev_in_use = 0; 377 logptr->dev_in_use = 0;
414 return -EIO; 378 return -EIO;
415
416
417} 379}
418 380
419 381
420static int 382static int vmlogrdr_release (struct inode *inode, struct file *filp)
421vmlogrdr_release (struct inode *inode, struct file *filp)
422{ 383{
423 int ret; 384 int ret;
424 385
425 struct vmlogrdr_priv_t * logptr = filp->private_data; 386 struct vmlogrdr_priv_t * logptr = filp->private_data;
426 387
427 iucv_unregister_program(logptr->iucv_handle);
428 logptr->iucv_handle = NULL;
429
430 if (logptr->autorecording) { 388 if (logptr->autorecording) {
431 ret = vmlogrdr_recording(logptr,0,logptr->autopurge); 389 ret = vmlogrdr_recording(logptr,0,logptr->autopurge);
432 if (ret) 390 if (ret)
@@ -439,8 +397,8 @@ vmlogrdr_release (struct inode *inode, struct file *filp)
439} 397}
440 398
441 399
442static int 400static int vmlogrdr_receive_data(struct vmlogrdr_priv_t *priv)
443vmlogrdr_receive_data(struct vmlogrdr_priv_t *priv) { 401{
444 int rc, *temp; 402 int rc, *temp;
445 /* we need to keep track of two data sizes here: 403 /* we need to keep track of two data sizes here:
446 * The number of bytes we need to receive from iucv and 404 * The number of bytes we need to receive from iucv and
@@ -461,8 +419,7 @@ vmlogrdr_receive_data(struct vmlogrdr_priv_t *priv) {
461 * We need to return the total length of the record 419 * We need to return the total length of the record
462 * + size of FENCE in the first 4 bytes of the buffer. 420 * + size of FENCE in the first 4 bytes of the buffer.
463 */ 421 */
464 iucv_data_count = 422 iucv_data_count = priv->local_interrupt_buffer.length;
465 priv->local_interrupt_buffer.ln1msg2.ipbfln1f;
466 user_data_count = sizeof(int); 423 user_data_count = sizeof(int);
467 temp = (int*)priv->buffer; 424 temp = (int*)priv->buffer;
468 *temp= iucv_data_count + sizeof(FENCE); 425 *temp= iucv_data_count + sizeof(FENCE);
@@ -474,14 +431,10 @@ vmlogrdr_receive_data(struct vmlogrdr_priv_t *priv) {
474 */ 431 */
475 if (iucv_data_count > NET_BUFFER_SIZE) 432 if (iucv_data_count > NET_BUFFER_SIZE)
476 iucv_data_count = NET_BUFFER_SIZE; 433 iucv_data_count = NET_BUFFER_SIZE;
477 rc = iucv_receive(priv->pathid, 434 rc = iucv_message_receive(priv->path,
478 priv->local_interrupt_buffer.ipmsgid, 435 &priv->local_interrupt_buffer,
479 priv->local_interrupt_buffer.iptrgcls, 436 0, buffer, iucv_data_count,
480 buffer, 437 &priv->residual_length);
481 iucv_data_count,
482 NULL,
483 NULL,
484 &priv->residual_length);
485 spin_unlock_bh(&priv->priv_lock); 438 spin_unlock_bh(&priv->priv_lock);
486 /* An rc of 5 indicates that the record was bigger then 439 /* An rc of 5 indicates that the record was bigger then
487 * the buffer, which is OK for us. A 9 indicates that the 440 * the buffer, which is OK for us. A 9 indicates that the
@@ -513,8 +466,8 @@ vmlogrdr_receive_data(struct vmlogrdr_priv_t *priv) {
513} 466}
514 467
515 468
516static ssize_t 469static ssize_t vmlogrdr_read(struct file *filp, char __user *data,
517vmlogrdr_read(struct file *filp, char __user *data, size_t count, loff_t * ppos) 470 size_t count, loff_t * ppos)
518{ 471{
519 int rc; 472 int rc;
520 struct vmlogrdr_priv_t * priv = filp->private_data; 473 struct vmlogrdr_priv_t * priv = filp->private_data;
@@ -546,8 +499,10 @@ vmlogrdr_read(struct file *filp, char __user *data, size_t count, loff_t * ppos)
546 return count; 499 return count;
547} 500}
548 501
549static ssize_t 502static ssize_t vmlogrdr_autopurge_store(struct device * dev,
550vmlogrdr_autopurge_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t count) { 503 struct device_attribute *attr,
504 const char * buf, size_t count)
505{
551 struct vmlogrdr_priv_t *priv = dev->driver_data; 506 struct vmlogrdr_priv_t *priv = dev->driver_data;
552 ssize_t ret = count; 507 ssize_t ret = count;
553 508
@@ -565,8 +520,10 @@ vmlogrdr_autopurge_store(struct device * dev, struct device_attribute *attr, con
565} 520}
566 521
567 522
568static ssize_t 523static ssize_t vmlogrdr_autopurge_show(struct device *dev,
569vmlogrdr_autopurge_show(struct device *dev, struct device_attribute *attr, char *buf) { 524 struct device_attribute *attr,
525 char *buf)
526{
570 struct vmlogrdr_priv_t *priv = dev->driver_data; 527 struct vmlogrdr_priv_t *priv = dev->driver_data;
571 return sprintf(buf, "%u\n", priv->autopurge); 528 return sprintf(buf, "%u\n", priv->autopurge);
572} 529}
@@ -576,8 +533,10 @@ static DEVICE_ATTR(autopurge, 0644, vmlogrdr_autopurge_show,
576 vmlogrdr_autopurge_store); 533 vmlogrdr_autopurge_store);
577 534
578 535
579static ssize_t 536static ssize_t vmlogrdr_purge_store(struct device * dev,
580vmlogrdr_purge_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t count) { 537 struct device_attribute *attr,
538 const char * buf, size_t count)
539{
581 540
582 char cp_command[80]; 541 char cp_command[80];
583 char cp_response[80]; 542 char cp_response[80];
@@ -617,9 +576,10 @@ vmlogrdr_purge_store(struct device * dev, struct device_attribute *attr, const c
617static DEVICE_ATTR(purge, 0200, NULL, vmlogrdr_purge_store); 576static DEVICE_ATTR(purge, 0200, NULL, vmlogrdr_purge_store);
618 577
619 578
620static ssize_t 579static ssize_t vmlogrdr_autorecording_store(struct device *dev,
621vmlogrdr_autorecording_store(struct device *dev, struct device_attribute *attr, const char *buf, 580 struct device_attribute *attr,
622 size_t count) { 581 const char *buf, size_t count)
582{
623 struct vmlogrdr_priv_t *priv = dev->driver_data; 583 struct vmlogrdr_priv_t *priv = dev->driver_data;
624 ssize_t ret = count; 584 ssize_t ret = count;
625 585
@@ -637,8 +597,10 @@ vmlogrdr_autorecording_store(struct device *dev, struct device_attribute *attr,
637} 597}
638 598
639 599
640static ssize_t 600static ssize_t vmlogrdr_autorecording_show(struct device *dev,
641vmlogrdr_autorecording_show(struct device *dev, struct device_attribute *attr, char *buf) { 601 struct device_attribute *attr,
602 char *buf)
603{
642 struct vmlogrdr_priv_t *priv = dev->driver_data; 604 struct vmlogrdr_priv_t *priv = dev->driver_data;
643 return sprintf(buf, "%u\n", priv->autorecording); 605 return sprintf(buf, "%u\n", priv->autorecording);
644} 606}
@@ -648,9 +610,10 @@ static DEVICE_ATTR(autorecording, 0644, vmlogrdr_autorecording_show,
648 vmlogrdr_autorecording_store); 610 vmlogrdr_autorecording_store);
649 611
650 612
651static ssize_t 613static ssize_t vmlogrdr_recording_store(struct device * dev,
652vmlogrdr_recording_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t count) { 614 struct device_attribute *attr,
653 615 const char * buf, size_t count)
616{
654 struct vmlogrdr_priv_t *priv = dev->driver_data; 617 struct vmlogrdr_priv_t *priv = dev->driver_data;
655 ssize_t ret; 618 ssize_t ret;
656 619
@@ -675,8 +638,9 @@ vmlogrdr_recording_store(struct device * dev, struct device_attribute *attr, con
675static DEVICE_ATTR(recording, 0200, NULL, vmlogrdr_recording_store); 638static DEVICE_ATTR(recording, 0200, NULL, vmlogrdr_recording_store);
676 639
677 640
678static ssize_t 641static ssize_t vmlogrdr_recording_status_show(struct device_driver *driver,
679vmlogrdr_recording_status_show(struct device_driver *driver, char *buf) { 642 char *buf)
643{
680 644
681 char cp_command[] = "QUERY RECORDING "; 645 char cp_command[] = "QUERY RECORDING ";
682 int len; 646 int len;
@@ -709,52 +673,63 @@ static struct device_driver vmlogrdr_driver = {
709}; 673};
710 674
711 675
712static int 676static int vmlogrdr_register_driver(void)
713vmlogrdr_register_driver(void) { 677{
714 int ret; 678 int ret;
715 679
680 /* Register with iucv driver */
681 ret = iucv_register(&vmlogrdr_iucv_handler, 1);
682 if (ret) {
683 printk (KERN_ERR "vmlogrdr: failed to register with"
684 "iucv driver\n");
685 goto out;
686 }
687
716 ret = driver_register(&vmlogrdr_driver); 688 ret = driver_register(&vmlogrdr_driver);
717 if (ret) { 689 if (ret) {
718 printk(KERN_ERR "vmlogrdr: failed to register driver.\n"); 690 printk(KERN_ERR "vmlogrdr: failed to register driver.\n");
719 return ret; 691 goto out_iucv;
720 } 692 }
721 693
722 ret = driver_create_file(&vmlogrdr_driver, 694 ret = driver_create_file(&vmlogrdr_driver,
723 &driver_attr_recording_status); 695 &driver_attr_recording_status);
724 if (ret) { 696 if (ret) {
725 printk(KERN_ERR "vmlogrdr: failed to add driver attribute.\n"); 697 printk(KERN_ERR "vmlogrdr: failed to add driver attribute.\n");
726 goto unregdriver; 698 goto out_driver;
727 } 699 }
728 700
729 vmlogrdr_class = class_create(THIS_MODULE, "vmlogrdr"); 701 vmlogrdr_class = class_create(THIS_MODULE, "vmlogrdr");
730 if (IS_ERR(vmlogrdr_class)) { 702 if (IS_ERR(vmlogrdr_class)) {
731 printk(KERN_ERR "vmlogrdr: failed to create class.\n"); 703 printk(KERN_ERR "vmlogrdr: failed to create class.\n");
732 ret=PTR_ERR(vmlogrdr_class); 704 ret = PTR_ERR(vmlogrdr_class);
733 vmlogrdr_class=NULL; 705 vmlogrdr_class = NULL;
734 goto unregattr; 706 goto out_attr;
735 } 707 }
736 return 0; 708 return 0;
737 709
738unregattr: 710out_attr:
739 driver_remove_file(&vmlogrdr_driver, &driver_attr_recording_status); 711 driver_remove_file(&vmlogrdr_driver, &driver_attr_recording_status);
740unregdriver: 712out_driver:
741 driver_unregister(&vmlogrdr_driver); 713 driver_unregister(&vmlogrdr_driver);
714out_iucv:
715 iucv_unregister(&vmlogrdr_iucv_handler, 1);
716out:
742 return ret; 717 return ret;
743} 718}
744 719
745 720
746static void 721static void vmlogrdr_unregister_driver(void)
747vmlogrdr_unregister_driver(void) { 722{
748 class_destroy(vmlogrdr_class); 723 class_destroy(vmlogrdr_class);
749 vmlogrdr_class = NULL; 724 vmlogrdr_class = NULL;
750 driver_remove_file(&vmlogrdr_driver, &driver_attr_recording_status); 725 driver_remove_file(&vmlogrdr_driver, &driver_attr_recording_status);
751 driver_unregister(&vmlogrdr_driver); 726 driver_unregister(&vmlogrdr_driver);
752 return; 727 iucv_unregister(&vmlogrdr_iucv_handler, 1);
753} 728}
754 729
755 730
756static int 731static int vmlogrdr_register_device(struct vmlogrdr_priv_t *priv)
757vmlogrdr_register_device(struct vmlogrdr_priv_t *priv) { 732{
758 struct device *dev; 733 struct device *dev;
759 int ret; 734 int ret;
760 735
@@ -803,9 +778,10 @@ vmlogrdr_register_device(struct vmlogrdr_priv_t *priv) {
803} 778}
804 779
805 780
806static int 781static int vmlogrdr_unregister_device(struct vmlogrdr_priv_t *priv)
807vmlogrdr_unregister_device(struct vmlogrdr_priv_t *priv ) { 782{
808 class_device_destroy(vmlogrdr_class, MKDEV(vmlogrdr_major, priv->minor_num)); 783 class_device_destroy(vmlogrdr_class,
784 MKDEV(vmlogrdr_major, priv->minor_num));
809 if (priv->device != NULL) { 785 if (priv->device != NULL) {
810 sysfs_remove_group(&priv->device->kobj, &vmlogrdr_attr_group); 786 sysfs_remove_group(&priv->device->kobj, &vmlogrdr_attr_group);
811 device_unregister(priv->device); 787 device_unregister(priv->device);
@@ -815,8 +791,8 @@ vmlogrdr_unregister_device(struct vmlogrdr_priv_t *priv ) {
815} 791}
816 792
817 793
818static int 794static int vmlogrdr_register_cdev(dev_t dev)
819vmlogrdr_register_cdev(dev_t dev) { 795{
820 int rc = 0; 796 int rc = 0;
821 vmlogrdr_cdev = cdev_alloc(); 797 vmlogrdr_cdev = cdev_alloc();
822 if (!vmlogrdr_cdev) { 798 if (!vmlogrdr_cdev) {
@@ -836,9 +812,10 @@ vmlogrdr_register_cdev(dev_t dev) {
836} 812}
837 813
838 814
839static void 815static void vmlogrdr_cleanup(void)
840vmlogrdr_cleanup(void) { 816{
841 int i; 817 int i;
818
842 if (vmlogrdr_cdev) { 819 if (vmlogrdr_cdev) {
843 cdev_del(vmlogrdr_cdev); 820 cdev_del(vmlogrdr_cdev);
844 vmlogrdr_cdev=NULL; 821 vmlogrdr_cdev=NULL;
@@ -855,8 +832,7 @@ vmlogrdr_cleanup(void) {
855} 832}
856 833
857 834
858static int 835static int vmlogrdr_init(void)
859vmlogrdr_init(void)
860{ 836{
861 int rc; 837 int rc;
862 int i; 838 int i;
@@ -906,8 +882,7 @@ cleanup:
906} 882}
907 883
908 884
909static void 885static void vmlogrdr_exit(void)
910vmlogrdr_exit(void)
911{ 886{
912 vmlogrdr_cleanup(); 887 vmlogrdr_cleanup();
913 printk (KERN_INFO "vmlogrdr: driver unloaded\n"); 888 printk (KERN_INFO "vmlogrdr: driver unloaded\n");
diff --git a/drivers/s390/net/Kconfig b/drivers/s390/net/Kconfig
index 52625153a4f0..f98fa465df0a 100644
--- a/drivers/s390/net/Kconfig
+++ b/drivers/s390/net/Kconfig
@@ -22,13 +22,6 @@ config CTC
22 available. This option is also available as a module which will be 22 available. This option is also available as a module which will be
23 called ctc.ko. If you do not know what it is, it's safe to say "Y". 23 called ctc.ko. If you do not know what it is, it's safe to say "Y".
24 24
25config IUCV
26 tristate "IUCV support (VM only)"
27 help
28 Select this option if you want to use inter-user communication
29 under VM or VIF. If unsure, say "Y" to enable a fast communication
30 link between VM guests.
31
32config NETIUCV 25config NETIUCV
33 tristate "IUCV network device support (VM only)" 26 tristate "IUCV network device support (VM only)"
34 depends on IUCV && NETDEVICES 27 depends on IUCV && NETDEVICES
diff --git a/drivers/s390/net/Makefile b/drivers/s390/net/Makefile
index 4777e36a922f..bbe3ab2e93d9 100644
--- a/drivers/s390/net/Makefile
+++ b/drivers/s390/net/Makefile
@@ -4,7 +4,6 @@
4 4
5ctc-objs := ctcmain.o ctcdbug.o 5ctc-objs := ctcmain.o ctcdbug.o
6 6
7obj-$(CONFIG_IUCV) += iucv.o
8obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o 7obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o
9obj-$(CONFIG_SMSGIUCV) += smsgiucv.o 8obj-$(CONFIG_SMSGIUCV) += smsgiucv.o
10obj-$(CONFIG_CTC) += ctc.o fsm.o cu3088.o 9obj-$(CONFIG_CTC) += ctc.o fsm.o cu3088.o
diff --git a/drivers/s390/net/iucv.c b/drivers/s390/net/iucv.c
deleted file mode 100644
index 229aeb5fc399..000000000000
--- a/drivers/s390/net/iucv.c
+++ /dev/null
@@ -1,2540 +0,0 @@
1/*
2 * IUCV network driver
3 *
4 * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
5 * Author(s):
6 * Original source:
7 * Alan Altmark (Alan_Altmark@us.ibm.com) Sept. 2000
8 * Xenia Tkatschow (xenia@us.ibm.com)
9 * 2Gb awareness and general cleanup:
10 * Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com)
11 *
12 * Documentation used:
13 * The original source
14 * CP Programming Service, IBM document # SC24-5760
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2, or (at your option)
19 * any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 *
30 */
31
32/* #define DEBUG */
33
34#include <linux/module.h>
35#include <linux/moduleparam.h>
36
37#include <linux/spinlock.h>
38#include <linux/kernel.h>
39#include <linux/slab.h>
40#include <linux/init.h>
41#include <linux/interrupt.h>
42#include <linux/list.h>
43#include <linux/errno.h>
44#include <linux/err.h>
45#include <linux/device.h>
46#include <asm/atomic.h>
47#include "iucv.h"
48#include <asm/io.h>
49#include <asm/s390_ext.h>
50#include <asm/ebcdic.h>
51#include <asm/smp.h>
52#include <asm/s390_rdev.h>
53
54/* FLAGS:
55 * All flags are defined in the field IPFLAGS1 of each function
56 * and can be found in CP Programming Services.
57 * IPSRCCLS - Indicates you have specified a source class
58 * IPFGMCL - Indicates you have specified a target class
59 * IPFGPID - Indicates you have specified a pathid
60 * IPFGMID - Indicates you have specified a message ID
61 * IPANSLST - Indicates that you are using an address list for
62 * reply data
63 * IPBUFLST - Indicates that you are using an address list for
64 * message data
65 */
66
67#define IPSRCCLS 0x01
68#define IPFGMCL 0x01
69#define IPFGPID 0x02
70#define IPFGMID 0x04
71#define IPANSLST 0x08
72#define IPBUFLST 0x40
73
74static int
75iucv_bus_match (struct device *dev, struct device_driver *drv)
76{
77 return 0;
78}
79
80struct bus_type iucv_bus = {
81 .name = "iucv",
82 .match = iucv_bus_match,
83};
84
85struct device *iucv_root;
86
87/* General IUCV interrupt structure */
88typedef struct {
89 __u16 ippathid;
90 __u8 res1;
91 __u8 iptype;
92 __u32 res2;
93 __u8 ipvmid[8];
94 __u8 res3[24];
95} iucv_GeneralInterrupt;
96
97static iucv_GeneralInterrupt *iucv_external_int_buffer = NULL;
98
99/* Spin Lock declaration */
100
101static DEFINE_SPINLOCK(iucv_lock);
102
103static int messagesDisabled = 0;
104
105/***************INTERRUPT HANDLING ***************/
106
107typedef struct {
108 struct list_head queue;
109 iucv_GeneralInterrupt data;
110} iucv_irqdata;
111
112static struct list_head iucv_irq_queue;
113static DEFINE_SPINLOCK(iucv_irq_queue_lock);
114
115/*
116 *Internal function prototypes
117 */
118static void iucv_tasklet_handler(unsigned long);
119static void iucv_irq_handler(__u16);
120
121static DECLARE_TASKLET(iucv_tasklet,iucv_tasklet_handler,0);
122
123/************ FUNCTION ID'S ****************************/
124
125#define ACCEPT 10
126#define CONNECT 11
127#define DECLARE_BUFFER 12
128#define PURGE 9
129#define QUERY 0
130#define QUIESCE 13
131#define RECEIVE 5
132#define REJECT 8
133#define REPLY 6
134#define RESUME 14
135#define RETRIEVE_BUFFER 2
136#define SEND 4
137#define SETMASK 16
138#define SEVER 15
139
140/**
141 * Structure: handler
142 * members: list - list management.
143 * structure: id
144 * userid - 8 char array of machine identification
145 * user_data - 16 char array for user identification
146 * mask - 24 char array used to compare the 2 previous
147 * interrupt_table - vector of interrupt functions.
148 * pgm_data - ulong, application data that is passed
149 * to the interrupt handlers
150*/
151typedef struct handler_t {
152 struct list_head list;
153 struct {
154 __u8 userid[8];
155 __u8 user_data[16];
156 __u8 mask[24];
157 } id;
158 iucv_interrupt_ops_t *interrupt_table;
159 void *pgm_data;
160} handler;
161
162/**
163 * iucv_handler_table: List of registered handlers.
164 */
165static struct list_head iucv_handler_table;
166
167/**
168 * iucv_pathid_table: an array of *handler pointing into
169 * iucv_handler_table for fast indexing by pathid;
170 */
171static handler **iucv_pathid_table;
172
173static unsigned long max_connections;
174
175/**
176 * iucv_cpuid: contains the logical cpu number of the cpu which
177 * has declared the iucv buffer by issuing DECLARE_BUFFER.
178 * If no cpu has done the initialization iucv_cpuid contains -1.
179 */
180static int iucv_cpuid = -1;
181/**
182 * register_flag: is 0 when external interrupt has not been registered
183 */
184static int register_flag;
185
186/****************FIVE 40-BYTE PARAMETER STRUCTURES******************/
187/* Data struct 1: iparml_control
188 * Used for iucv_accept
189 * iucv_connect
190 * iucv_quiesce
191 * iucv_resume
192 * iucv_sever
193 * iucv_retrieve_buffer
194 * Data struct 2: iparml_dpl (data in parameter list)
195 * Used for iucv_send_prmmsg
196 * iucv_send2way_prmmsg
197 * iucv_send2way_prmmsg_array
198 * iucv_reply_prmmsg
199 * Data struct 3: iparml_db (data in a buffer)
200 * Used for iucv_receive
201 * iucv_receive_array
202 * iucv_reject
203 * iucv_reply
204 * iucv_reply_array
205 * iucv_send
206 * iucv_send_array
207 * iucv_send2way
208 * iucv_send2way_array
209 * iucv_declare_buffer
210 * Data struct 4: iparml_purge
211 * Used for iucv_purge
212 * iucv_query
213 * Data struct 5: iparml_set_mask
214 * Used for iucv_set_mask
215 */
216
217typedef struct {
218 __u16 ippathid;
219 __u8 ipflags1;
220 __u8 iprcode;
221 __u16 ipmsglim;
222 __u16 res1;
223 __u8 ipvmid[8];
224 __u8 ipuser[16];
225 __u8 iptarget[8];
226} iparml_control;
227
228typedef struct {
229 __u16 ippathid;
230 __u8 ipflags1;
231 __u8 iprcode;
232 __u32 ipmsgid;
233 __u32 iptrgcls;
234 __u8 iprmmsg[8];
235 __u32 ipsrccls;
236 __u32 ipmsgtag;
237 __u32 ipbfadr2;
238 __u32 ipbfln2f;
239 __u32 res;
240} iparml_dpl;
241
242typedef struct {
243 __u16 ippathid;
244 __u8 ipflags1;
245 __u8 iprcode;
246 __u32 ipmsgid;
247 __u32 iptrgcls;
248 __u32 ipbfadr1;
249 __u32 ipbfln1f;
250 __u32 ipsrccls;
251 __u32 ipmsgtag;
252 __u32 ipbfadr2;
253 __u32 ipbfln2f;
254 __u32 res;
255} iparml_db;
256
257typedef struct {
258 __u16 ippathid;
259 __u8 ipflags1;
260 __u8 iprcode;
261 __u32 ipmsgid;
262 __u8 ipaudit[3];
263 __u8 res1[5];
264 __u32 res2;
265 __u32 ipsrccls;
266 __u32 ipmsgtag;
267 __u32 res3[3];
268} iparml_purge;
269
270typedef struct {
271 __u8 ipmask;
272 __u8 res1[2];
273 __u8 iprcode;
274 __u32 res2[9];
275} iparml_set_mask;
276
277typedef struct {
278 union {
279 iparml_control p_ctrl;
280 iparml_dpl p_dpl;
281 iparml_db p_db;
282 iparml_purge p_purge;
283 iparml_set_mask p_set_mask;
284 } param;
285 atomic_t in_use;
286 __u32 res;
287} __attribute__ ((aligned(8))) iucv_param;
288#define PARAM_POOL_SIZE (PAGE_SIZE / sizeof(iucv_param))
289
290static iucv_param * iucv_param_pool;
291
292MODULE_AUTHOR("(C) 2001 IBM Corp. by Fritz Elfert (felfert@millenux.com)");
293MODULE_DESCRIPTION("Linux for S/390 IUCV lowlevel driver");
294MODULE_LICENSE("GPL");
295
296/*
297 * Debugging stuff
298 *******************************************************************************/
299
300
301#ifdef DEBUG
302static int debuglevel = 0;
303
304module_param(debuglevel, int, 0);
305MODULE_PARM_DESC(debuglevel,
306 "Specifies the debug level (0=off ... 3=all)");
307
308static void
309iucv_dumpit(char *title, void *buf, int len)
310{
311 int i;
312 __u8 *p = (__u8 *)buf;
313
314 if (debuglevel < 3)
315 return;
316
317 printk(KERN_DEBUG "%s\n", title);
318 printk(" ");
319 for (i = 0; i < len; i++) {
320 if (!(i % 16) && i != 0)
321 printk ("\n ");
322 else if (!(i % 4) && i != 0)
323 printk(" ");
324 printk("%02X", *p++);
325 }
326 if (len % 16)
327 printk ("\n");
328 return;
329}
330#define iucv_debug(lvl, fmt, args...) \
331do { \
332 if (debuglevel >= lvl) \
333 printk(KERN_DEBUG "%s: " fmt "\n", __FUNCTION__ , ## args); \
334} while (0)
335
336#else
337
338#define iucv_debug(lvl, fmt, args...) do { } while (0)
339#define iucv_dumpit(title, buf, len) do { } while (0)
340
341#endif
342
343/*
344 * Internal functions
345 *******************************************************************************/
346
347/**
348 * print start banner
349 */
350static void
351iucv_banner(void)
352{
353 printk(KERN_INFO "IUCV lowlevel driver initialized\n");
354}
355
356/**
357 * iucv_init - Initialization
358 *
359 * Allocates and initializes various data structures.
360 */
361static int
362iucv_init(void)
363{
364 int ret;
365
366 if (iucv_external_int_buffer)
367 return 0;
368
369 if (!MACHINE_IS_VM) {
370 printk(KERN_ERR "IUCV: IUCV connection needs VM as base\n");
371 return -EPROTONOSUPPORT;
372 }
373
374 ret = bus_register(&iucv_bus);
375 if (ret) {
376 printk(KERN_ERR "IUCV: failed to register bus.\n");
377 return ret;
378 }
379
380 iucv_root = s390_root_dev_register("iucv");
381 if (IS_ERR(iucv_root)) {
382 printk(KERN_ERR "IUCV: failed to register iucv root.\n");
383 bus_unregister(&iucv_bus);
384 return PTR_ERR(iucv_root);
385 }
386
387 /* Note: GFP_DMA used used to get memory below 2G */
388 iucv_external_int_buffer = kzalloc(sizeof(iucv_GeneralInterrupt),
389 GFP_KERNEL|GFP_DMA);
390 if (!iucv_external_int_buffer) {
391 printk(KERN_WARNING
392 "%s: Could not allocate external interrupt buffer\n",
393 __FUNCTION__);
394 s390_root_dev_unregister(iucv_root);
395 bus_unregister(&iucv_bus);
396 return -ENOMEM;
397 }
398
399 /* Initialize parameter pool */
400 iucv_param_pool = kzalloc(sizeof(iucv_param) * PARAM_POOL_SIZE,
401 GFP_KERNEL|GFP_DMA);
402 if (!iucv_param_pool) {
403 printk(KERN_WARNING "%s: Could not allocate param pool\n",
404 __FUNCTION__);
405 kfree(iucv_external_int_buffer);
406 iucv_external_int_buffer = NULL;
407 s390_root_dev_unregister(iucv_root);
408 bus_unregister(&iucv_bus);
409 return -ENOMEM;
410 }
411
412 /* Initialize irq queue */
413 INIT_LIST_HEAD(&iucv_irq_queue);
414
415 /* Initialize handler table */
416 INIT_LIST_HEAD(&iucv_handler_table);
417
418 iucv_banner();
419 return 0;
420}
421
422/**
423 * iucv_exit - De-Initialization
424 *
425 * Frees everything allocated from iucv_init.
426 */
427static int iucv_retrieve_buffer (void);
428
429static void
430iucv_exit(void)
431{
432 iucv_retrieve_buffer();
433 kfree(iucv_external_int_buffer);
434 iucv_external_int_buffer = NULL;
435 kfree(iucv_param_pool);
436 iucv_param_pool = NULL;
437 s390_root_dev_unregister(iucv_root);
438 bus_unregister(&iucv_bus);
439 printk(KERN_INFO "IUCV lowlevel driver unloaded\n");
440}
441
442/**
443 * grab_param: - Get a parameter buffer from the pre-allocated pool.
444 *
445 * This function searches for an unused element in the pre-allocated pool
446 * of parameter buffers. If one is found, it marks it "in use" and returns
447 * a pointer to it. The calling function is responsible for releasing it
448 * when it has finished its usage.
449 *
450 * Returns: A pointer to iucv_param.
451 */
452static __inline__ iucv_param *
453grab_param(void)
454{
455 iucv_param *ptr;
456 static int hint = 0;
457
458 ptr = iucv_param_pool + hint;
459 do {
460 ptr++;
461 if (ptr >= iucv_param_pool + PARAM_POOL_SIZE)
462 ptr = iucv_param_pool;
463 } while (atomic_cmpxchg(&ptr->in_use, 0, 1) != 0);
464 hint = ptr - iucv_param_pool;
465
466 memset(&ptr->param, 0, sizeof(ptr->param));
467 return ptr;
468}
469
470/**
471 * release_param - Release a parameter buffer.
472 * @p: A pointer to a struct iucv_param, previously obtained by calling
473 * grab_param().
474 *
475 * This function marks the specified parameter buffer "unused".
476 */
477static __inline__ void
478release_param(void *p)
479{
480 atomic_set(&((iucv_param *)p)->in_use, 0);
481}
482
483/**
484 * iucv_add_handler: - Add a new handler
485 * @new_handler: handle that is being entered into chain.
486 *
487 * Places new handle on iucv_handler_table, if identical handler is not
488 * found.
489 *
490 * Returns: 0 on success, !0 on failure (handler already in chain).
491 */
492static int
493iucv_add_handler (handler *new)
494{
495 ulong flags;
496
497 iucv_debug(1, "entering");
498 iucv_dumpit("handler:", new, sizeof(handler));
499
500 spin_lock_irqsave (&iucv_lock, flags);
501 if (!list_empty(&iucv_handler_table)) {
502 struct list_head *lh;
503
504 /**
505 * Search list for handler with identical id. If one
506 * is found, the new handler is _not_ added.
507 */
508 list_for_each(lh, &iucv_handler_table) {
509 handler *h = list_entry(lh, handler, list);
510 if (!memcmp(&new->id, &h->id, sizeof(h->id))) {
511 iucv_debug(1, "ret 1");
512 spin_unlock_irqrestore (&iucv_lock, flags);
513 return 1;
514 }
515 }
516 }
517 /**
518 * If we get here, no handler was found.
519 */
520 INIT_LIST_HEAD(&new->list);
521 list_add(&new->list, &iucv_handler_table);
522 spin_unlock_irqrestore (&iucv_lock, flags);
523
524 iucv_debug(1, "exiting");
525 return 0;
526}
527
528/**
529 * b2f0:
530 * @code: identifier of IUCV call to CP.
531 * @parm: pointer to 40 byte iparml area passed to CP
532 *
533 * Calls CP to execute IUCV commands.
534 *
535 * Returns: return code from CP's IUCV call
536 */
537static inline ulong b2f0(__u32 code, void *parm)
538{
539 register unsigned long reg0 asm ("0");
540 register unsigned long reg1 asm ("1");
541 iucv_dumpit("iparml before b2f0 call:", parm, sizeof(iucv_param));
542
543 reg0 = code;
544 reg1 = virt_to_phys(parm);
545 asm volatile(".long 0xb2f01000" : : "d" (reg0), "a" (reg1));
546
547 iucv_dumpit("iparml after b2f0 call:", parm, sizeof(iucv_param));
548
549 return (unsigned long)*((__u8 *)(parm + 3));
550}
551
552/*
553 * Name: iucv_add_pathid
554 * Purpose: Adds a path id to the system.
555 * Input: pathid - pathid that is going to be entered into system
556 * handle - address of handler that the pathid will be associated
557 * with.
558 * pgm_data - token passed in by application.
559 * Output: 0: successful addition of pathid
560 * - EINVAL - pathid entry is being used by another application
561 * - ENOMEM - storage allocation for a new pathid table failed
562*/
563static int
564__iucv_add_pathid(__u16 pathid, handler *handler)
565{
566
567 iucv_debug(1, "entering");
568
569 iucv_debug(1, "handler is pointing to %p", handler);
570
571 if (pathid > (max_connections - 1))
572 return -EINVAL;
573
574 if (iucv_pathid_table[pathid]) {
575 iucv_debug(1, "pathid entry is %p", iucv_pathid_table[pathid]);
576 printk(KERN_WARNING
577 "%s: Pathid being used, error.\n", __FUNCTION__);
578 return -EINVAL;
579 }
580 iucv_pathid_table[pathid] = handler;
581
582 iucv_debug(1, "exiting");
583 return 0;
584} /* end of add_pathid function */
585
586static int
587iucv_add_pathid(__u16 pathid, handler *handler)
588{
589 ulong flags;
590 int rc;
591
592 spin_lock_irqsave (&iucv_lock, flags);
593 rc = __iucv_add_pathid(pathid, handler);
594 spin_unlock_irqrestore (&iucv_lock, flags);
595 return rc;
596}
597
598static void
599iucv_remove_pathid(__u16 pathid)
600{
601 ulong flags;
602
603 if (pathid > (max_connections - 1))
604 return;
605
606 spin_lock_irqsave (&iucv_lock, flags);
607 iucv_pathid_table[pathid] = NULL;
608 spin_unlock_irqrestore (&iucv_lock, flags);
609}
610
611/**
612 * iucv_declare_buffer_cpuid
613 * Register at VM for subsequent IUCV operations. This is executed
614 * on the reserved CPU iucv_cpuid. Called from iucv_declare_buffer().
615 */
616static void
617iucv_declare_buffer_cpuid (void *result)
618{
619 iparml_db *parm;
620
621 parm = (iparml_db *)grab_param();
622 parm->ipbfadr1 = virt_to_phys(iucv_external_int_buffer);
623 if ((*((ulong *)result) = b2f0(DECLARE_BUFFER, parm)) == 1)
624 *((ulong *)result) = parm->iprcode;
625 release_param(parm);
626}
627
628/**
629 * iucv_retrieve_buffer_cpuid:
630 * Unregister IUCV usage at VM. This is always executed on the same
631 * cpu that registered the buffer to VM.
632 * Called from iucv_retrieve_buffer().
633 */
634static void
635iucv_retrieve_buffer_cpuid (void *cpu)
636{
637 iparml_control *parm;
638
639 parm = (iparml_control *)grab_param();
640 b2f0(RETRIEVE_BUFFER, parm);
641 release_param(parm);
642}
643
644/**
645 * Name: iucv_declare_buffer
646 * Purpose: Specifies the guests real address of an external
647 * interrupt.
648 * Input: void
649 * Output: iprcode - return code from b2f0 call
650 */
651static int
652iucv_declare_buffer (void)
653{
654 unsigned long flags;
655 ulong b2f0_result;
656
657 iucv_debug(1, "entering");
658 b2f0_result = -ENODEV;
659 spin_lock_irqsave (&iucv_lock, flags);
660 if (iucv_cpuid == -1) {
661 /* Reserve any cpu for use by iucv. */
662 iucv_cpuid = smp_get_cpu(CPU_MASK_ALL);
663 spin_unlock_irqrestore (&iucv_lock, flags);
664 smp_call_function_on(iucv_declare_buffer_cpuid,
665 &b2f0_result, 0, 1, iucv_cpuid);
666 if (b2f0_result) {
667 smp_put_cpu(iucv_cpuid);
668 iucv_cpuid = -1;
669 }
670 iucv_debug(1, "Address of EIB = %p", iucv_external_int_buffer);
671 } else {
672 spin_unlock_irqrestore (&iucv_lock, flags);
673 b2f0_result = 0;
674 }
675 iucv_debug(1, "exiting");
676 return b2f0_result;
677}
678
679/**
680 * iucv_retrieve_buffer:
681 *
682 * Terminates all use of IUCV.
683 * Returns: return code from CP
684 */
685static int
686iucv_retrieve_buffer (void)
687{
688 iucv_debug(1, "entering");
689 if (iucv_cpuid != -1) {
690 smp_call_function_on(iucv_retrieve_buffer_cpuid,
691 NULL, 0, 1, iucv_cpuid);
692 /* Release the cpu reserved by iucv_declare_buffer. */
693 smp_put_cpu(iucv_cpuid);
694 iucv_cpuid = -1;
695 }
696 iucv_debug(1, "exiting");
697 return 0;
698}
699
700/**
701 * iucv_remove_handler:
702 * @users_handler: handler to be removed
703 *
704 * Remove handler when application unregisters.
705 */
706static void
707iucv_remove_handler(handler *handler)
708{
709 unsigned long flags;
710
711 if ((!iucv_pathid_table) || (!handler))
712 return;
713
714 iucv_debug(1, "entering");
715
716 spin_lock_irqsave (&iucv_lock, flags);
717 list_del(&handler->list);
718 if (list_empty(&iucv_handler_table)) {
719 if (register_flag) {
720 unregister_external_interrupt(0x4000, iucv_irq_handler);
721 register_flag = 0;
722 }
723 }
724 spin_unlock_irqrestore (&iucv_lock, flags);
725
726 iucv_debug(1, "exiting");
727 return;
728}
729
730/**
731 * iucv_register_program:
732 * @pgmname: user identification
733 * @userid: machine identification
734 * @pgmmask: Indicates which bits in the pgmname and userid combined will be
735 * used to determine who is given control.
736 * @ops: Address of interrupt handler table.
737 * @pgm_data: Application data to be passed to interrupt handlers.
738 *
739 * Registers an application with IUCV.
740 * Returns:
741 * The address of handler, or NULL on failure.
742 * NOTE on pgmmask:
743 * If pgmname, userid and pgmmask are provided, pgmmask is entered into the
744 * handler as is.
745 * If pgmmask is NULL, the internal mask is set to all 0xff's
746 * When userid is NULL, the first 8 bytes of the internal mask are forced
747 * to 0x00.
748 * If pgmmask and userid are NULL, the first 8 bytes of the internal mask
749 * are forced to 0x00 and the last 16 bytes to 0xff.
750 */
751
752iucv_handle_t
753iucv_register_program (__u8 pgmname[16],
754 __u8 userid[8],
755 __u8 pgmmask[24],
756 iucv_interrupt_ops_t * ops, void *pgm_data)
757{
758 ulong rc = 0; /* return code from function calls */
759 handler *new_handler;
760
761 iucv_debug(1, "entering");
762
763 if (ops == NULL) {
764 /* interrupt table is not defined */
765 printk(KERN_WARNING "%s: Interrupt table is not defined, "
766 "exiting\n", __FUNCTION__);
767 return NULL;
768 }
769 if (!pgmname) {
770 printk(KERN_WARNING "%s: pgmname not provided\n", __FUNCTION__);
771 return NULL;
772 }
773
774 /* Allocate handler entry */
775 new_handler = kmalloc(sizeof(handler), GFP_ATOMIC);
776 if (new_handler == NULL) {
777 printk(KERN_WARNING "%s: storage allocation for new handler "
778 "failed.\n", __FUNCTION__);
779 return NULL;
780 }
781
782 if (!iucv_pathid_table) {
783 if (iucv_init()) {
784 kfree(new_handler);
785 return NULL;
786 }
787
788 max_connections = iucv_query_maxconn();
789 iucv_pathid_table = kcalloc(max_connections, sizeof(handler *),
790 GFP_ATOMIC);
791 if (iucv_pathid_table == NULL) {
792 printk(KERN_WARNING "%s: iucv_pathid_table storage "
793 "allocation failed\n", __FUNCTION__);
794 kfree(new_handler);
795 return NULL;
796 }
797 }
798 memset(new_handler, 0, sizeof (handler));
799 memcpy(new_handler->id.user_data, pgmname,
800 sizeof (new_handler->id.user_data));
801 if (userid) {
802 memcpy (new_handler->id.userid, userid,
803 sizeof (new_handler->id.userid));
804 ASCEBC (new_handler->id.userid,
805 sizeof (new_handler->id.userid));
806 EBC_TOUPPER (new_handler->id.userid,
807 sizeof (new_handler->id.userid));
808
809 if (pgmmask) {
810 memcpy (new_handler->id.mask, pgmmask,
811 sizeof (new_handler->id.mask));
812 } else {
813 memset (new_handler->id.mask, 0xFF,
814 sizeof (new_handler->id.mask));
815 }
816 } else {
817 if (pgmmask) {
818 memcpy (new_handler->id.mask, pgmmask,
819 sizeof (new_handler->id.mask));
820 } else {
821 memset (new_handler->id.mask, 0xFF,
822 sizeof (new_handler->id.mask));
823 }
824 memset (new_handler->id.userid, 0x00,
825 sizeof (new_handler->id.userid));
826 }
827 /* fill in the rest of handler */
828 new_handler->pgm_data = pgm_data;
829 new_handler->interrupt_table = ops;
830
831 /*
832 * Check if someone else is registered with same pgmname, userid
833 * and mask. If someone is already registered with same pgmname,
834 * userid and mask, registration will fail and NULL will be returned
835 * to the application.
836 * If identical handler not found, then handler is added to list.
837 */
838 rc = iucv_add_handler(new_handler);
839 if (rc) {
840 printk(KERN_WARNING "%s: Someone already registered with same "
841 "pgmname, userid, pgmmask\n", __FUNCTION__);
842 kfree (new_handler);
843 return NULL;
844 }
845
846 rc = iucv_declare_buffer();
847 if (rc) {
848 char *err = "Unknown";
849 iucv_remove_handler(new_handler);
850 kfree(new_handler);
851 switch(rc) {
852 case 0x03:
853 err = "Directory error";
854 break;
855 case 0x0a:
856 err = "Invalid length";
857 break;
858 case 0x13:
859 err = "Buffer already exists";
860 break;
861 case 0x3e:
862 err = "Buffer overlap";
863 break;
864 case 0x5c:
865 err = "Paging or storage error";
866 break;
867 }
868 printk(KERN_WARNING "%s: iucv_declare_buffer "
869 "returned error 0x%02lx (%s)\n", __FUNCTION__, rc, err);
870 return NULL;
871 }
872 if (!register_flag) {
873 /* request the 0x4000 external interrupt */
874 rc = register_external_interrupt (0x4000, iucv_irq_handler);
875 if (rc) {
876 iucv_remove_handler(new_handler);
877 kfree (new_handler);
878 printk(KERN_WARNING "%s: "
879 "register_external_interrupt returned %ld\n",
880 __FUNCTION__, rc);
881 return NULL;
882
883 }
884 register_flag = 1;
885 }
886 iucv_debug(1, "exiting");
887 return new_handler;
888} /* end of register function */
889
890/**
891 * iucv_unregister_program:
892 * @handle: address of handler
893 *
894 * Unregister application with IUCV.
895 * Returns:
896 * 0 on success, -EINVAL, if specified handle is invalid.
897 */
898
899int
900iucv_unregister_program (iucv_handle_t handle)
901{
902 handler *h = NULL;
903 struct list_head *lh;
904 int i;
905 ulong flags;
906
907 iucv_debug(1, "entering");
908 iucv_debug(1, "address of handler is %p", h);
909
910 /* Checking if handle is valid */
911 spin_lock_irqsave (&iucv_lock, flags);
912 list_for_each(lh, &iucv_handler_table) {
913 if ((handler *)handle == list_entry(lh, handler, list)) {
914 h = (handler *)handle;
915 break;
916 }
917 }
918 if (!h) {
919 spin_unlock_irqrestore (&iucv_lock, flags);
920 if (handle)
921 printk(KERN_WARNING
922 "%s: Handler not found in iucv_handler_table.\n",
923 __FUNCTION__);
924 else
925 printk(KERN_WARNING
926 "%s: NULL handle passed by application.\n",
927 __FUNCTION__);
928 return -EINVAL;
929 }
930
931 /**
932 * First, walk thru iucv_pathid_table and sever any pathid which is
933 * still pointing to the handler to be removed.
934 */
935 for (i = 0; i < max_connections; i++)
936 if (iucv_pathid_table[i] == h) {
937 spin_unlock_irqrestore (&iucv_lock, flags);
938 iucv_sever(i, h->id.user_data);
939 spin_lock_irqsave(&iucv_lock, flags);
940 }
941 spin_unlock_irqrestore (&iucv_lock, flags);
942
943 iucv_remove_handler(h);
944 kfree(h);
945
946 iucv_debug(1, "exiting");
947 return 0;
948}
949
950/**
951 * iucv_accept:
952 * @pathid: Path identification number
953 * @msglim_reqstd: The number of outstanding messages requested.
954 * @user_data: Data specified by the iucv_connect function.
955 * @flags1: Contains options for this path.
956 * - IPPRTY (0x20) Specifies if you want to send priority message.
957 * - IPRMDATA (0x80) Specifies whether your program can handle a message
958 * in the parameter list.
959 * - IPQUSCE (0x40) Specifies whether you want to quiesce the path being
960 * established.
961 * @handle: Address of handler.
962 * @pgm_data: Application data passed to interrupt handlers.
963 * @flags1_out: Pointer to an int. If not NULL, on return the options for
964 * the path are stored at the given location:
965 * - IPPRTY (0x20) Indicates you may send a priority message.
966 * @msglim: Pointer to an __u16. If not NULL, on return the maximum
967 * number of outstanding messages is stored at the given
968 * location.
969 *
970 * This function is issued after the user receives a Connection Pending external
971 * interrupt and now wishes to complete the IUCV communication path.
972 * Returns:
973 * return code from CP
974 */
975int
976iucv_accept(__u16 pathid, __u16 msglim_reqstd,
977 __u8 user_data[16], int flags1,
978 iucv_handle_t handle, void *pgm_data,
979 int *flags1_out, __u16 * msglim)
980{
981 ulong b2f0_result = 0;
982 ulong flags;
983 struct list_head *lh;
984 handler *h = NULL;
985 iparml_control *parm;
986
987 iucv_debug(1, "entering");
988 iucv_debug(1, "pathid = %d", pathid);
989
990 /* Checking if handle is valid */
991 spin_lock_irqsave (&iucv_lock, flags);
992 list_for_each(lh, &iucv_handler_table) {
993 if ((handler *)handle == list_entry(lh, handler, list)) {
994 h = (handler *)handle;
995 break;
996 }
997 }
998 spin_unlock_irqrestore (&iucv_lock, flags);
999
1000 if (!h) {
1001 if (handle)
1002 printk(KERN_WARNING
1003 "%s: Handler not found in iucv_handler_table.\n",
1004 __FUNCTION__);
1005 else
1006 printk(KERN_WARNING
1007 "%s: NULL handle passed by application.\n",
1008 __FUNCTION__);
1009 return -EINVAL;
1010 }
1011
1012 parm = (iparml_control *)grab_param();
1013
1014 parm->ippathid = pathid;
1015 parm->ipmsglim = msglim_reqstd;
1016 if (user_data)
1017 memcpy(parm->ipuser, user_data, sizeof(parm->ipuser));
1018
1019 parm->ipflags1 = (__u8)flags1;
1020 b2f0_result = b2f0(ACCEPT, parm);
1021
1022 if (!b2f0_result) {
1023 if (msglim)
1024 *msglim = parm->ipmsglim;
1025 if (pgm_data)
1026 h->pgm_data = pgm_data;
1027 if (flags1_out)
1028 *flags1_out = (parm->ipflags1 & IPPRTY) ? IPPRTY : 0;
1029 }
1030 release_param(parm);
1031
1032 iucv_debug(1, "exiting");
1033 return b2f0_result;
1034}
1035
1036/**
1037 * iucv_connect:
1038 * @pathid: Path identification number
1039 * @msglim_reqstd: Number of outstanding messages requested
1040 * @user_data: 16-byte user data
1041 * @userid: 8-byte of user identification
1042 * @system_name: 8-byte identifying the system name
1043 * @flags1: Specifies options for this path:
1044 * - IPPRTY (0x20) Specifies if you want to send priority message.
1045 * - IPRMDATA (0x80) Specifies whether your program can handle a message
1046 * in the parameter list.
1047 * - IPQUSCE (0x40) Specifies whether you want to quiesce the path being
1048 * established.
1049 * - IPLOCAL (0x01) Allows an application to force the partner to be on the
1050 * local system. If local is specified then target class
1051 * cannot be specified.
1052 * @flags1_out: Pointer to an int. If not NULL, on return the options for
1053 * the path are stored at the given location:
1054 * - IPPRTY (0x20) Indicates you may send a priority message.
1055 * @msglim: Pointer to an __u16. If not NULL, on return the maximum
1056 * number of outstanding messages is stored at the given
1057 * location.
1058 * @handle: Address of handler.
1059 * @pgm_data: Application data to be passed to interrupt handlers.
1060 *
1061 * This function establishes an IUCV path. Although the connect may complete
1062 * successfully, you are not able to use the path until you receive an IUCV
1063 * Connection Complete external interrupt.
1064 * Returns: return code from CP, or one of the following
1065 * - ENOMEM
1066 * - return code from iucv_declare_buffer
1067 * - EINVAL - invalid handle passed by application
1068 * - EINVAL - pathid address is NULL
1069 * - ENOMEM - pathid table storage allocation failed
1070 * - return code from internal function add_pathid
1071 */
1072int
1073iucv_connect (__u16 *pathid, __u16 msglim_reqstd,
1074 __u8 user_data[16], __u8 userid[8],
1075 __u8 system_name[8], int flags1,
1076 int *flags1_out, __u16 * msglim,
1077 iucv_handle_t handle, void *pgm_data)
1078{
1079 iparml_control *parm;
1080 iparml_control local_parm;
1081 struct list_head *lh;
1082 ulong b2f0_result = 0;
1083 ulong flags;
1084 int add_pathid_result = 0;
1085 handler *h = NULL;
1086 __u8 no_memory[16] = "NO MEMORY";
1087
1088 iucv_debug(1, "entering");
1089
1090 /* Checking if handle is valid */
1091 spin_lock_irqsave (&iucv_lock, flags);
1092 list_for_each(lh, &iucv_handler_table) {
1093 if ((handler *)handle == list_entry(lh, handler, list)) {
1094 h = (handler *)handle;
1095 break;
1096 }
1097 }
1098 spin_unlock_irqrestore (&iucv_lock, flags);
1099
1100 if (!h) {
1101 if (handle)
1102 printk(KERN_WARNING
1103 "%s: Handler not found in iucv_handler_table.\n",
1104 __FUNCTION__);
1105 else
1106 printk(KERN_WARNING
1107 "%s: NULL handle passed by application.\n",
1108 __FUNCTION__);
1109 return -EINVAL;
1110 }
1111
1112 if (pathid == NULL) {
1113 printk(KERN_WARNING "%s: NULL pathid pointer\n",
1114 __FUNCTION__);
1115 return -EINVAL;
1116 }
1117
1118 parm = (iparml_control *)grab_param();
1119
1120 parm->ipmsglim = msglim_reqstd;
1121
1122 if (user_data)
1123 memcpy(parm->ipuser, user_data, sizeof(parm->ipuser));
1124
1125 if (userid) {
1126 memcpy(parm->ipvmid, userid, sizeof(parm->ipvmid));
1127 ASCEBC(parm->ipvmid, sizeof(parm->ipvmid));
1128 EBC_TOUPPER(parm->ipvmid, sizeof(parm->ipvmid));
1129 }
1130
1131 if (system_name) {
1132 memcpy(parm->iptarget, system_name, sizeof(parm->iptarget));
1133 ASCEBC(parm->iptarget, sizeof(parm->iptarget));
1134 EBC_TOUPPER(parm->iptarget, sizeof(parm->iptarget));
1135 }
1136
1137 /* In order to establish an IUCV connection, the procedure is:
1138 *
1139 * b2f0(CONNECT)
1140 * take the ippathid from the b2f0 call
1141 * register the handler to the ippathid
1142 *
1143 * Unfortunately, the ConnectionEstablished message gets sent after the
1144 * b2f0(CONNECT) call but before the register is handled.
1145 *
1146 * In order for this race condition to be eliminated, the IUCV Control
1147 * Interrupts must be disabled for the above procedure.
1148 *
1149 * David Kennedy <dkennedy@linuxcare.com>
1150 */
1151
1152 /* Enable everything but IUCV Control messages */
1153 iucv_setmask(~(AllInterrupts));
1154 messagesDisabled = 1;
1155
1156 spin_lock_irqsave (&iucv_lock, flags);
1157 parm->ipflags1 = (__u8)flags1;
1158 b2f0_result = b2f0(CONNECT, parm);
1159 memcpy(&local_parm, parm, sizeof(local_parm));
1160 release_param(parm);
1161 parm = &local_parm;
1162 if (!b2f0_result)
1163 add_pathid_result = __iucv_add_pathid(parm->ippathid, h);
1164 spin_unlock_irqrestore (&iucv_lock, flags);
1165
1166 if (b2f0_result) {
1167 iucv_setmask(~0);
1168 messagesDisabled = 0;
1169 return b2f0_result;
1170 }
1171
1172 *pathid = parm->ippathid;
1173
1174 /* Enable everything again */
1175 iucv_setmask(IUCVControlInterruptsFlag);
1176
1177 if (msglim)
1178 *msglim = parm->ipmsglim;
1179 if (flags1_out)
1180 *flags1_out = (parm->ipflags1 & IPPRTY) ? IPPRTY : 0;
1181
1182 if (add_pathid_result) {
1183 iucv_sever(*pathid, no_memory);
1184 printk(KERN_WARNING "%s: add_pathid failed with rc ="
1185 " %d\n", __FUNCTION__, add_pathid_result);
1186 return(add_pathid_result);
1187 }
1188
1189 iucv_debug(1, "exiting");
1190 return b2f0_result;
1191}
1192
1193/**
1194 * iucv_purge:
1195 * @pathid: Path identification number
1196 * @msgid: Message ID of message to purge.
1197 * @srccls: Message class of the message to purge.
1198 * @audit: Pointer to an __u32. If not NULL, on return, information about
1199 * asynchronous errors that may have affected the normal completion
1200 * of this message ist stored at the given location.
1201 *
1202 * Cancels a message you have sent.
1203 * Returns: return code from CP
1204 */
1205int
1206iucv_purge (__u16 pathid, __u32 msgid, __u32 srccls, __u32 *audit)
1207{
1208 iparml_purge *parm;
1209 ulong b2f0_result = 0;
1210
1211 iucv_debug(1, "entering");
1212 iucv_debug(1, "pathid = %d", pathid);
1213
1214 parm = (iparml_purge *)grab_param();
1215
1216 parm->ipmsgid = msgid;
1217 parm->ippathid = pathid;
1218 parm->ipsrccls = srccls;
1219 parm->ipflags1 |= (IPSRCCLS | IPFGMID | IPFGPID);
1220 b2f0_result = b2f0(PURGE, parm);
1221
1222 if (!b2f0_result && audit) {
1223 memcpy(audit, parm->ipaudit, sizeof(parm->ipaudit));
1224 /* parm->ipaudit has only 3 bytes */
1225 *audit >>= 8;
1226 }
1227
1228 release_param(parm);
1229
1230 iucv_debug(1, "b2f0_result = %ld", b2f0_result);
1231 iucv_debug(1, "exiting");
1232 return b2f0_result;
1233}
1234
1235/**
1236 * iucv_query_generic:
1237 * @want_maxconn: Flag, describing which value is to be returned.
1238 *
1239 * Helper function for iucv_query_maxconn() and iucv_query_bufsize().
1240 *
1241 * Returns: The buffersize, if want_maxconn is 0; the maximum number of
1242 * connections, if want_maxconn is 1 or an error-code < 0 on failure.
1243 */
1244static int
1245iucv_query_generic(int want_maxconn)
1246{
1247 register unsigned long reg0 asm ("0");
1248 register unsigned long reg1 asm ("1");
1249 iparml_purge *parm = (iparml_purge *)grab_param();
1250 int bufsize, maxconn;
1251 int ccode;
1252
1253 /**
1254 * Call b2f0 and store R0 (max buffer size),
1255 * R1 (max connections) and CC.
1256 */
1257 reg0 = QUERY;
1258 reg1 = virt_to_phys(parm);
1259 asm volatile(
1260 " .long 0xb2f01000\n"
1261 " ipm %0\n"
1262 " srl %0,28\n"
1263 : "=d" (ccode), "+d" (reg0), "+d" (reg1) : : "cc");
1264 bufsize = reg0;
1265 maxconn = reg1;
1266 release_param(parm);
1267
1268 if (ccode)
1269 return -EPERM;
1270 if (want_maxconn)
1271 return maxconn;
1272 return bufsize;
1273}
1274
1275/**
1276 * iucv_query_maxconn:
1277 *
1278 * Determines the maximum number of connections thay may be established.
1279 *
1280 * Returns: Maximum number of connections that can be.
1281 */
1282ulong
1283iucv_query_maxconn(void)
1284{
1285 return iucv_query_generic(1);
1286}
1287
1288/**
1289 * iucv_query_bufsize:
1290 *
1291 * Determines the size of the external interrupt buffer.
1292 *
1293 * Returns: Size of external interrupt buffer.
1294 */
1295ulong
1296iucv_query_bufsize (void)
1297{
1298 return iucv_query_generic(0);
1299}
1300
1301/**
1302 * iucv_quiesce:
1303 * @pathid: Path identification number
1304 * @user_data: 16-byte user data
1305 *
1306 * Temporarily suspends incoming messages on an IUCV path.
1307 * You can later reactivate the path by invoking the iucv_resume function.
1308 * Returns: return code from CP
1309 */
1310int
1311iucv_quiesce (__u16 pathid, __u8 user_data[16])
1312{
1313 iparml_control *parm;
1314 ulong b2f0_result = 0;
1315
1316 iucv_debug(1, "entering");
1317 iucv_debug(1, "pathid = %d", pathid);
1318
1319 parm = (iparml_control *)grab_param();
1320
1321 memcpy(parm->ipuser, user_data, sizeof(parm->ipuser));
1322 parm->ippathid = pathid;
1323
1324 b2f0_result = b2f0(QUIESCE, parm);
1325 release_param(parm);
1326
1327 iucv_debug(1, "b2f0_result = %ld", b2f0_result);
1328 iucv_debug(1, "exiting");
1329
1330 return b2f0_result;
1331}
1332
1333/**
1334 * iucv_receive:
1335 * @pathid: Path identification number.
1336 * @buffer: Address of buffer to receive. Must be below 2G.
1337 * @buflen: Length of buffer to receive.
1338 * @msgid: Specifies the message ID.
1339 * @trgcls: Specifies target class.
1340 * @flags1_out: Receives options for path on return.
1341 * - IPNORPY (0x10) Specifies whether a reply is required
1342 * - IPPRTY (0x20) Specifies if you want to send priority message
1343 * - IPRMDATA (0x80) Specifies the data is contained in the parameter list
1344 * @residual_buffer: Receives the address of buffer updated by the number
1345 * of bytes you have received on return.
1346 * @residual_length: On return, receives one of the following values:
1347 * - 0 If the receive buffer is the same length as
1348 * the message.
1349 * - Remaining bytes in buffer If the receive buffer is longer than the
1350 * message.
1351 * - Remaining bytes in message If the receive buffer is shorter than the
1352 * message.
1353 *
1354 * This function receives messages that are being sent to you over established
1355 * paths.
1356 * Returns: return code from CP IUCV call; If the receive buffer is shorter
1357 * than the message, always 5
1358 * -EINVAL - buffer address is pointing to NULL
1359 */
1360int
1361iucv_receive (__u16 pathid, __u32 msgid, __u32 trgcls,
1362 void *buffer, ulong buflen,
1363 int *flags1_out, ulong * residual_buffer, ulong * residual_length)
1364{
1365 iparml_db *parm;
1366 ulong b2f0_result;
1367 int moved = 0; /* number of bytes moved from parmlist to buffer */
1368
1369 iucv_debug(2, "entering");
1370
1371 if (!buffer)
1372 return -EINVAL;
1373
1374 parm = (iparml_db *)grab_param();
1375
1376 parm->ipbfadr1 = (__u32) (addr_t) buffer;
1377 parm->ipbfln1f = (__u32) ((ulong) buflen);
1378 parm->ipmsgid = msgid;
1379 parm->ippathid = pathid;
1380 parm->iptrgcls = trgcls;
1381 parm->ipflags1 = (IPFGPID | IPFGMID | IPFGMCL);
1382
1383 b2f0_result = b2f0(RECEIVE, parm);
1384
1385 if (!b2f0_result || b2f0_result == 5) {
1386 if (flags1_out) {
1387 iucv_debug(2, "*flags1_out = %d", *flags1_out);
1388 *flags1_out = (parm->ipflags1 & (~0x07));
1389 iucv_debug(2, "*flags1_out = %d", *flags1_out);
1390 }
1391
1392 if (!(parm->ipflags1 & IPRMDATA)) { /*msg not in parmlist */
1393 if (residual_length)
1394 *residual_length = parm->ipbfln1f;
1395
1396 if (residual_buffer)
1397 *residual_buffer = parm->ipbfadr1;
1398 } else {
1399 moved = min_t (unsigned long, buflen, 8);
1400
1401 memcpy ((char *) buffer,
1402 (char *) &parm->ipbfadr1, moved);
1403
1404 if (buflen < 8)
1405 b2f0_result = 5;
1406
1407 if (residual_length)
1408 *residual_length = abs (buflen - 8);
1409
1410 if (residual_buffer)
1411 *residual_buffer = (ulong) (buffer + moved);
1412 }
1413 }
1414 release_param(parm);
1415
1416 iucv_debug(2, "exiting");
1417 return b2f0_result;
1418}
1419
1420/*
1421 * Name: iucv_receive_array
1422 * Purpose: This function receives messages that are being sent to you
1423 * over established paths.
1424 * Input: pathid - path identification number
1425 * buffer - address of array of buffers
1426 * buflen - total length of buffers
1427 * msgid - specifies the message ID.
1428 * trgcls - specifies target class
1429 * Output:
1430 * flags1_out: Options for path.
1431 * IPNORPY - 0x10 specifies whether a reply is required
1432 * IPPRTY - 0x20 specifies if you want to send priority message
1433 * IPRMDATA - 0x80 specifies the data is contained in the parameter list
1434 * residual_buffer - address points to the current list entry IUCV
1435 * is working on.
1436 * residual_length -
1437 * Contains one of the following values, if the receive buffer is:
1438 * The same length as the message, this field is zero.
1439 * Longer than the message, this field contains the number of
1440 * bytes remaining in the buffer.
1441 * Shorter than the message, this field contains the residual
1442 * count (that is, the number of bytes remaining in the
1443 * message that does not fit into the buffer. In this case
1444 * b2f0_result = 5.
1445 * Return: b2f0_result - return code from CP
1446 * (-EINVAL) - buffer address is NULL
1447 */
1448int
1449iucv_receive_array (__u16 pathid,
1450 __u32 msgid, __u32 trgcls,
1451 iucv_array_t * buffer, ulong buflen,
1452 int *flags1_out,
1453 ulong * residual_buffer, ulong * residual_length)
1454{
1455 iparml_db *parm;
1456 ulong b2f0_result;
1457 int i = 0, moved = 0, need_to_move = 8, dyn_len;
1458
1459 iucv_debug(2, "entering");
1460
1461 if (!buffer)
1462 return -EINVAL;
1463
1464 parm = (iparml_db *)grab_param();
1465
1466 parm->ipbfadr1 = (__u32) ((ulong) buffer);
1467 parm->ipbfln1f = (__u32) buflen;
1468 parm->ipmsgid = msgid;
1469 parm->ippathid = pathid;
1470 parm->iptrgcls = trgcls;
1471 parm->ipflags1 = (IPBUFLST | IPFGPID | IPFGMID | IPFGMCL);
1472
1473 b2f0_result = b2f0(RECEIVE, parm);
1474
1475 if (!b2f0_result || b2f0_result == 5) {
1476
1477 if (flags1_out) {
1478 iucv_debug(2, "*flags1_out = %d", *flags1_out);
1479 *flags1_out = (parm->ipflags1 & (~0x07));
1480 iucv_debug(2, "*flags1_out = %d", *flags1_out);
1481 }
1482
1483 if (!(parm->ipflags1 & IPRMDATA)) { /*msg not in parmlist */
1484
1485 if (residual_length)
1486 *residual_length = parm->ipbfln1f;
1487
1488 if (residual_buffer)
1489 *residual_buffer = parm->ipbfadr1;
1490
1491 } else {
1492 /* copy msg from parmlist to users array. */
1493
1494 while ((moved < 8) && (moved < buflen)) {
1495 dyn_len =
1496 min_t (unsigned int,
1497 (buffer + i)->length, need_to_move);
1498
1499 memcpy ((char *)((ulong)((buffer + i)->address)),
1500 ((char *) &parm->ipbfadr1) + moved,
1501 dyn_len);
1502
1503 moved += dyn_len;
1504 need_to_move -= dyn_len;
1505
1506 (buffer + i)->address =
1507 (__u32)
1508 ((ulong)(__u8 *) ((ulong)(buffer + i)->address)
1509 + dyn_len);
1510
1511 (buffer + i)->length -= dyn_len;
1512 i++;
1513 }
1514
1515 if (need_to_move) /* buflen < 8 bytes */
1516 b2f0_result = 5;
1517
1518 if (residual_length)
1519 *residual_length = abs (buflen - 8);
1520
1521 if (residual_buffer) {
1522 if (!moved)
1523 *residual_buffer = (ulong) buffer;
1524 else
1525 *residual_buffer =
1526 (ulong) (buffer + (i - 1));
1527 }
1528
1529 }
1530 }
1531 release_param(parm);
1532
1533 iucv_debug(2, "exiting");
1534 return b2f0_result;
1535}
1536
1537/**
1538 * iucv_reject:
1539 * @pathid: Path identification number.
1540 * @msgid: Message ID of the message to reject.
1541 * @trgcls: Target class of the message to reject.
1542 * Returns: return code from CP
1543 *
1544 * Refuses a specified message. Between the time you are notified of a
1545 * message and the time that you complete the message, the message may
1546 * be rejected.
1547 */
1548int
1549iucv_reject (__u16 pathid, __u32 msgid, __u32 trgcls)
1550{
1551 iparml_db *parm;
1552 ulong b2f0_result = 0;
1553
1554 iucv_debug(1, "entering");
1555 iucv_debug(1, "pathid = %d", pathid);
1556
1557 parm = (iparml_db *)grab_param();
1558
1559 parm->ippathid = pathid;
1560 parm->ipmsgid = msgid;
1561 parm->iptrgcls = trgcls;
1562 parm->ipflags1 = (IPFGMCL | IPFGMID | IPFGPID);
1563
1564 b2f0_result = b2f0(REJECT, parm);
1565 release_param(parm);
1566
1567 iucv_debug(1, "b2f0_result = %ld", b2f0_result);
1568 iucv_debug(1, "exiting");
1569
1570 return b2f0_result;
1571}
1572
1573/*
1574 * Name: iucv_reply
1575 * Purpose: This function responds to the two-way messages that you
1576 * receive. You must identify completely the message to
1577 * which you wish to reply. ie, pathid, msgid, and trgcls.
1578 * Input: pathid - path identification number
1579 * msgid - specifies the message ID.
1580 * trgcls - specifies target class
1581 * flags1 - option for path
1582 * IPPRTY- 0x20 - specifies if you want to send priority message
1583 * buffer - address of reply buffer
1584 * buflen - length of reply buffer
1585 * Output: ipbfadr2 - Address of buffer updated by the number
1586 * of bytes you have moved.
1587 * ipbfln2f - Contains one of the following values:
1588 * If the answer buffer is the same length as the reply, this field
1589 * contains zero.
1590 * If the answer buffer is longer than the reply, this field contains
1591 * the number of bytes remaining in the buffer.
1592 * If the answer buffer is shorter than the reply, this field contains
1593 * a residual count (that is, the number of bytes remianing in the
1594 * reply that does not fit into the buffer. In this
1595 * case b2f0_result = 5.
1596 * Return: b2f0_result - return code from CP
1597 * (-EINVAL) - buffer address is NULL
1598 */
1599int
1600iucv_reply (__u16 pathid,
1601 __u32 msgid, __u32 trgcls,
1602 int flags1,
1603 void *buffer, ulong buflen, ulong * ipbfadr2, ulong * ipbfln2f)
1604{
1605 iparml_db *parm;
1606 ulong b2f0_result;
1607
1608 iucv_debug(2, "entering");
1609
1610 if (!buffer)
1611 return -EINVAL;
1612
1613 parm = (iparml_db *)grab_param();
1614
1615 parm->ipbfadr2 = (__u32) ((ulong) buffer);
1616 parm->ipbfln2f = (__u32) buflen; /* length of message */
1617 parm->ippathid = pathid;
1618 parm->ipmsgid = msgid;
1619 parm->iptrgcls = trgcls;
1620 parm->ipflags1 = (__u8) flags1; /* priority message */
1621
1622 b2f0_result = b2f0(REPLY, parm);
1623
1624 if ((!b2f0_result) || (b2f0_result == 5)) {
1625 if (ipbfadr2)
1626 *ipbfadr2 = parm->ipbfadr2;
1627 if (ipbfln2f)
1628 *ipbfln2f = parm->ipbfln2f;
1629 }
1630 release_param(parm);
1631
1632 iucv_debug(2, "exiting");
1633
1634 return b2f0_result;
1635}
1636
1637/*
1638 * Name: iucv_reply_array
1639 * Purpose: This function responds to the two-way messages that you
1640 * receive. You must identify completely the message to
1641 * which you wish to reply. ie, pathid, msgid, and trgcls.
1642 * The array identifies a list of addresses and lengths of
1643 * discontiguous buffers that contains the reply data.
1644 * Input: pathid - path identification number
1645 * msgid - specifies the message ID.
1646 * trgcls - specifies target class
1647 * flags1 - option for path
1648 * IPPRTY- specifies if you want to send priority message
1649 * buffer - address of array of reply buffers
1650 * buflen - total length of reply buffers
1651 * Output: ipbfadr2 - Address of buffer which IUCV is currently working on.
1652 * ipbfln2f - Contains one of the following values:
1653 * If the answer buffer is the same length as the reply, this field
1654 * contains zero.
1655 * If the answer buffer is longer than the reply, this field contains
1656 * the number of bytes remaining in the buffer.
1657 * If the answer buffer is shorter than the reply, this field contains
1658 * a residual count (that is, the number of bytes remianing in the
1659 * reply that does not fit into the buffer. In this
1660 * case b2f0_result = 5.
1661 * Return: b2f0_result - return code from CP
1662 * (-EINVAL) - buffer address is NULL
1663*/
1664int
1665iucv_reply_array (__u16 pathid,
1666 __u32 msgid, __u32 trgcls,
1667 int flags1,
1668 iucv_array_t * buffer,
1669 ulong buflen, ulong * ipbfadr2, ulong * ipbfln2f)
1670{
1671 iparml_db *parm;
1672 ulong b2f0_result;
1673
1674 iucv_debug(2, "entering");
1675
1676 if (!buffer)
1677 return -EINVAL;
1678
1679 parm = (iparml_db *)grab_param();
1680
1681 parm->ipbfadr2 = (__u32) ((ulong) buffer);
1682 parm->ipbfln2f = buflen; /* length of message */
1683 parm->ippathid = pathid;
1684 parm->ipmsgid = msgid;
1685 parm->iptrgcls = trgcls;
1686 parm->ipflags1 = (IPANSLST | flags1);
1687
1688 b2f0_result = b2f0(REPLY, parm);
1689
1690 if ((!b2f0_result) || (b2f0_result == 5)) {
1691
1692 if (ipbfadr2)
1693 *ipbfadr2 = parm->ipbfadr2;
1694 if (ipbfln2f)
1695 *ipbfln2f = parm->ipbfln2f;
1696 }
1697 release_param(parm);
1698
1699 iucv_debug(2, "exiting");
1700
1701 return b2f0_result;
1702}
1703
1704/*
1705 * Name: iucv_reply_prmmsg
1706 * Purpose: This function responds to the two-way messages that you
1707 * receive. You must identify completely the message to
1708 * which you wish to reply. ie, pathid, msgid, and trgcls.
1709 * Prmmsg signifies the data is moved into the
1710 * parameter list.
1711 * Input: pathid - path identification number
1712 * msgid - specifies the message ID.
1713 * trgcls - specifies target class
1714 * flags1 - option for path
1715 * IPPRTY- specifies if you want to send priority message
1716 * prmmsg - 8-bytes of data to be placed into the parameter
1717 * list.
1718 * Output: NA
1719 * Return: b2f0_result - return code from CP
1720*/
1721int
1722iucv_reply_prmmsg (__u16 pathid,
1723 __u32 msgid, __u32 trgcls, int flags1, __u8 prmmsg[8])
1724{
1725 iparml_dpl *parm;
1726 ulong b2f0_result;
1727
1728 iucv_debug(2, "entering");
1729
1730 parm = (iparml_dpl *)grab_param();
1731
1732 parm->ippathid = pathid;
1733 parm->ipmsgid = msgid;
1734 parm->iptrgcls = trgcls;
1735 memcpy(parm->iprmmsg, prmmsg, sizeof (parm->iprmmsg));
1736 parm->ipflags1 = (IPRMDATA | flags1);
1737
1738 b2f0_result = b2f0(REPLY, parm);
1739 release_param(parm);
1740
1741 iucv_debug(2, "exiting");
1742
1743 return b2f0_result;
1744}
1745
1746/**
1747 * iucv_resume:
1748 * @pathid: Path identification number
1749 * @user_data: 16-byte of user data
1750 *
1751 * This function restores communication over a quiesced path.
1752 * Returns: return code from CP
1753 */
1754int
1755iucv_resume (__u16 pathid, __u8 user_data[16])
1756{
1757 iparml_control *parm;
1758 ulong b2f0_result = 0;
1759
1760 iucv_debug(1, "entering");
1761 iucv_debug(1, "pathid = %d", pathid);
1762
1763 parm = (iparml_control *)grab_param();
1764
1765 memcpy (parm->ipuser, user_data, sizeof (*user_data));
1766 parm->ippathid = pathid;
1767
1768 b2f0_result = b2f0(RESUME, parm);
1769 release_param(parm);
1770
1771 iucv_debug(1, "exiting");
1772
1773 return b2f0_result;
1774}
1775
1776/*
1777 * Name: iucv_send
1778 * Purpose: sends messages
1779 * Input: pathid - ushort, pathid
1780 * msgid - ulong *, id of message returned to caller
1781 * trgcls - ulong, target message class
1782 * srccls - ulong, source message class
1783 * msgtag - ulong, message tag
1784 * flags1 - Contains options for this path.
1785 * IPPRTY - Ox20 - specifies if you want to send a priority message.
1786 * buffer - pointer to buffer
1787 * buflen - ulong, length of buffer
1788 * Output: b2f0_result - return code from b2f0 call
1789 * msgid - returns message id
1790 */
1791int
1792iucv_send (__u16 pathid, __u32 * msgid,
1793 __u32 trgcls, __u32 srccls,
1794 __u32 msgtag, int flags1, void *buffer, ulong buflen)
1795{
1796 iparml_db *parm;
1797 ulong b2f0_result;
1798
1799 iucv_debug(2, "entering");
1800
1801 if (!buffer)
1802 return -EINVAL;
1803
1804 parm = (iparml_db *)grab_param();
1805
1806 parm->ipbfadr1 = (__u32) ((ulong) buffer);
1807 parm->ippathid = pathid;
1808 parm->iptrgcls = trgcls;
1809 parm->ipbfln1f = (__u32) buflen; /* length of message */
1810 parm->ipsrccls = srccls;
1811 parm->ipmsgtag = msgtag;
1812 parm->ipflags1 = (IPNORPY | flags1); /* one way priority message */
1813
1814 b2f0_result = b2f0(SEND, parm);
1815
1816 if ((!b2f0_result) && (msgid))
1817 *msgid = parm->ipmsgid;
1818 release_param(parm);
1819
1820 iucv_debug(2, "exiting");
1821
1822 return b2f0_result;
1823}
1824
1825/*
1826 * Name: iucv_send_array
1827 * Purpose: This function transmits data to another application.
1828 * The contents of buffer is the address of the array of
1829 * addresses and lengths of discontiguous buffers that hold
1830 * the message text. This is a one-way message and the
1831 * receiver will not reply to the message.
1832 * Input: pathid - path identification number
1833 * trgcls - specifies target class
1834 * srccls - specifies the source message class
1835 * msgtag - specifies a tag to be associated witht the message
1836 * flags1 - option for path
1837 * IPPRTY- specifies if you want to send priority message
1838 * buffer - address of array of send buffers
1839 * buflen - total length of send buffers
1840 * Output: msgid - specifies the message ID.
1841 * Return: b2f0_result - return code from CP
1842 * (-EINVAL) - buffer address is NULL
1843 */
1844int
1845iucv_send_array (__u16 pathid,
1846 __u32 * msgid,
1847 __u32 trgcls,
1848 __u32 srccls,
1849 __u32 msgtag, int flags1, iucv_array_t * buffer, ulong buflen)
1850{
1851 iparml_db *parm;
1852 ulong b2f0_result;
1853
1854 iucv_debug(2, "entering");
1855
1856 if (!buffer)
1857 return -EINVAL;
1858
1859 parm = (iparml_db *)grab_param();
1860
1861 parm->ippathid = pathid;
1862 parm->iptrgcls = trgcls;
1863 parm->ipbfadr1 = (__u32) ((ulong) buffer);
1864 parm->ipbfln1f = (__u32) buflen; /* length of message */
1865 parm->ipsrccls = srccls;
1866 parm->ipmsgtag = msgtag;
1867 parm->ipflags1 = (IPNORPY | IPBUFLST | flags1);
1868 b2f0_result = b2f0(SEND, parm);
1869
1870 if ((!b2f0_result) && (msgid))
1871 *msgid = parm->ipmsgid;
1872 release_param(parm);
1873
1874 iucv_debug(2, "exiting");
1875 return b2f0_result;
1876}
1877
1878/*
1879 * Name: iucv_send_prmmsg
1880 * Purpose: This function transmits data to another application.
1881 * Prmmsg specifies that the 8-bytes of data are to be moved
1882 * into the parameter list. This is a one-way message and the
1883 * receiver will not reply to the message.
1884 * Input: pathid - path identification number
1885 * trgcls - specifies target class
1886 * srccls - specifies the source message class
1887 * msgtag - specifies a tag to be associated with the message
1888 * flags1 - option for path
1889 * IPPRTY- specifies if you want to send priority message
1890 * prmmsg - 8-bytes of data to be placed into parameter list
1891 * Output: msgid - specifies the message ID.
1892 * Return: b2f0_result - return code from CP
1893*/
1894int
1895iucv_send_prmmsg (__u16 pathid,
1896 __u32 * msgid,
1897 __u32 trgcls,
1898 __u32 srccls, __u32 msgtag, int flags1, __u8 prmmsg[8])
1899{
1900 iparml_dpl *parm;
1901 ulong b2f0_result;
1902
1903 iucv_debug(2, "entering");
1904
1905 parm = (iparml_dpl *)grab_param();
1906
1907 parm->ippathid = pathid;
1908 parm->iptrgcls = trgcls;
1909 parm->ipsrccls = srccls;
1910 parm->ipmsgtag = msgtag;
1911 parm->ipflags1 = (IPRMDATA | IPNORPY | flags1);
1912 memcpy(parm->iprmmsg, prmmsg, sizeof(parm->iprmmsg));
1913
1914 b2f0_result = b2f0(SEND, parm);
1915
1916 if ((!b2f0_result) && (msgid))
1917 *msgid = parm->ipmsgid;
1918 release_param(parm);
1919
1920 iucv_debug(2, "exiting");
1921
1922 return b2f0_result;
1923}
1924
1925/*
1926 * Name: iucv_send2way
1927 * Purpose: This function transmits data to another application.
1928 * Data to be transmitted is in a buffer. The receiver
1929 * of the send is expected to reply to the message and
1930 * a buffer is provided into which IUCV moves the reply
1931 * to this message.
1932 * Input: pathid - path identification number
1933 * trgcls - specifies target class
1934 * srccls - specifies the source message class
1935 * msgtag - specifies a tag associated with the message
1936 * flags1 - option for path
1937 * IPPRTY- specifies if you want to send priority message
1938 * buffer - address of send buffer
1939 * buflen - length of send buffer
1940 * ansbuf - address of buffer to reply with
1941 * anslen - length of buffer to reply with
1942 * Output: msgid - specifies the message ID.
1943 * Return: b2f0_result - return code from CP
1944 * (-EINVAL) - buffer or ansbuf address is NULL
1945 */
1946int
1947iucv_send2way (__u16 pathid,
1948 __u32 * msgid,
1949 __u32 trgcls,
1950 __u32 srccls,
1951 __u32 msgtag,
1952 int flags1,
1953 void *buffer, ulong buflen, void *ansbuf, ulong anslen)
1954{
1955 iparml_db *parm;
1956 ulong b2f0_result;
1957
1958 iucv_debug(2, "entering");
1959
1960 if (!buffer || !ansbuf)
1961 return -EINVAL;
1962
1963 parm = (iparml_db *)grab_param();
1964
1965 parm->ippathid = pathid;
1966 parm->iptrgcls = trgcls;
1967 parm->ipbfadr1 = (__u32) ((ulong) buffer);
1968 parm->ipbfln1f = (__u32) buflen; /* length of message */
1969 parm->ipbfadr2 = (__u32) ((ulong) ansbuf);
1970 parm->ipbfln2f = (__u32) anslen;
1971 parm->ipsrccls = srccls;
1972 parm->ipmsgtag = msgtag;
1973 parm->ipflags1 = flags1; /* priority message */
1974
1975 b2f0_result = b2f0(SEND, parm);
1976
1977 if ((!b2f0_result) && (msgid))
1978 *msgid = parm->ipmsgid;
1979 release_param(parm);
1980
1981 iucv_debug(2, "exiting");
1982
1983 return b2f0_result;
1984}
1985
1986/*
1987 * Name: iucv_send2way_array
1988 * Purpose: This function transmits data to another application.
1989 * The contents of buffer is the address of the array of
1990 * addresses and lengths of discontiguous buffers that hold
1991 * the message text. The receiver of the send is expected to
1992 * reply to the message and a buffer is provided into which
1993 * IUCV moves the reply to this message.
1994 * Input: pathid - path identification number
1995 * trgcls - specifies target class
1996 * srccls - specifies the source message class
1997 * msgtag - spcifies a tag to be associated with the message
1998 * flags1 - option for path
1999 * IPPRTY- specifies if you want to send priority message
2000 * buffer - address of array of send buffers
2001 * buflen - total length of send buffers
2002 * ansbuf - address of buffer to reply with
2003 * anslen - length of buffer to reply with
2004 * Output: msgid - specifies the message ID.
2005 * Return: b2f0_result - return code from CP
2006 * (-EINVAL) - buffer address is NULL
2007 */
2008int
2009iucv_send2way_array (__u16 pathid,
2010 __u32 * msgid,
2011 __u32 trgcls,
2012 __u32 srccls,
2013 __u32 msgtag,
2014 int flags1,
2015 iucv_array_t * buffer,
2016 ulong buflen, iucv_array_t * ansbuf, ulong anslen)
2017{
2018 iparml_db *parm;
2019 ulong b2f0_result;
2020
2021 iucv_debug(2, "entering");
2022
2023 if (!buffer || !ansbuf)
2024 return -EINVAL;
2025
2026 parm = (iparml_db *)grab_param();
2027
2028 parm->ippathid = pathid;
2029 parm->iptrgcls = trgcls;
2030 parm->ipbfadr1 = (__u32) ((ulong) buffer);
2031 parm->ipbfln1f = (__u32) buflen; /* length of message */
2032 parm->ipbfadr2 = (__u32) ((ulong) ansbuf);
2033 parm->ipbfln2f = (__u32) anslen;
2034 parm->ipsrccls = srccls;
2035 parm->ipmsgtag = msgtag;
2036 parm->ipflags1 = (IPBUFLST | IPANSLST | flags1);
2037 b2f0_result = b2f0(SEND, parm);
2038 if ((!b2f0_result) && (msgid))
2039 *msgid = parm->ipmsgid;
2040 release_param(parm);
2041
2042 iucv_debug(2, "exiting");
2043 return b2f0_result;
2044}
2045
2046/*
2047 * Name: iucv_send2way_prmmsg
2048 * Purpose: This function transmits data to another application.
2049 * Prmmsg specifies that the 8-bytes of data are to be moved
2050 * into the parameter list. This is a two-way message and the
2051 * receiver of the message is expected to reply. A buffer
2052 * is provided into which IUCV moves the reply to this
2053 * message.
2054 * Input: pathid - path identification number
2055 * trgcls - specifies target class
2056 * srccls - specifies the source message class
2057 * msgtag - specifies a tag to be associated with the message
2058 * flags1 - option for path
2059 * IPPRTY- specifies if you want to send priority message
2060 * prmmsg - 8-bytes of data to be placed in parameter list
2061 * ansbuf - address of buffer to reply with
2062 * anslen - length of buffer to reply with
2063 * Output: msgid - specifies the message ID.
2064 * Return: b2f0_result - return code from CP
2065 * (-EINVAL) - buffer address is NULL
2066*/
2067int
2068iucv_send2way_prmmsg (__u16 pathid,
2069 __u32 * msgid,
2070 __u32 trgcls,
2071 __u32 srccls,
2072 __u32 msgtag,
2073 ulong flags1, __u8 prmmsg[8], void *ansbuf, ulong anslen)
2074{
2075 iparml_dpl *parm;
2076 ulong b2f0_result;
2077
2078 iucv_debug(2, "entering");
2079
2080 if (!ansbuf)
2081 return -EINVAL;
2082
2083 parm = (iparml_dpl *)grab_param();
2084
2085 parm->ippathid = pathid;
2086 parm->iptrgcls = trgcls;
2087 parm->ipsrccls = srccls;
2088 parm->ipmsgtag = msgtag;
2089 parm->ipbfadr2 = (__u32) ((ulong) ansbuf);
2090 parm->ipbfln2f = (__u32) anslen;
2091 parm->ipflags1 = (IPRMDATA | flags1); /* message in prmlist */
2092 memcpy(parm->iprmmsg, prmmsg, sizeof(parm->iprmmsg));
2093
2094 b2f0_result = b2f0(SEND, parm);
2095
2096 if ((!b2f0_result) && (msgid))
2097 *msgid = parm->ipmsgid;
2098 release_param(parm);
2099
2100 iucv_debug(2, "exiting");
2101
2102 return b2f0_result;
2103}
2104
2105/*
2106 * Name: iucv_send2way_prmmsg_array
2107 * Purpose: This function transmits data to another application.
2108 * Prmmsg specifies that the 8-bytes of data are to be moved
2109 * into the parameter list. This is a two-way message and the
2110 * receiver of the message is expected to reply. A buffer
2111 * is provided into which IUCV moves the reply to this
2112 * message. The contents of ansbuf is the address of the
2113 * array of addresses and lengths of discontiguous buffers
2114 * that contain the reply.
2115 * Input: pathid - path identification number
2116 * trgcls - specifies target class
2117 * srccls - specifies the source message class
2118 * msgtag - specifies a tag to be associated with the message
2119 * flags1 - option for path
2120 * IPPRTY- specifies if you want to send priority message
2121 * prmmsg - 8-bytes of data to be placed into the parameter list
2122 * ansbuf - address of buffer to reply with
2123 * anslen - length of buffer to reply with
2124 * Output: msgid - specifies the message ID.
2125 * Return: b2f0_result - return code from CP
2126 * (-EINVAL) - ansbuf address is NULL
2127 */
2128int
2129iucv_send2way_prmmsg_array (__u16 pathid,
2130 __u32 * msgid,
2131 __u32 trgcls,
2132 __u32 srccls,
2133 __u32 msgtag,
2134 int flags1,
2135 __u8 prmmsg[8],
2136 iucv_array_t * ansbuf, ulong anslen)
2137{
2138 iparml_dpl *parm;
2139 ulong b2f0_result;
2140
2141 iucv_debug(2, "entering");
2142
2143 if (!ansbuf)
2144 return -EINVAL;
2145
2146 parm = (iparml_dpl *)grab_param();
2147
2148 parm->ippathid = pathid;
2149 parm->iptrgcls = trgcls;
2150 parm->ipsrccls = srccls;
2151 parm->ipmsgtag = msgtag;
2152 parm->ipbfadr2 = (__u32) ((ulong) ansbuf);
2153 parm->ipbfln2f = (__u32) anslen;
2154 parm->ipflags1 = (IPRMDATA | IPANSLST | flags1);
2155 memcpy(parm->iprmmsg, prmmsg, sizeof(parm->iprmmsg));
2156 b2f0_result = b2f0(SEND, parm);
2157 if ((!b2f0_result) && (msgid))
2158 *msgid = parm->ipmsgid;
2159 release_param(parm);
2160
2161 iucv_debug(2, "exiting");
2162 return b2f0_result;
2163}
2164
2165void
2166iucv_setmask_cpuid (void *result)
2167{
2168 iparml_set_mask *parm;
2169
2170 iucv_debug(1, "entering");
2171 parm = (iparml_set_mask *)grab_param();
2172 parm->ipmask = *((__u8*)result);
2173 *((ulong *)result) = b2f0(SETMASK, parm);
2174 release_param(parm);
2175
2176 iucv_debug(1, "b2f0_result = %ld", *((ulong *)result));
2177 iucv_debug(1, "exiting");
2178}
2179
2180/*
2181 * Name: iucv_setmask
2182 * Purpose: This function enables or disables the following IUCV
2183 * external interruptions: Nonpriority and priority message
2184 * interrupts, nonpriority and priority reply interrupts.
2185 * Input: SetMaskFlag - options for interrupts
2186 * 0x80 - Nonpriority_MessagePendingInterruptsFlag
2187 * 0x40 - Priority_MessagePendingInterruptsFlag
2188 * 0x20 - Nonpriority_MessageCompletionInterruptsFlag
2189 * 0x10 - Priority_MessageCompletionInterruptsFlag
2190 * 0x08 - IUCVControlInterruptsFlag
2191 * Output: NA
2192 * Return: b2f0_result - return code from CP
2193*/
2194int
2195iucv_setmask (int SetMaskFlag)
2196{
2197 union {
2198 ulong result;
2199 __u8 param;
2200 } u;
2201 int cpu;
2202
2203 u.param = SetMaskFlag;
2204 cpu = get_cpu();
2205 smp_call_function_on(iucv_setmask_cpuid, &u, 0, 1, iucv_cpuid);
2206 put_cpu();
2207
2208 return u.result;
2209}
2210
2211/**
2212 * iucv_sever:
2213 * @pathid: Path identification number
2214 * @user_data: 16-byte of user data
2215 *
2216 * This function terminates an iucv path.
2217 * Returns: return code from CP
2218 */
2219int
2220iucv_sever(__u16 pathid, __u8 user_data[16])
2221{
2222 iparml_control *parm;
2223 ulong b2f0_result = 0;
2224
2225 iucv_debug(1, "entering");
2226 parm = (iparml_control *)grab_param();
2227
2228 memcpy(parm->ipuser, user_data, sizeof(parm->ipuser));
2229 parm->ippathid = pathid;
2230
2231 b2f0_result = b2f0(SEVER, parm);
2232
2233 if (!b2f0_result)
2234 iucv_remove_pathid(pathid);
2235 release_param(parm);
2236
2237 iucv_debug(1, "exiting");
2238 return b2f0_result;
2239}
2240
2241/*
2242 * Interrupt Handlers
2243 *******************************************************************************/
2244
2245/**
2246 * iucv_irq_handler:
2247 * @regs: Current registers
2248 * @code: irq code
2249 *
2250 * Handles external interrupts coming in from CP.
2251 * Places the interrupt buffer on a queue and schedules iucv_tasklet_handler().
2252 */
2253static void
2254iucv_irq_handler(__u16 code)
2255{
2256 iucv_irqdata *irqdata;
2257
2258 irqdata = kmalloc(sizeof(iucv_irqdata), GFP_ATOMIC);
2259 if (!irqdata) {
2260 printk(KERN_WARNING "%s: out of memory\n", __FUNCTION__);
2261 return;
2262 }
2263
2264 memcpy(&irqdata->data, iucv_external_int_buffer,
2265 sizeof(iucv_GeneralInterrupt));
2266
2267 spin_lock(&iucv_irq_queue_lock);
2268 list_add_tail(&irqdata->queue, &iucv_irq_queue);
2269 spin_unlock(&iucv_irq_queue_lock);
2270
2271 tasklet_schedule(&iucv_tasklet);
2272}
2273
2274/**
2275 * iucv_do_int:
2276 * @int_buf: Pointer to copy of external interrupt buffer
2277 *
2278 * The workhorse for handling interrupts queued by iucv_irq_handler().
2279 * This function is called from the bottom half iucv_tasklet_handler().
2280 */
2281static void
2282iucv_do_int(iucv_GeneralInterrupt * int_buf)
2283{
2284 handler *h = NULL;
2285 struct list_head *lh;
2286 ulong flags;
2287 iucv_interrupt_ops_t *interrupt = NULL; /* interrupt addresses */
2288 __u8 temp_buff1[24], temp_buff2[24]; /* masked handler id. */
2289 int rc = 0, j = 0;
2290 __u8 no_listener[16] = "NO LISTENER";
2291
2292 iucv_debug(2, "entering, pathid %d, type %02X",
2293 int_buf->ippathid, int_buf->iptype);
2294 iucv_dumpit("External Interrupt Buffer:",
2295 int_buf, sizeof(iucv_GeneralInterrupt));
2296
2297 ASCEBC (no_listener, 16);
2298
2299 if (int_buf->iptype != 01) {
2300 if ((int_buf->ippathid) > (max_connections - 1)) {
2301 printk(KERN_WARNING "%s: Got interrupt with pathid %d"
2302 " > max_connections (%ld)\n", __FUNCTION__,
2303 int_buf->ippathid, max_connections - 1);
2304 } else {
2305 h = iucv_pathid_table[int_buf->ippathid];
2306 interrupt = h->interrupt_table;
2307 iucv_dumpit("Handler:", h, sizeof(handler));
2308 }
2309 }
2310
2311 /* end of if statement */
2312 switch (int_buf->iptype) {
2313 case 0x01: /* connection pending */
2314 if (messagesDisabled) {
2315 iucv_setmask(~0);
2316 messagesDisabled = 0;
2317 }
2318 spin_lock_irqsave(&iucv_lock, flags);
2319 list_for_each(lh, &iucv_handler_table) {
2320 h = list_entry(lh, handler, list);
2321 memcpy(temp_buff1, &(int_buf->ipvmid), 24);
2322 memcpy(temp_buff2, &(h->id.userid), 24);
2323 for (j = 0; j < 24; j++) {
2324 temp_buff1[j] &= (h->id.mask)[j];
2325 temp_buff2[j] &= (h->id.mask)[j];
2326 }
2327
2328 iucv_dumpit("temp_buff1:",
2329 temp_buff1, sizeof(temp_buff1));
2330 iucv_dumpit("temp_buff2",
2331 temp_buff2, sizeof(temp_buff2));
2332
2333 if (!memcmp (temp_buff1, temp_buff2, 24)) {
2334
2335 iucv_debug(2,
2336 "found a matching handler");
2337 break;
2338 } else
2339 h = NULL;
2340 }
2341 spin_unlock_irqrestore (&iucv_lock, flags);
2342 if (h) {
2343 /* ADD PATH TO PATHID TABLE */
2344 rc = iucv_add_pathid(int_buf->ippathid, h);
2345 if (rc) {
2346 iucv_sever (int_buf->ippathid,
2347 no_listener);
2348 iucv_debug(1,
2349 "add_pathid failed, rc = %d",
2350 rc);
2351 } else {
2352 interrupt = h->interrupt_table;
2353 if (interrupt->ConnectionPending) {
2354 EBCASC (int_buf->ipvmid, 8);
2355 interrupt->ConnectionPending(
2356 (iucv_ConnectionPending *)int_buf,
2357 h->pgm_data);
2358 } else
2359 iucv_sever(int_buf->ippathid,
2360 no_listener);
2361 }
2362 } else
2363 iucv_sever(int_buf->ippathid, no_listener);
2364 break;
2365
2366 case 0x02: /*connection complete */
2367 if (messagesDisabled) {
2368 iucv_setmask(~0);
2369 messagesDisabled = 0;
2370 }
2371 if (h) {
2372 if (interrupt->ConnectionComplete)
2373 {
2374 interrupt->ConnectionComplete(
2375 (iucv_ConnectionComplete *)int_buf,
2376 h->pgm_data);
2377 }
2378 else
2379 iucv_debug(1,
2380 "ConnectionComplete not called");
2381 } else
2382 iucv_sever(int_buf->ippathid, no_listener);
2383 break;
2384
2385 case 0x03: /* connection severed */
2386 if (messagesDisabled) {
2387 iucv_setmask(~0);
2388 messagesDisabled = 0;
2389 }
2390 if (h) {
2391 if (interrupt->ConnectionSevered)
2392 interrupt->ConnectionSevered(
2393 (iucv_ConnectionSevered *)int_buf,
2394 h->pgm_data);
2395
2396 else
2397 iucv_sever (int_buf->ippathid, no_listener);
2398 } else
2399 iucv_sever(int_buf->ippathid, no_listener);
2400 break;
2401
2402 case 0x04: /* connection quiesced */
2403 if (messagesDisabled) {
2404 iucv_setmask(~0);
2405 messagesDisabled = 0;
2406 }
2407 if (h) {
2408 if (interrupt->ConnectionQuiesced)
2409 interrupt->ConnectionQuiesced(
2410 (iucv_ConnectionQuiesced *)int_buf,
2411 h->pgm_data);
2412 else
2413 iucv_debug(1,
2414 "ConnectionQuiesced not called");
2415 }
2416 break;
2417
2418 case 0x05: /* connection resumed */
2419 if (messagesDisabled) {
2420 iucv_setmask(~0);
2421 messagesDisabled = 0;
2422 }
2423 if (h) {
2424 if (interrupt->ConnectionResumed)
2425 interrupt->ConnectionResumed(
2426 (iucv_ConnectionResumed *)int_buf,
2427 h->pgm_data);
2428 else
2429 iucv_debug(1,
2430 "ConnectionResumed not called");
2431 }
2432 break;
2433
2434 case 0x06: /* priority message complete */
2435 case 0x07: /* nonpriority message complete */
2436 if (h) {
2437 if (interrupt->MessageComplete)
2438 interrupt->MessageComplete(
2439 (iucv_MessageComplete *)int_buf,
2440 h->pgm_data);
2441 else
2442 iucv_debug(2,
2443 "MessageComplete not called");
2444 }
2445 break;
2446
2447 case 0x08: /* priority message pending */
2448 case 0x09: /* nonpriority message pending */
2449 if (h) {
2450 if (interrupt->MessagePending)
2451 interrupt->MessagePending(
2452 (iucv_MessagePending *) int_buf,
2453 h->pgm_data);
2454 else
2455 iucv_debug(2,
2456 "MessagePending not called");
2457 }
2458 break;
2459 default: /* unknown iucv type */
2460 printk(KERN_WARNING "%s: unknown iucv interrupt\n",
2461 __FUNCTION__);
2462 break;
2463 } /* end switch */
2464
2465 iucv_debug(2, "exiting pathid %d, type %02X",
2466 int_buf->ippathid, int_buf->iptype);
2467
2468 return;
2469}
2470
2471/**
2472 * iucv_tasklet_handler:
2473 *
2474 * This function loops over the queue of irq buffers and runs iucv_do_int()
2475 * on every queue element.
2476 */
2477static void
2478iucv_tasklet_handler(unsigned long ignored)
2479{
2480 struct list_head head;
2481 struct list_head *next;
2482 ulong flags;
2483
2484 spin_lock_irqsave(&iucv_irq_queue_lock, flags);
2485 list_add(&head, &iucv_irq_queue);
2486 list_del_init(&iucv_irq_queue);
2487 spin_unlock_irqrestore (&iucv_irq_queue_lock, flags);
2488
2489 next = head.next;
2490 while (next != &head) {
2491 iucv_irqdata *p = list_entry(next, iucv_irqdata, queue);
2492
2493 next = next->next;
2494 iucv_do_int(&p->data);
2495 kfree(p);
2496 }
2497
2498 return;
2499}
2500
2501subsys_initcall(iucv_init);
2502module_exit(iucv_exit);
2503
2504/**
2505 * Export all public stuff
2506 */
2507EXPORT_SYMBOL (iucv_bus);
2508EXPORT_SYMBOL (iucv_root);
2509EXPORT_SYMBOL (iucv_accept);
2510EXPORT_SYMBOL (iucv_connect);
2511#if 0
2512EXPORT_SYMBOL (iucv_purge);
2513EXPORT_SYMBOL (iucv_query_maxconn);
2514EXPORT_SYMBOL (iucv_query_bufsize);
2515EXPORT_SYMBOL (iucv_quiesce);
2516#endif
2517EXPORT_SYMBOL (iucv_receive);
2518#if 0
2519EXPORT_SYMBOL (iucv_receive_array);
2520#endif
2521EXPORT_SYMBOL (iucv_reject);
2522#if 0
2523EXPORT_SYMBOL (iucv_reply);
2524EXPORT_SYMBOL (iucv_reply_array);
2525EXPORT_SYMBOL (iucv_resume);
2526#endif
2527EXPORT_SYMBOL (iucv_reply_prmmsg);
2528EXPORT_SYMBOL (iucv_send);
2529EXPORT_SYMBOL (iucv_send2way);
2530EXPORT_SYMBOL (iucv_send2way_array);
2531EXPORT_SYMBOL (iucv_send2way_prmmsg);
2532EXPORT_SYMBOL (iucv_send2way_prmmsg_array);
2533#if 0
2534EXPORT_SYMBOL (iucv_send_array);
2535EXPORT_SYMBOL (iucv_send_prmmsg);
2536EXPORT_SYMBOL (iucv_setmask);
2537#endif
2538EXPORT_SYMBOL (iucv_sever);
2539EXPORT_SYMBOL (iucv_register_program);
2540EXPORT_SYMBOL (iucv_unregister_program);
diff --git a/drivers/s390/net/iucv.h b/drivers/s390/net/iucv.h
deleted file mode 100644
index 5b6b1b7241c9..000000000000
--- a/drivers/s390/net/iucv.h
+++ /dev/null
@@ -1,849 +0,0 @@
1/*
2 * drivers/s390/net/iucv.h
3 * IUCV base support.
4 *
5 * S390 version
6 * Copyright (C) 2000 IBM Corporation
7 * Author(s):Alan Altmark (Alan_Altmark@us.ibm.com)
8 * Xenia Tkatschow (xenia@us.ibm.com)
9 *
10 *
11 * Functionality:
12 * To explore any of the IUCV functions, one must first register
13 * their program using iucv_register_program(). Once your program has
14 * successfully completed a register, it can exploit the other functions.
15 * For furthur reference on all IUCV functionality, refer to the
16 * CP Programming Services book, also available on the web
17 * thru www.ibm.com/s390/vm/pubs, manual # SC24-5760
18 *
19 * Definition of Return Codes
20 * -All positive return codes including zero are reflected back
21 * from CP except for iucv_register_program. The definition of each
22 * return code can be found in CP Programming Services book.
23 * Also available on the web thru www.ibm.com/s390/vm/pubs, manual # SC24-5760
24 * - Return Code of:
25 * (-EINVAL) Invalid value
26 * (-ENOMEM) storage allocation failed
27 * pgmask defined in iucv_register_program will be set depending on input
28 * paramters.
29 *
30 */
31
32#include <linux/types.h>
33#include <asm/debug.h>
34
35/**
36 * Debug Facility stuff
37 */
38#define IUCV_DBF_SETUP_NAME "iucv_setup"
39#define IUCV_DBF_SETUP_LEN 32
40#define IUCV_DBF_SETUP_PAGES 2
41#define IUCV_DBF_SETUP_NR_AREAS 1
42#define IUCV_DBF_SETUP_LEVEL 3
43
44#define IUCV_DBF_DATA_NAME "iucv_data"
45#define IUCV_DBF_DATA_LEN 128
46#define IUCV_DBF_DATA_PAGES 2
47#define IUCV_DBF_DATA_NR_AREAS 1
48#define IUCV_DBF_DATA_LEVEL 2
49
50#define IUCV_DBF_TRACE_NAME "iucv_trace"
51#define IUCV_DBF_TRACE_LEN 16
52#define IUCV_DBF_TRACE_PAGES 4
53#define IUCV_DBF_TRACE_NR_AREAS 1
54#define IUCV_DBF_TRACE_LEVEL 3
55
56#define IUCV_DBF_TEXT(name,level,text) \
57 do { \
58 debug_text_event(iucv_dbf_##name,level,text); \
59 } while (0)
60
61#define IUCV_DBF_HEX(name,level,addr,len) \
62 do { \
63 debug_event(iucv_dbf_##name,level,(void*)(addr),len); \
64 } while (0)
65
66DECLARE_PER_CPU(char[256], iucv_dbf_txt_buf);
67
68#define IUCV_DBF_TEXT_(name,level,text...) \
69 do { \
70 char* iucv_dbf_txt_buf = get_cpu_var(iucv_dbf_txt_buf); \
71 sprintf(iucv_dbf_txt_buf, text); \
72 debug_text_event(iucv_dbf_##name,level,iucv_dbf_txt_buf); \
73 put_cpu_var(iucv_dbf_txt_buf); \
74 } while (0)
75
76#define IUCV_DBF_SPRINTF(name,level,text...) \
77 do { \
78 debug_sprintf_event(iucv_dbf_trace, level, ##text ); \
79 debug_sprintf_event(iucv_dbf_trace, level, text ); \
80 } while (0)
81
82/**
83 * some more debug stuff
84 */
85#define IUCV_HEXDUMP16(importance,header,ptr) \
86PRINT_##importance(header "%02x %02x %02x %02x %02x %02x %02x %02x " \
87 "%02x %02x %02x %02x %02x %02x %02x %02x\n", \
88 *(((char*)ptr)),*(((char*)ptr)+1),*(((char*)ptr)+2), \
89 *(((char*)ptr)+3),*(((char*)ptr)+4),*(((char*)ptr)+5), \
90 *(((char*)ptr)+6),*(((char*)ptr)+7),*(((char*)ptr)+8), \
91 *(((char*)ptr)+9),*(((char*)ptr)+10),*(((char*)ptr)+11), \
92 *(((char*)ptr)+12),*(((char*)ptr)+13), \
93 *(((char*)ptr)+14),*(((char*)ptr)+15)); \
94PRINT_##importance(header "%02x %02x %02x %02x %02x %02x %02x %02x " \
95 "%02x %02x %02x %02x %02x %02x %02x %02x\n", \
96 *(((char*)ptr)+16),*(((char*)ptr)+17), \
97 *(((char*)ptr)+18),*(((char*)ptr)+19), \
98 *(((char*)ptr)+20),*(((char*)ptr)+21), \
99 *(((char*)ptr)+22),*(((char*)ptr)+23), \
100 *(((char*)ptr)+24),*(((char*)ptr)+25), \
101 *(((char*)ptr)+26),*(((char*)ptr)+27), \
102 *(((char*)ptr)+28),*(((char*)ptr)+29), \
103 *(((char*)ptr)+30),*(((char*)ptr)+31));
104
105static inline void
106iucv_hex_dump(unsigned char *buf, size_t len)
107{
108 size_t i;
109
110 for (i = 0; i < len; i++) {
111 if (i && !(i % 16))
112 printk("\n");
113 printk("%02x ", *(buf + i));
114 }
115 printk("\n");
116}
117/**
118 * end of debug stuff
119 */
120
121#define uchar unsigned char
122#define ushort unsigned short
123#define ulong unsigned long
124#define iucv_handle_t void *
125
126/* flags1:
127 * All flags are defined in the field IPFLAGS1 of each function
128 * and can be found in CP Programming Services.
129 * IPLOCAL - Indicates the connect can only be satisfied on the
130 * local system
131 * IPPRTY - Indicates a priority message
132 * IPQUSCE - Indicates you do not want to receive messages on a
133 * path until an iucv_resume is issued
134 * IPRMDATA - Indicates that the message is in the parameter list
135 */
136#define IPLOCAL 0x01
137#define IPPRTY 0x20
138#define IPQUSCE 0x40
139#define IPRMDATA 0x80
140
141/* flags1_out:
142 * All flags are defined in the output field of IPFLAGS1 for each function
143 * and can be found in CP Programming Services.
144 * IPNORPY - Specifies this is a one-way message and no reply is expected.
145 * IPPRTY - Indicates a priority message is permitted. Defined in flags1.
146 */
147#define IPNORPY 0x10
148
149#define Nonpriority_MessagePendingInterruptsFlag 0x80
150#define Priority_MessagePendingInterruptsFlag 0x40
151#define Nonpriority_MessageCompletionInterruptsFlag 0x20
152#define Priority_MessageCompletionInterruptsFlag 0x10
153#define IUCVControlInterruptsFlag 0x08
154#define AllInterrupts 0xf8
155/*
156 * Mapping of external interrupt buffers should be used with the corresponding
157 * interrupt types.
158 * Names: iucv_ConnectionPending -> connection pending
159 * iucv_ConnectionComplete -> connection complete
160 * iucv_ConnectionSevered -> connection severed
161 * iucv_ConnectionQuiesced -> connection quiesced
162 * iucv_ConnectionResumed -> connection resumed
163 * iucv_MessagePending -> message pending
164 * iucv_MessageComplete -> message complete
165 */
166typedef struct {
167 u16 ippathid;
168 uchar ipflags1;
169 uchar iptype;
170 u16 ipmsglim;
171 u16 res1;
172 uchar ipvmid[8];
173 uchar ipuser[16];
174 u32 res3;
175 uchar ippollfg;
176 uchar res4[3];
177} iucv_ConnectionPending;
178
179typedef struct {
180 u16 ippathid;
181 uchar ipflags1;
182 uchar iptype;
183 u16 ipmsglim;
184 u16 res1;
185 uchar res2[8];
186 uchar ipuser[16];
187 u32 res3;
188 uchar ippollfg;
189 uchar res4[3];
190} iucv_ConnectionComplete;
191
192typedef struct {
193 u16 ippathid;
194 uchar res1;
195 uchar iptype;
196 u32 res2;
197 uchar res3[8];
198 uchar ipuser[16];
199 u32 res4;
200 uchar ippollfg;
201 uchar res5[3];
202} iucv_ConnectionSevered;
203
204typedef struct {
205 u16 ippathid;
206 uchar res1;
207 uchar iptype;
208 u32 res2;
209 uchar res3[8];
210 uchar ipuser[16];
211 u32 res4;
212 uchar ippollfg;
213 uchar res5[3];
214} iucv_ConnectionQuiesced;
215
216typedef struct {
217 u16 ippathid;
218 uchar res1;
219 uchar iptype;
220 u32 res2;
221 uchar res3[8];
222 uchar ipuser[16];
223 u32 res4;
224 uchar ippollfg;
225 uchar res5[3];
226} iucv_ConnectionResumed;
227
228typedef struct {
229 u16 ippathid;
230 uchar ipflags1;
231 uchar iptype;
232 u32 ipmsgid;
233 u32 iptrgcls;
234 union u2 {
235 u32 iprmmsg1_u32;
236 uchar iprmmsg1[4];
237 } ln1msg1;
238 union u1 {
239 u32 ipbfln1f;
240 uchar iprmmsg2[4];
241 } ln1msg2;
242 u32 res1[3];
243 u32 ipbfln2f;
244 uchar ippollfg;
245 uchar res2[3];
246} iucv_MessagePending;
247
248typedef struct {
249 u16 ippathid;
250 uchar ipflags1;
251 uchar iptype;
252 u32 ipmsgid;
253 u32 ipaudit;
254 uchar iprmmsg[8];
255 u32 ipsrccls;
256 u32 ipmsgtag;
257 u32 res;
258 u32 ipbfln2f;
259 uchar ippollfg;
260 uchar res2[3];
261} iucv_MessageComplete;
262
263/*
264 * iucv_interrupt_ops_t: Is a vector of functions that handle
265 * IUCV interrupts.
266 * Parameter list:
267 * eib - is a pointer to a 40-byte area described
268 * with one of the structures above.
269 * pgm_data - this data is strictly for the
270 * interrupt handler that is passed by
271 * the application. This may be an address
272 * or token.
273*/
274typedef struct {
275 void (*ConnectionPending) (iucv_ConnectionPending * eib,
276 void *pgm_data);
277 void (*ConnectionComplete) (iucv_ConnectionComplete * eib,
278 void *pgm_data);
279 void (*ConnectionSevered) (iucv_ConnectionSevered * eib,
280 void *pgm_data);
281 void (*ConnectionQuiesced) (iucv_ConnectionQuiesced * eib,
282 void *pgm_data);
283 void (*ConnectionResumed) (iucv_ConnectionResumed * eib,
284 void *pgm_data);
285 void (*MessagePending) (iucv_MessagePending * eib, void *pgm_data);
286 void (*MessageComplete) (iucv_MessageComplete * eib, void *pgm_data);
287} iucv_interrupt_ops_t;
288
289/*
290 *iucv_array_t : Defines buffer array.
291 * Inside the array may be 31- bit addresses and 31-bit lengths.
292*/
293typedef struct {
294 u32 address;
295 u32 length;
296} iucv_array_t __attribute__ ((aligned (8)));
297
298extern struct bus_type iucv_bus;
299extern struct device *iucv_root;
300
301/* -prototypes- */
302/*
303 * Name: iucv_register_program
304 * Purpose: Registers an application with IUCV
305 * Input: prmname - user identification
306 * userid - machine identification
307 * pgmmask - indicates which bits in the prmname and userid combined will be
308 * used to determine who is given control
309 * ops - address of vector of interrupt handlers
310 * pgm_data- application data passed to interrupt handlers
311 * Output: NA
312 * Return: address of handler
313 * (0) - Error occurred, registration not completed.
314 * NOTE: Exact cause of failure will be recorded in syslog.
315*/
316iucv_handle_t iucv_register_program (uchar pgmname[16],
317 uchar userid[8],
318 uchar pgmmask[24],
319 iucv_interrupt_ops_t * ops,
320 void *pgm_data);
321
322/*
323 * Name: iucv_unregister_program
324 * Purpose: Unregister application with IUCV
325 * Input: address of handler
326 * Output: NA
327 * Return: (0) - Normal return
328 * (-EINVAL) - Internal error, wild pointer
329*/
330int iucv_unregister_program (iucv_handle_t handle);
331
332/*
333 * Name: iucv_accept
334 * Purpose: This function is issued after the user receives a Connection Pending external
335 * interrupt and now wishes to complete the IUCV communication path.
336 * Input: pathid - u16 , Path identification number
337 * msglim_reqstd - u16, The number of outstanding messages requested.
338 * user_data - uchar[16], Data specified by the iucv_connect function.
339 * flags1 - int, Contains options for this path.
340 * -IPPRTY - 0x20- Specifies if you want to send priority message.
341 * -IPRMDATA - 0x80, Specifies whether your program can handle a message
342 * in the parameter list.
343 * -IPQUSCE - 0x40, Specifies whether you want to quiesce the path being
344 * established.
345 * handle - iucv_handle_t, Address of handler.
346 * pgm_data - void *, Application data passed to interrupt handlers.
347 * flags1_out - int * Contains information about the path
348 * - IPPRTY - 0x20, Indicates you may send priority messages.
349 * msglim - *u16, Number of outstanding messages.
350 * Output: return code from CP IUCV call.
351*/
352
353int iucv_accept (u16 pathid,
354 u16 msglim_reqstd,
355 uchar user_data[16],
356 int flags1,
357 iucv_handle_t handle,
358 void *pgm_data, int *flags1_out, u16 * msglim);
359
360/*
361 * Name: iucv_connect
362 * Purpose: This function establishes an IUCV path. Although the connect may complete
363 * successfully, you are not able to use the path until you receive an IUCV
364 * Connection Complete external interrupt.
365 * Input: pathid - u16 *, Path identification number
366 * msglim_reqstd - u16, Number of outstanding messages requested
367 * user_data - uchar[16], 16-byte user data
368 * userid - uchar[8], User identification
369 * system_name - uchar[8], 8-byte identifying the system name
370 * flags1 - int, Contains options for this path.
371 * -IPPRTY - 0x20, Specifies if you want to send priority message.
372 * -IPRMDATA - 0x80, Specifies whether your program can handle a message
373 * in the parameter list.
374 * -IPQUSCE - 0x40, Specifies whether you want to quiesce the path being
375 * established.
376 * -IPLOCAL - 0X01, Allows an application to force the partner to be on
377 * the local system. If local is specified then target class cannot be
378 * specified.
379 * flags1_out - int * Contains information about the path
380 * - IPPRTY - 0x20, Indicates you may send priority messages.
381 * msglim - * u16, Number of outstanding messages
382 * handle - iucv_handle_t, Address of handler
383 * pgm_data - void *, Application data passed to interrupt handlers
384 * Output: return code from CP IUCV call
385 * rc - return code from iucv_declare_buffer
386 * -EINVAL - Invalid handle passed by application
387 * -EINVAL - Pathid address is NULL
388 * add_pathid_result - Return code from internal function add_pathid
389*/
390int
391 iucv_connect (u16 * pathid,
392 u16 msglim_reqstd,
393 uchar user_data[16],
394 uchar userid[8],
395 uchar system_name[8],
396 int flags1,
397 int *flags1_out,
398 u16 * msglim, iucv_handle_t handle, void *pgm_data);
399
400/*
401 * Name: iucv_purge
402 * Purpose: This function cancels a message that you have sent.
403 * Input: pathid - Path identification number.
404 * msgid - Specifies the message ID of the message to be purged.
405 * srccls - Specifies the source message class.
406 * Output: audit - Contains information about asynchronous error
407 * that may have affected the normal completion
408 * of this message.
409 * Return: Return code from CP IUCV call.
410*/
411int iucv_purge (u16 pathid, u32 msgid, u32 srccls, __u32 *audit);
412/*
413 * Name: iucv_query_maxconn
414 * Purpose: This function determines the maximum number of communication paths you
415 * may establish.
416 * Return: maxconn - ulong, Maximum number of connection the virtual machine may
417 * establish.
418*/
419ulong iucv_query_maxconn (void);
420
421/*
422 * Name: iucv_query_bufsize
423 * Purpose: This function determines how large an external interrupt
424 * buffer IUCV requires to store information.
425 * Return: bufsize - ulong, Size of external interrupt buffer.
426 */
427ulong iucv_query_bufsize (void);
428
429/*
430 * Name: iucv_quiesce
431 * Purpose: This function temporarily suspends incoming messages on an
432 * IUCV path. You can later reactivate the path by invoking
433 * the iucv_resume function.
434 * Input: pathid - Path identification number
435 * user_data - 16-bytes of user data
436 * Output: NA
437 * Return: Return code from CP IUCV call.
438*/
439int iucv_quiesce (u16 pathid, uchar user_data[16]);
440
441/*
442 * Name: iucv_receive
443 * Purpose: This function receives messages that are being sent to you
444 * over established paths. Data will be returned in buffer for length of
445 * buflen.
446 * Input:
447 * pathid - Path identification number.
448 * buffer - Address of buffer to receive.
449 * buflen - Length of buffer to receive.
450 * msgid - Specifies the message ID.
451 * trgcls - Specifies target class.
452 * Output:
453 * flags1_out: int *, Contains information about this path.
454 * IPNORPY - 0x10 Specifies this is a one-way message and no reply is
455 * expected.
456 * IPPRTY - 0x20 Specifies if you want to send priority message.
457 * IPRMDATA - 0x80 specifies the data is contained in the parameter list
458 * residual_buffer - address of buffer updated by the number
459 * of bytes you have received.
460 * residual_length -
461 * Contains one of the following values, if the receive buffer is:
462 * The same length as the message, this field is zero.
463 * Longer than the message, this field contains the number of
464 * bytes remaining in the buffer.
465 * Shorter than the message, this field contains the residual
466 * count (that is, the number of bytes remaining in the
467 * message that does not fit into the buffer. In this
468 * case b2f0_result = 5.
469 * Return: Return code from CP IUCV call.
470 * (-EINVAL) - buffer address is pointing to NULL
471*/
472int iucv_receive (u16 pathid,
473 u32 msgid,
474 u32 trgcls,
475 void *buffer,
476 ulong buflen,
477 int *flags1_out,
478 ulong * residual_buffer, ulong * residual_length);
479
480 /*
481 * Name: iucv_receive_array
482 * Purpose: This function receives messages that are being sent to you
483 * over established paths. Data will be returned in first buffer for
484 * length of first buffer.
485 * Input: pathid - Path identification number.
486 * msgid - specifies the message ID.
487 * trgcls - Specifies target class.
488 * buffer - Address of array of buffers.
489 * buflen - Total length of buffers.
490 * Output:
491 * flags1_out: int *, Contains information about this path.
492 * IPNORPY - 0x10 Specifies this is a one-way message and no reply is
493 * expected.
494 * IPPRTY - 0x20 Specifies if you want to send priority message.
495 * IPRMDATA - 0x80 specifies the data is contained in the parameter list
496 * residual_buffer - address points to the current list entry IUCV
497 * is working on.
498 * residual_length -
499 * Contains one of the following values, if the receive buffer is:
500 * The same length as the message, this field is zero.
501 * Longer than the message, this field contains the number of
502 * bytes remaining in the buffer.
503 * Shorter than the message, this field contains the residual
504 * count (that is, the number of bytes remaining in the
505 * message that does not fit into the buffer. In this
506 * case b2f0_result = 5.
507 * Return: Return code from CP IUCV call.
508 * (-EINVAL) - Buffer address is NULL.
509 */
510int iucv_receive_array (u16 pathid,
511 u32 msgid,
512 u32 trgcls,
513 iucv_array_t * buffer,
514 ulong buflen,
515 int *flags1_out,
516 ulong * residual_buffer, ulong * residual_length);
517
518/*
519 * Name: iucv_reject
520 * Purpose: The reject function refuses a specified message. Between the
521 * time you are notified of a message and the time that you
522 * complete the message, the message may be rejected.
523 * Input: pathid - Path identification number.
524 * msgid - Specifies the message ID.
525 * trgcls - Specifies target class.
526 * Output: NA
527 * Return: Return code from CP IUCV call.
528*/
529int iucv_reject (u16 pathid, u32 msgid, u32 trgcls);
530
531/*
532 * Name: iucv_reply
533 * Purpose: This function responds to the two-way messages that you
534 * receive. You must identify completely the message to
535 * which you wish to reply. ie, pathid, msgid, and trgcls.
536 * Input: pathid - Path identification number.
537 * msgid - Specifies the message ID.
538 * trgcls - Specifies target class.
539 * flags1 - Option for path.
540 * IPPRTY- 0x20, Specifies if you want to send priority message.
541 * buffer - Address of reply buffer.
542 * buflen - Length of reply buffer.
543 * Output: residual_buffer - Address of buffer updated by the number
544 * of bytes you have moved.
545 * residual_length - Contains one of the following values:
546 * If the answer buffer is the same length as the reply, this field
547 * contains zero.
548 * If the answer buffer is longer than the reply, this field contains
549 * the number of bytes remaining in the buffer.
550 * If the answer buffer is shorter than the reply, this field contains
551 * a residual count (that is, the number of bytes remianing in the
552 * reply that does not fit into the buffer. In this
553 * case b2f0_result = 5.
554 * Return: Return code from CP IUCV call.
555 * (-EINVAL) - Buffer address is NULL.
556*/
557int iucv_reply (u16 pathid,
558 u32 msgid,
559 u32 trgcls,
560 int flags1,
561 void *buffer, ulong buflen, ulong * residual_buffer,
562 ulong * residual_length);
563
564/*
565 * Name: iucv_reply_array
566 * Purpose: This function responds to the two-way messages that you
567 * receive. You must identify completely the message to
568 * which you wish to reply. ie, pathid, msgid, and trgcls.
569 * The array identifies a list of addresses and lengths of
570 * discontiguous buffers that contains the reply data.
571 * Input: pathid - Path identification number
572 * msgid - Specifies the message ID.
573 * trgcls - Specifies target class.
574 * flags1 - Option for path.
575 * IPPRTY- 0x20, Specifies if you want to send priority message.
576 * buffer - Address of array of reply buffers.
577 * buflen - Total length of reply buffers.
578 * Output: residual_buffer - Address of buffer which IUCV is currently working on.
579 * residual_length - Contains one of the following values:
580 * If the answer buffer is the same length as the reply, this field
581 * contains zero.
582 * If the answer buffer is longer than the reply, this field contains
583 * the number of bytes remaining in the buffer.
584 * If the answer buffer is shorter than the reply, this field contains
585 * a residual count (that is, the number of bytes remianing in the
586 * reply that does not fit into the buffer. In this
587 * case b2f0_result = 5.
588 * Return: Return code from CP IUCV call.
589 * (-EINVAL) - Buffer address is NULL.
590*/
591int iucv_reply_array (u16 pathid,
592 u32 msgid,
593 u32 trgcls,
594 int flags1,
595 iucv_array_t * buffer,
596 ulong buflen, ulong * residual_address,
597 ulong * residual_length);
598
599/*
600 * Name: iucv_reply_prmmsg
601 * Purpose: This function responds to the two-way messages that you
602 * receive. You must identify completely the message to
603 * which you wish to reply. ie, pathid, msgid, and trgcls.
604 * Prmmsg signifies the data is moved into the
605 * parameter list.
606 * Input: pathid - Path identification number.
607 * msgid - Specifies the message ID.
608 * trgcls - Specifies target class.
609 * flags1 - Option for path.
610 * IPPRTY- 0x20 Specifies if you want to send priority message.
611 * prmmsg - 8-bytes of data to be placed into the parameter.
612 * list.
613 * Output: NA
614 * Return: Return code from CP IUCV call.
615*/
616int iucv_reply_prmmsg (u16 pathid,
617 u32 msgid, u32 trgcls, int flags1, uchar prmmsg[8]);
618
619/*
620 * Name: iucv_resume
621 * Purpose: This function restores communications over a quiesced path
622 * Input: pathid - Path identification number.
623 * user_data - 16-bytes of user data.
624 * Output: NA
625 * Return: Return code from CP IUCV call.
626*/
627int iucv_resume (u16 pathid, uchar user_data[16]);
628
629/*
630 * Name: iucv_send
631 * Purpose: This function transmits data to another application.
632 * Data to be transmitted is in a buffer and this is a
633 * one-way message and the receiver will not reply to the
634 * message.
635 * Input: pathid - Path identification number.
636 * trgcls - Specifies target class.
637 * srccls - Specifies the source message class.
638 * msgtag - Specifies a tag to be associated with the message.
639 * flags1 - Option for path.
640 * IPPRTY- 0x20 Specifies if you want to send priority message.
641 * buffer - Address of send buffer.
642 * buflen - Length of send buffer.
643 * Output: msgid - Specifies the message ID.
644 * Return: Return code from CP IUCV call.
645 * (-EINVAL) - Buffer address is NULL.
646*/
647int iucv_send (u16 pathid,
648 u32 * msgid,
649 u32 trgcls,
650 u32 srccls, u32 msgtag, int flags1, void *buffer, ulong buflen);
651
652/*
653 * Name: iucv_send_array
654 * Purpose: This function transmits data to another application.
655 * The contents of buffer is the address of the array of
656 * addresses and lengths of discontiguous buffers that hold
657 * the message text. This is a one-way message and the
658 * receiver will not reply to the message.
659 * Input: pathid - Path identification number.
660 * trgcls - Specifies target class.
661 * srccls - Specifies the source message class.
662 * msgtag - Specifies a tag to be associated witht the message.
663 * flags1 - Option for path.
664 * IPPRTY- specifies if you want to send priority message.
665 * buffer - Address of array of send buffers.
666 * buflen - Total length of send buffers.
667 * Output: msgid - Specifies the message ID.
668 * Return: Return code from CP IUCV call.
669 * (-EINVAL) - Buffer address is NULL.
670*/
671int iucv_send_array (u16 pathid,
672 u32 * msgid,
673 u32 trgcls,
674 u32 srccls,
675 u32 msgtag,
676 int flags1, iucv_array_t * buffer, ulong buflen);
677
678/*
679 * Name: iucv_send_prmmsg
680 * Purpose: This function transmits data to another application.
681 * Prmmsg specifies that the 8-bytes of data are to be moved
682 * into the parameter list. This is a one-way message and the
683 * receiver will not reply to the message.
684 * Input: pathid - Path identification number.
685 * trgcls - Specifies target class.
686 * srccls - Specifies the source message class.
687 * msgtag - Specifies a tag to be associated with the message.
688 * flags1 - Option for path.
689 * IPPRTY- 0x20 specifies if you want to send priority message.
690 * prmmsg - 8-bytes of data to be placed into parameter list.
691 * Output: msgid - Specifies the message ID.
692 * Return: Return code from CP IUCV call.
693*/
694int iucv_send_prmmsg (u16 pathid,
695 u32 * msgid,
696 u32 trgcls,
697 u32 srccls, u32 msgtag, int flags1, uchar prmmsg[8]);
698
699/*
700 * Name: iucv_send2way
701 * Purpose: This function transmits data to another application.
702 * Data to be transmitted is in a buffer. The receiver
703 * of the send is expected to reply to the message and
704 * a buffer is provided into which IUCV moves the reply
705 * to this message.
706 * Input: pathid - Path identification number.
707 * trgcls - Specifies target class.
708 * srccls - Specifies the source message class.
709 * msgtag - Specifies a tag associated with the message.
710 * flags1 - Option for path.
711 * IPPRTY- 0x20 Specifies if you want to send priority message.
712 * buffer - Address of send buffer.
713 * buflen - Length of send buffer.
714 * ansbuf - Address of buffer into which IUCV moves the reply of
715 * this message.
716 * anslen - Address of length of buffer.
717 * Output: msgid - Specifies the message ID.
718 * Return: Return code from CP IUCV call.
719 * (-EINVAL) - Buffer or ansbuf address is NULL.
720*/
721int iucv_send2way (u16 pathid,
722 u32 * msgid,
723 u32 trgcls,
724 u32 srccls,
725 u32 msgtag,
726 int flags1,
727 void *buffer, ulong buflen, void *ansbuf, ulong anslen);
728
729/*
730 * Name: iucv_send2way_array
731 * Purpose: This function transmits data to another application.
732 * The contents of buffer is the address of the array of
733 * addresses and lengths of discontiguous buffers that hold
734 * the message text. The receiver of the send is expected to
735 * reply to the message and a buffer is provided into which
736 * IUCV moves the reply to this message.
737 * Input: pathid - Path identification number.
738 * trgcls - Specifies target class.
739 * srccls - Specifies the source message class.
740 * msgtag - Specifies a tag to be associated with the message.
741 * flags1 - Option for path.
742 * IPPRTY- 0x20 Specifies if you want to send priority message.
743 * buffer - Sddress of array of send buffers.
744 * buflen - Total length of send buffers.
745 * ansbuf - Address of array of buffer into which IUCV moves the reply
746 * of this message.
747 * anslen - Address of length reply buffers.
748 * Output: msgid - Specifies the message ID.
749 * Return: Return code from CP IUCV call.
750 * (-EINVAL) - Buffer address is NULL.
751*/
752int iucv_send2way_array (u16 pathid,
753 u32 * msgid,
754 u32 trgcls,
755 u32 srccls,
756 u32 msgtag,
757 int flags1,
758 iucv_array_t * buffer,
759 ulong buflen, iucv_array_t * ansbuf, ulong anslen);
760
761/*
762 * Name: iucv_send2way_prmmsg
763 * Purpose: This function transmits data to another application.
764 * Prmmsg specifies that the 8-bytes of data are to be moved
765 * into the parameter list. This is a two-way message and the
766 * receiver of the message is expected to reply. A buffer
767 * is provided into which IUCV moves the reply to this
768 * message.
769 * Input: pathid - Rath identification number.
770 * trgcls - Specifies target class.
771 * srccls - Specifies the source message class.
772 * msgtag - Specifies a tag to be associated with the message.
773 * flags1 - Option for path.
774 * IPPRTY- 0x20 Specifies if you want to send priority message.
775 * prmmsg - 8-bytes of data to be placed in parameter list.
776 * ansbuf - Address of buffer into which IUCV moves the reply of
777 * this message.
778 * anslen - Address of length of buffer.
779 * Output: msgid - Specifies the message ID.
780 * Return: Return code from CP IUCV call.
781 * (-EINVAL) - Buffer address is NULL.
782*/
783int iucv_send2way_prmmsg (u16 pathid,
784 u32 * msgid,
785 u32 trgcls,
786 u32 srccls,
787 u32 msgtag,
788 ulong flags1,
789 uchar prmmsg[8], void *ansbuf, ulong anslen);
790
791/*
792 * Name: iucv_send2way_prmmsg_array
793 * Purpose: This function transmits data to another application.
794 * Prmmsg specifies that the 8-bytes of data are to be moved
795 * into the parameter list. This is a two-way message and the
796 * receiver of the message is expected to reply. A buffer
797 * is provided into which IUCV moves the reply to this
798 * message. The contents of ansbuf is the address of the
799 * array of addresses and lengths of discontiguous buffers
800 * that contain the reply.
801 * Input: pathid - Path identification number.
802 * trgcls - Specifies target class.
803 * srccls - Specifies the source message class.
804 * msgtag - Specifies a tag to be associated with the message.
805 * flags1 - Option for path.
806 * IPPRTY- 0x20 specifies if you want to send priority message.
807 * prmmsg - 8-bytes of data to be placed into the parameter list.
808 * ansbuf - Address of array of buffer into which IUCV moves the reply
809 * of this message.
810 * anslen - Address of length of reply buffers.
811 * Output: msgid - Specifies the message ID.
812 * Return: Return code from CP IUCV call.
813 * (-EINVAL) - Ansbuf address is NULL.
814*/
815int iucv_send2way_prmmsg_array (u16 pathid,
816 u32 * msgid,
817 u32 trgcls,
818 u32 srccls,
819 u32 msgtag,
820 int flags1,
821 uchar prmmsg[8],
822 iucv_array_t * ansbuf, ulong anslen);
823
824/*
825 * Name: iucv_setmask
826 * Purpose: This function enables or disables the following IUCV
827 * external interruptions: Nonpriority and priority message
828 * interrupts, nonpriority and priority reply interrupts.
829 * Input: SetMaskFlag - options for interrupts
830 * 0x80 - Nonpriority_MessagePendingInterruptsFlag
831 * 0x40 - Priority_MessagePendingInterruptsFlag
832 * 0x20 - Nonpriority_MessageCompletionInterruptsFlag
833 * 0x10 - Priority_MessageCompletionInterruptsFlag
834 * 0x08 - IUCVControlInterruptsFlag
835 * Output: NA
836 * Return: Return code from CP IUCV call.
837*/
838int iucv_setmask (int SetMaskFlag);
839
840/*
841 * Name: iucv_sever
842 * Purpose: This function terminates an IUCV path.
843 * Input: pathid - Path identification number.
844 * user_data - 16-bytes of user data.
845 * Output: NA
846 * Return: Return code from CP IUCV call.
847 * (-EINVAL) - Interal error, wild pointer.
848*/
849int iucv_sever (u16 pathid, uchar user_data[16]);
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
index 3346088f47e0..6387b483f2bf 100644
--- a/drivers/s390/net/netiucv.c
+++ b/drivers/s390/net/netiucv.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * IUCV network driver 2 * IUCV network driver
3 * 3 *
4 * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation 4 * Copyright 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
5 * Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com) 5 * Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com)
6 * 6 *
7 * Sysfs integration and all bugs therein by Cornelia Huck 7 * Sysfs integration and all bugs therein by Cornelia Huck
@@ -58,13 +58,94 @@
58#include <asm/io.h> 58#include <asm/io.h>
59#include <asm/uaccess.h> 59#include <asm/uaccess.h>
60 60
61#include "iucv.h" 61#include <net/iucv/iucv.h>
62#include "fsm.h" 62#include "fsm.h"
63 63
64MODULE_AUTHOR 64MODULE_AUTHOR
65 ("(C) 2001 IBM Corporation by Fritz Elfert (felfert@millenux.com)"); 65 ("(C) 2001 IBM Corporation by Fritz Elfert (felfert@millenux.com)");
66MODULE_DESCRIPTION ("Linux for S/390 IUCV network driver"); 66MODULE_DESCRIPTION ("Linux for S/390 IUCV network driver");
67 67
68/**
69 * Debug Facility stuff
70 */
71#define IUCV_DBF_SETUP_NAME "iucv_setup"
72#define IUCV_DBF_SETUP_LEN 32
73#define IUCV_DBF_SETUP_PAGES 2
74#define IUCV_DBF_SETUP_NR_AREAS 1
75#define IUCV_DBF_SETUP_LEVEL 3
76
77#define IUCV_DBF_DATA_NAME "iucv_data"
78#define IUCV_DBF_DATA_LEN 128
79#define IUCV_DBF_DATA_PAGES 2
80#define IUCV_DBF_DATA_NR_AREAS 1
81#define IUCV_DBF_DATA_LEVEL 2
82
83#define IUCV_DBF_TRACE_NAME "iucv_trace"
84#define IUCV_DBF_TRACE_LEN 16
85#define IUCV_DBF_TRACE_PAGES 4
86#define IUCV_DBF_TRACE_NR_AREAS 1
87#define IUCV_DBF_TRACE_LEVEL 3
88
89#define IUCV_DBF_TEXT(name,level,text) \
90 do { \
91 debug_text_event(iucv_dbf_##name,level,text); \
92 } while (0)
93
94#define IUCV_DBF_HEX(name,level,addr,len) \
95 do { \
96 debug_event(iucv_dbf_##name,level,(void*)(addr),len); \
97 } while (0)
98
99DECLARE_PER_CPU(char[256], iucv_dbf_txt_buf);
100
101#define IUCV_DBF_TEXT_(name,level,text...) \
102 do { \
103 char* iucv_dbf_txt_buf = get_cpu_var(iucv_dbf_txt_buf); \
104 sprintf(iucv_dbf_txt_buf, text); \
105 debug_text_event(iucv_dbf_##name,level,iucv_dbf_txt_buf); \
106 put_cpu_var(iucv_dbf_txt_buf); \
107 } while (0)
108
109#define IUCV_DBF_SPRINTF(name,level,text...) \
110 do { \
111 debug_sprintf_event(iucv_dbf_trace, level, ##text ); \
112 debug_sprintf_event(iucv_dbf_trace, level, text ); \
113 } while (0)
114
115/**
116 * some more debug stuff
117 */
118#define IUCV_HEXDUMP16(importance,header,ptr) \
119PRINT_##importance(header "%02x %02x %02x %02x %02x %02x %02x %02x " \
120 "%02x %02x %02x %02x %02x %02x %02x %02x\n", \
121 *(((char*)ptr)),*(((char*)ptr)+1),*(((char*)ptr)+2), \
122 *(((char*)ptr)+3),*(((char*)ptr)+4),*(((char*)ptr)+5), \
123 *(((char*)ptr)+6),*(((char*)ptr)+7),*(((char*)ptr)+8), \
124 *(((char*)ptr)+9),*(((char*)ptr)+10),*(((char*)ptr)+11), \
125 *(((char*)ptr)+12),*(((char*)ptr)+13), \
126 *(((char*)ptr)+14),*(((char*)ptr)+15)); \
127PRINT_##importance(header "%02x %02x %02x %02x %02x %02x %02x %02x " \
128 "%02x %02x %02x %02x %02x %02x %02x %02x\n", \
129 *(((char*)ptr)+16),*(((char*)ptr)+17), \
130 *(((char*)ptr)+18),*(((char*)ptr)+19), \
131 *(((char*)ptr)+20),*(((char*)ptr)+21), \
132 *(((char*)ptr)+22),*(((char*)ptr)+23), \
133 *(((char*)ptr)+24),*(((char*)ptr)+25), \
134 *(((char*)ptr)+26),*(((char*)ptr)+27), \
135 *(((char*)ptr)+28),*(((char*)ptr)+29), \
136 *(((char*)ptr)+30),*(((char*)ptr)+31));
137
138static inline void iucv_hex_dump(unsigned char *buf, size_t len)
139{
140 size_t i;
141
142 for (i = 0; i < len; i++) {
143 if (i && !(i % 16))
144 printk("\n");
145 printk("%02x ", *(buf + i));
146 }
147 printk("\n");
148}
68 149
69#define PRINTK_HEADER " iucv: " /* for debugging */ 150#define PRINTK_HEADER " iucv: " /* for debugging */
70 151
@@ -73,6 +154,25 @@ static struct device_driver netiucv_driver = {
73 .bus = &iucv_bus, 154 .bus = &iucv_bus,
74}; 155};
75 156
157static int netiucv_callback_connreq(struct iucv_path *,
158 u8 ipvmid[8], u8 ipuser[16]);
159static void netiucv_callback_connack(struct iucv_path *, u8 ipuser[16]);
160static void netiucv_callback_connrej(struct iucv_path *, u8 ipuser[16]);
161static void netiucv_callback_connsusp(struct iucv_path *, u8 ipuser[16]);
162static void netiucv_callback_connres(struct iucv_path *, u8 ipuser[16]);
163static void netiucv_callback_rx(struct iucv_path *, struct iucv_message *);
164static void netiucv_callback_txdone(struct iucv_path *, struct iucv_message *);
165
166static struct iucv_handler netiucv_handler = {
167 .path_pending = netiucv_callback_connreq,
168 .path_complete = netiucv_callback_connack,
169 .path_severed = netiucv_callback_connrej,
170 .path_quiesced = netiucv_callback_connsusp,
171 .path_resumed = netiucv_callback_connres,
172 .message_pending = netiucv_callback_rx,
173 .message_complete = netiucv_callback_txdone
174};
175
76/** 176/**
77 * Per connection profiling data 177 * Per connection profiling data
78 */ 178 */
@@ -92,9 +192,8 @@ struct connection_profile {
92 * Representation of one iucv connection 192 * Representation of one iucv connection
93 */ 193 */
94struct iucv_connection { 194struct iucv_connection {
95 struct iucv_connection *next; 195 struct list_head list;
96 iucv_handle_t handle; 196 struct iucv_path *path;
97 __u16 pathid;
98 struct sk_buff *rx_buff; 197 struct sk_buff *rx_buff;
99 struct sk_buff *tx_buff; 198 struct sk_buff *tx_buff;
100 struct sk_buff_head collect_queue; 199 struct sk_buff_head collect_queue;
@@ -112,12 +211,9 @@ struct iucv_connection {
112/** 211/**
113 * Linked list of all connection structs. 212 * Linked list of all connection structs.
114 */ 213 */
115struct iucv_connection_struct { 214static struct list_head iucv_connection_list =
116 struct iucv_connection *iucv_connections; 215 LIST_HEAD_INIT(iucv_connection_list);
117 rwlock_t iucv_rwlock; 216static rwlock_t iucv_connection_rwlock = RW_LOCK_UNLOCKED;
118};
119
120static struct iucv_connection_struct iucv_conns;
121 217
122/** 218/**
123 * Representation of event-data for the 219 * Representation of event-data for the
@@ -142,11 +238,11 @@ struct netiucv_priv {
142/** 238/**
143 * Link level header for a packet. 239 * Link level header for a packet.
144 */ 240 */
145typedef struct ll_header_t { 241struct ll_header {
146 __u16 next; 242 u16 next;
147} ll_header; 243};
148 244
149#define NETIUCV_HDRLEN (sizeof(ll_header)) 245#define NETIUCV_HDRLEN (sizeof(struct ll_header))
150#define NETIUCV_BUFSIZE_MAX 32768 246#define NETIUCV_BUFSIZE_MAX 32768
151#define NETIUCV_BUFSIZE_DEFAULT NETIUCV_BUFSIZE_MAX 247#define NETIUCV_BUFSIZE_DEFAULT NETIUCV_BUFSIZE_MAX
152#define NETIUCV_MTU_MAX (NETIUCV_BUFSIZE_MAX - NETIUCV_HDRLEN) 248#define NETIUCV_MTU_MAX (NETIUCV_BUFSIZE_MAX - NETIUCV_HDRLEN)
@@ -158,36 +254,26 @@ typedef struct ll_header_t {
158 * Compatibility macros for busy handling 254 * Compatibility macros for busy handling
159 * of network devices. 255 * of network devices.
160 */ 256 */
161static __inline__ void netiucv_clear_busy(struct net_device *dev) 257static inline void netiucv_clear_busy(struct net_device *dev)
162{ 258{
163 clear_bit(0, &(((struct netiucv_priv *)dev->priv)->tbusy)); 259 struct netiucv_priv *priv = netdev_priv(dev);
260 clear_bit(0, &priv->tbusy);
164 netif_wake_queue(dev); 261 netif_wake_queue(dev);
165} 262}
166 263
167static __inline__ int netiucv_test_and_set_busy(struct net_device *dev) 264static inline int netiucv_test_and_set_busy(struct net_device *dev)
168{ 265{
266 struct netiucv_priv *priv = netdev_priv(dev);
169 netif_stop_queue(dev); 267 netif_stop_queue(dev);
170 return test_and_set_bit(0, &((struct netiucv_priv *)dev->priv)->tbusy); 268 return test_and_set_bit(0, &priv->tbusy);
171} 269}
172 270
173static __u8 iucv_host[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 271static u8 iucvMagic[16] = {
174static __u8 iucvMagic[16] = {
175 0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 272 0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
176 0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 273 0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40
177}; 274};
178 275
179/** 276/**
180 * This mask means the 16-byte IUCV "magic" and the origin userid must
181 * match exactly as specified in order to give connection_pending()
182 * control.
183 */
184static __u8 netiucv_mask[] = {
185 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
186 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
187 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
188};
189
190/**
191 * Convert an iucv userId to its printable 277 * Convert an iucv userId to its printable
192 * form (strip whitespace at end). 278 * form (strip whitespace at end).
193 * 279 *
@@ -195,8 +281,7 @@ static __u8 netiucv_mask[] = {
195 * 281 *
196 * @returns The printable string (static data!!) 282 * @returns The printable string (static data!!)
197 */ 283 */
198static __inline__ char * 284static inline char *netiucv_printname(char *name)
199netiucv_printname(char *name)
200{ 285{
201 static char tmp[9]; 286 static char tmp[9];
202 char *p = tmp; 287 char *p = tmp;
@@ -379,8 +464,7 @@ static debug_info_t *iucv_dbf_trace = NULL;
379 464
380DEFINE_PER_CPU(char[256], iucv_dbf_txt_buf); 465DEFINE_PER_CPU(char[256], iucv_dbf_txt_buf);
381 466
382static void 467static void iucv_unregister_dbf_views(void)
383iucv_unregister_dbf_views(void)
384{ 468{
385 if (iucv_dbf_setup) 469 if (iucv_dbf_setup)
386 debug_unregister(iucv_dbf_setup); 470 debug_unregister(iucv_dbf_setup);
@@ -389,8 +473,7 @@ iucv_unregister_dbf_views(void)
389 if (iucv_dbf_trace) 473 if (iucv_dbf_trace)
390 debug_unregister(iucv_dbf_trace); 474 debug_unregister(iucv_dbf_trace);
391} 475}
392static int 476static int iucv_register_dbf_views(void)
393iucv_register_dbf_views(void)
394{ 477{
395 iucv_dbf_setup = debug_register(IUCV_DBF_SETUP_NAME, 478 iucv_dbf_setup = debug_register(IUCV_DBF_SETUP_NAME,
396 IUCV_DBF_SETUP_PAGES, 479 IUCV_DBF_SETUP_PAGES,
@@ -422,125 +505,111 @@ iucv_register_dbf_views(void)
422 return 0; 505 return 0;
423} 506}
424 507
425/** 508/*
426 * Callback-wrappers, called from lowlevel iucv layer. 509 * Callback-wrappers, called from lowlevel iucv layer.
427 *****************************************************************************/ 510 */
428 511
429static void 512static void netiucv_callback_rx(struct iucv_path *path,
430netiucv_callback_rx(iucv_MessagePending *eib, void *pgm_data) 513 struct iucv_message *msg)
431{ 514{
432 struct iucv_connection *conn = (struct iucv_connection *)pgm_data; 515 struct iucv_connection *conn = path->private;
433 struct iucv_event ev; 516 struct iucv_event ev;
434 517
435 ev.conn = conn; 518 ev.conn = conn;
436 ev.data = (void *)eib; 519 ev.data = msg;
437
438 fsm_event(conn->fsm, CONN_EVENT_RX, &ev); 520 fsm_event(conn->fsm, CONN_EVENT_RX, &ev);
439} 521}
440 522
441static void 523static void netiucv_callback_txdone(struct iucv_path *path,
442netiucv_callback_txdone(iucv_MessageComplete *eib, void *pgm_data) 524 struct iucv_message *msg)
443{ 525{
444 struct iucv_connection *conn = (struct iucv_connection *)pgm_data; 526 struct iucv_connection *conn = path->private;
445 struct iucv_event ev; 527 struct iucv_event ev;
446 528
447 ev.conn = conn; 529 ev.conn = conn;
448 ev.data = (void *)eib; 530 ev.data = msg;
449 fsm_event(conn->fsm, CONN_EVENT_TXDONE, &ev); 531 fsm_event(conn->fsm, CONN_EVENT_TXDONE, &ev);
450} 532}
451 533
452static void 534static void netiucv_callback_connack(struct iucv_path *path, u8 ipuser[16])
453netiucv_callback_connack(iucv_ConnectionComplete *eib, void *pgm_data)
454{ 535{
455 struct iucv_connection *conn = (struct iucv_connection *)pgm_data; 536 struct iucv_connection *conn = path->private;
456 struct iucv_event ev;
457 537
458 ev.conn = conn; 538 fsm_event(conn->fsm, CONN_EVENT_CONN_ACK, conn);
459 ev.data = (void *)eib;
460 fsm_event(conn->fsm, CONN_EVENT_CONN_ACK, &ev);
461} 539}
462 540
463static void 541static int netiucv_callback_connreq(struct iucv_path *path,
464netiucv_callback_connreq(iucv_ConnectionPending *eib, void *pgm_data) 542 u8 ipvmid[8], u8 ipuser[16])
465{ 543{
466 struct iucv_connection *conn = (struct iucv_connection *)pgm_data; 544 struct iucv_connection *conn = path->private;
467 struct iucv_event ev; 545 struct iucv_event ev;
546 int rc;
468 547
469 ev.conn = conn; 548 if (memcmp(iucvMagic, ipuser, sizeof(ipuser)))
470 ev.data = (void *)eib; 549 /* ipuser must match iucvMagic. */
471 fsm_event(conn->fsm, CONN_EVENT_CONN_REQ, &ev); 550 return -EINVAL;
551 rc = -EINVAL;
552 read_lock_bh(&iucv_connection_rwlock);
553 list_for_each_entry(conn, &iucv_connection_list, list) {
554 if (strncmp(ipvmid, conn->userid, 8))
555 continue;
556 /* Found a matching connection for this path. */
557 conn->path = path;
558 ev.conn = conn;
559 ev.data = path;
560 fsm_event(conn->fsm, CONN_EVENT_CONN_REQ, &ev);
561 rc = 0;
562 }
563 read_unlock_bh(&iucv_connection_rwlock);
564 return rc;
472} 565}
473 566
474static void 567static void netiucv_callback_connrej(struct iucv_path *path, u8 ipuser[16])
475netiucv_callback_connrej(iucv_ConnectionSevered *eib, void *pgm_data)
476{ 568{
477 struct iucv_connection *conn = (struct iucv_connection *)pgm_data; 569 struct iucv_connection *conn = path->private;
478 struct iucv_event ev;
479 570
480 ev.conn = conn; 571 fsm_event(conn->fsm, CONN_EVENT_CONN_REJ, conn);
481 ev.data = (void *)eib;
482 fsm_event(conn->fsm, CONN_EVENT_CONN_REJ, &ev);
483} 572}
484 573
485static void 574static void netiucv_callback_connsusp(struct iucv_path *path, u8 ipuser[16])
486netiucv_callback_connsusp(iucv_ConnectionQuiesced *eib, void *pgm_data)
487{ 575{
488 struct iucv_connection *conn = (struct iucv_connection *)pgm_data; 576 struct iucv_connection *conn = path->private;
489 struct iucv_event ev;
490 577
491 ev.conn = conn; 578 fsm_event(conn->fsm, CONN_EVENT_CONN_SUS, conn);
492 ev.data = (void *)eib;
493 fsm_event(conn->fsm, CONN_EVENT_CONN_SUS, &ev);
494} 579}
495 580
496static void 581static void netiucv_callback_connres(struct iucv_path *path, u8 ipuser[16])
497netiucv_callback_connres(iucv_ConnectionResumed *eib, void *pgm_data)
498{ 582{
499 struct iucv_connection *conn = (struct iucv_connection *)pgm_data; 583 struct iucv_connection *conn = path->private;
500 struct iucv_event ev;
501 584
502 ev.conn = conn; 585 fsm_event(conn->fsm, CONN_EVENT_CONN_RES, conn);
503 ev.data = (void *)eib; 586}
504 fsm_event(conn->fsm, CONN_EVENT_CONN_RES, &ev);
505}
506
507static iucv_interrupt_ops_t netiucv_ops = {
508 .ConnectionPending = netiucv_callback_connreq,
509 .ConnectionComplete = netiucv_callback_connack,
510 .ConnectionSevered = netiucv_callback_connrej,
511 .ConnectionQuiesced = netiucv_callback_connsusp,
512 .ConnectionResumed = netiucv_callback_connres,
513 .MessagePending = netiucv_callback_rx,
514 .MessageComplete = netiucv_callback_txdone
515};
516 587
517/** 588/**
518 * Dummy NOP action for all statemachines 589 * Dummy NOP action for all statemachines
519 */ 590 */
520static void 591static void fsm_action_nop(fsm_instance *fi, int event, void *arg)
521fsm_action_nop(fsm_instance *fi, int event, void *arg)
522{ 592{
523} 593}
524 594
525/** 595/*
526 * Actions of the connection statemachine 596 * Actions of the connection statemachine
527 *****************************************************************************/ 597 */
528 598
529/** 599/**
530 * Helper function for conn_action_rx() 600 * netiucv_unpack_skb
531 * Unpack a just received skb and hand it over to 601 * @conn: The connection where this skb has been received.
532 * upper layers. 602 * @pskb: The received skb.
533 * 603 *
534 * @param conn The connection where this skb has been received. 604 * Unpack a just received skb and hand it over to upper layers.
535 * @param pskb The received skb. 605 * Helper function for conn_action_rx.
536 */ 606 */
537//static __inline__ void 607static void netiucv_unpack_skb(struct iucv_connection *conn,
538static void 608 struct sk_buff *pskb)
539netiucv_unpack_skb(struct iucv_connection *conn, struct sk_buff *pskb)
540{ 609{
541 struct net_device *dev = conn->netdev; 610 struct net_device *dev = conn->netdev;
542 struct netiucv_priv *privptr = dev->priv; 611 struct netiucv_priv *privptr = netdev_priv(dev);
543 __u16 offset = 0; 612 u16 offset = 0;
544 613
545 skb_put(pskb, NETIUCV_HDRLEN); 614 skb_put(pskb, NETIUCV_HDRLEN);
546 pskb->dev = dev; 615 pskb->dev = dev;
@@ -549,7 +618,7 @@ netiucv_unpack_skb(struct iucv_connection *conn, struct sk_buff *pskb)
549 618
550 while (1) { 619 while (1) {
551 struct sk_buff *skb; 620 struct sk_buff *skb;
552 ll_header *header = (ll_header *)pskb->data; 621 struct ll_header *header = (struct ll_header *) pskb->data;
553 622
554 if (!header->next) 623 if (!header->next)
555 break; 624 break;
@@ -595,40 +664,37 @@ netiucv_unpack_skb(struct iucv_connection *conn, struct sk_buff *pskb)
595 } 664 }
596} 665}
597 666
598static void 667static void conn_action_rx(fsm_instance *fi, int event, void *arg)
599conn_action_rx(fsm_instance *fi, int event, void *arg)
600{ 668{
601 struct iucv_event *ev = (struct iucv_event *)arg; 669 struct iucv_event *ev = arg;
602 struct iucv_connection *conn = ev->conn; 670 struct iucv_connection *conn = ev->conn;
603 iucv_MessagePending *eib = (iucv_MessagePending *)ev->data; 671 struct iucv_message *msg = ev->data;
604 struct netiucv_priv *privptr =(struct netiucv_priv *)conn->netdev->priv; 672 struct netiucv_priv *privptr = netdev_priv(conn->netdev);
605
606 __u32 msglen = eib->ln1msg2.ipbfln1f;
607 int rc; 673 int rc;
608 674
609 IUCV_DBF_TEXT(trace, 4, __FUNCTION__); 675 IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
610 676
611 if (!conn->netdev) { 677 if (!conn->netdev) {
612 /* FRITZ: How to tell iucv LL to drop the msg? */ 678 iucv_message_reject(conn->path, msg);
613 PRINT_WARN("Received data for unlinked connection\n"); 679 PRINT_WARN("Received data for unlinked connection\n");
614 IUCV_DBF_TEXT(data, 2, 680 IUCV_DBF_TEXT(data, 2,
615 "Received data for unlinked connection\n"); 681 "Received data for unlinked connection\n");
616 return; 682 return;
617 } 683 }
618 if (msglen > conn->max_buffsize) { 684 if (msg->length > conn->max_buffsize) {
619 /* FRITZ: How to tell iucv LL to drop the msg? */ 685 iucv_message_reject(conn->path, msg);
620 privptr->stats.rx_dropped++; 686 privptr->stats.rx_dropped++;
621 PRINT_WARN("msglen %d > max_buffsize %d\n", 687 PRINT_WARN("msglen %d > max_buffsize %d\n",
622 msglen, conn->max_buffsize); 688 msg->length, conn->max_buffsize);
623 IUCV_DBF_TEXT_(data, 2, "msglen %d > max_buffsize %d\n", 689 IUCV_DBF_TEXT_(data, 2, "msglen %d > max_buffsize %d\n",
624 msglen, conn->max_buffsize); 690 msg->length, conn->max_buffsize);
625 return; 691 return;
626 } 692 }
627 conn->rx_buff->data = conn->rx_buff->tail = conn->rx_buff->head; 693 conn->rx_buff->data = conn->rx_buff->tail = conn->rx_buff->head;
628 conn->rx_buff->len = 0; 694 conn->rx_buff->len = 0;
629 rc = iucv_receive(conn->pathid, eib->ipmsgid, eib->iptrgcls, 695 rc = iucv_message_receive(conn->path, msg, 0, conn->rx_buff->data,
630 conn->rx_buff->data, msglen, NULL, NULL, NULL); 696 msg->length, NULL);
631 if (rc || msglen < 5) { 697 if (rc || msg->length < 5) {
632 privptr->stats.rx_errors++; 698 privptr->stats.rx_errors++;
633 PRINT_WARN("iucv_receive returned %08x\n", rc); 699 PRINT_WARN("iucv_receive returned %08x\n", rc);
634 IUCV_DBF_TEXT_(data, 2, "rc %d from iucv_receive\n", rc); 700 IUCV_DBF_TEXT_(data, 2, "rc %d from iucv_receive\n", rc);
@@ -637,26 +703,26 @@ conn_action_rx(fsm_instance *fi, int event, void *arg)
637 netiucv_unpack_skb(conn, conn->rx_buff); 703 netiucv_unpack_skb(conn, conn->rx_buff);
638} 704}
639 705
640static void 706static void conn_action_txdone(fsm_instance *fi, int event, void *arg)
641conn_action_txdone(fsm_instance *fi, int event, void *arg)
642{ 707{
643 struct iucv_event *ev = (struct iucv_event *)arg; 708 struct iucv_event *ev = arg;
644 struct iucv_connection *conn = ev->conn; 709 struct iucv_connection *conn = ev->conn;
645 iucv_MessageComplete *eib = (iucv_MessageComplete *)ev->data; 710 struct iucv_message *msg = ev->data;
711 struct iucv_message txmsg;
646 struct netiucv_priv *privptr = NULL; 712 struct netiucv_priv *privptr = NULL;
647 /* Shut up, gcc! skb is always below 2G. */ 713 u32 single_flag = msg->tag;
648 __u32 single_flag = eib->ipmsgtag; 714 u32 txbytes = 0;
649 __u32 txbytes = 0; 715 u32 txpackets = 0;
650 __u32 txpackets = 0; 716 u32 stat_maxcq = 0;
651 __u32 stat_maxcq = 0;
652 struct sk_buff *skb; 717 struct sk_buff *skb;
653 unsigned long saveflags; 718 unsigned long saveflags;
654 ll_header header; 719 struct ll_header header;
720 int rc;
655 721
656 IUCV_DBF_TEXT(trace, 4, __FUNCTION__); 722 IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
657 723
658 if (conn && conn->netdev && conn->netdev->priv) 724 if (conn && conn->netdev)
659 privptr = (struct netiucv_priv *)conn->netdev->priv; 725 privptr = netdev_priv(conn->netdev);
660 conn->prof.tx_pending--; 726 conn->prof.tx_pending--;
661 if (single_flag) { 727 if (single_flag) {
662 if ((skb = skb_dequeue(&conn->commit_queue))) { 728 if ((skb = skb_dequeue(&conn->commit_queue))) {
@@ -688,56 +754,55 @@ conn_action_txdone(fsm_instance *fi, int event, void *arg)
688 conn->prof.maxmulti = conn->collect_len; 754 conn->prof.maxmulti = conn->collect_len;
689 conn->collect_len = 0; 755 conn->collect_len = 0;
690 spin_unlock_irqrestore(&conn->collect_lock, saveflags); 756 spin_unlock_irqrestore(&conn->collect_lock, saveflags);
691 if (conn->tx_buff->len) { 757 if (conn->tx_buff->len == 0) {
692 int rc; 758 fsm_newstate(fi, CONN_STATE_IDLE);
693 759 return;
694 header.next = 0; 760 }
695 memcpy(skb_put(conn->tx_buff, NETIUCV_HDRLEN), &header,
696 NETIUCV_HDRLEN);
697 761
698 conn->prof.send_stamp = xtime; 762 header.next = 0;
699 rc = iucv_send(conn->pathid, NULL, 0, 0, 0, 0, 763 memcpy(skb_put(conn->tx_buff, NETIUCV_HDRLEN), &header, NETIUCV_HDRLEN);
764 conn->prof.send_stamp = xtime;
765 txmsg.class = 0;
766 txmsg.tag = 0;
767 rc = iucv_message_send(conn->path, &txmsg, 0, 0,
700 conn->tx_buff->data, conn->tx_buff->len); 768 conn->tx_buff->data, conn->tx_buff->len);
701 conn->prof.doios_multi++; 769 conn->prof.doios_multi++;
702 conn->prof.txlen += conn->tx_buff->len; 770 conn->prof.txlen += conn->tx_buff->len;
703 conn->prof.tx_pending++; 771 conn->prof.tx_pending++;
704 if (conn->prof.tx_pending > conn->prof.tx_max_pending) 772 if (conn->prof.tx_pending > conn->prof.tx_max_pending)
705 conn->prof.tx_max_pending = conn->prof.tx_pending; 773 conn->prof.tx_max_pending = conn->prof.tx_pending;
706 if (rc) { 774 if (rc) {
707 conn->prof.tx_pending--; 775 conn->prof.tx_pending--;
708 fsm_newstate(fi, CONN_STATE_IDLE);
709 if (privptr)
710 privptr->stats.tx_errors += txpackets;
711 PRINT_WARN("iucv_send returned %08x\n", rc);
712 IUCV_DBF_TEXT_(data, 2, "rc %d from iucv_send\n", rc);
713 } else {
714 if (privptr) {
715 privptr->stats.tx_packets += txpackets;
716 privptr->stats.tx_bytes += txbytes;
717 }
718 if (stat_maxcq > conn->prof.maxcqueue)
719 conn->prof.maxcqueue = stat_maxcq;
720 }
721 } else
722 fsm_newstate(fi, CONN_STATE_IDLE); 776 fsm_newstate(fi, CONN_STATE_IDLE);
777 if (privptr)
778 privptr->stats.tx_errors += txpackets;
779 PRINT_WARN("iucv_send returned %08x\n", rc);
780 IUCV_DBF_TEXT_(data, 2, "rc %d from iucv_send\n", rc);
781 } else {
782 if (privptr) {
783 privptr->stats.tx_packets += txpackets;
784 privptr->stats.tx_bytes += txbytes;
785 }
786 if (stat_maxcq > conn->prof.maxcqueue)
787 conn->prof.maxcqueue = stat_maxcq;
788 }
723} 789}
724 790
725static void 791static void conn_action_connaccept(fsm_instance *fi, int event, void *arg)
726conn_action_connaccept(fsm_instance *fi, int event, void *arg)
727{ 792{
728 struct iucv_event *ev = (struct iucv_event *)arg; 793 struct iucv_event *ev = arg;
729 struct iucv_connection *conn = ev->conn; 794 struct iucv_connection *conn = ev->conn;
730 iucv_ConnectionPending *eib = (iucv_ConnectionPending *)ev->data; 795 struct iucv_path *path = ev->data;
731 struct net_device *netdev = conn->netdev; 796 struct net_device *netdev = conn->netdev;
732 struct netiucv_priv *privptr = (struct netiucv_priv *)netdev->priv; 797 struct netiucv_priv *privptr = netdev_priv(netdev);
733 int rc; 798 int rc;
734 __u16 msglimit;
735 __u8 udata[16];
736 799
737 IUCV_DBF_TEXT(trace, 3, __FUNCTION__); 800 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
738 801
739 rc = iucv_accept(eib->ippathid, NETIUCV_QUEUELEN_DEFAULT, udata, 0, 802 conn->path = path;
740 conn->handle, conn, NULL, &msglimit); 803 path->msglim = NETIUCV_QUEUELEN_DEFAULT;
804 path->flags = 0;
805 rc = iucv_path_accept(path, &netiucv_handler, NULL, conn);
741 if (rc) { 806 if (rc) {
742 PRINT_WARN("%s: IUCV accept failed with error %d\n", 807 PRINT_WARN("%s: IUCV accept failed with error %d\n",
743 netdev->name, rc); 808 netdev->name, rc);
@@ -745,183 +810,126 @@ conn_action_connaccept(fsm_instance *fi, int event, void *arg)
745 return; 810 return;
746 } 811 }
747 fsm_newstate(fi, CONN_STATE_IDLE); 812 fsm_newstate(fi, CONN_STATE_IDLE);
748 conn->pathid = eib->ippathid; 813 netdev->tx_queue_len = conn->path->msglim;
749 netdev->tx_queue_len = msglimit;
750 fsm_event(privptr->fsm, DEV_EVENT_CONUP, netdev); 814 fsm_event(privptr->fsm, DEV_EVENT_CONUP, netdev);
751} 815}
752 816
753static void 817static void conn_action_connreject(fsm_instance *fi, int event, void *arg)
754conn_action_connreject(fsm_instance *fi, int event, void *arg)
755{ 818{
756 struct iucv_event *ev = (struct iucv_event *)arg; 819 struct iucv_event *ev = arg;
757 struct iucv_connection *conn = ev->conn; 820 struct iucv_path *path = ev->data;
758 struct net_device *netdev = conn->netdev;
759 iucv_ConnectionPending *eib = (iucv_ConnectionPending *)ev->data;
760 __u8 udata[16];
761 821
762 IUCV_DBF_TEXT(trace, 3, __FUNCTION__); 822 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
763 823 iucv_path_sever(path, NULL);
764 iucv_sever(eib->ippathid, udata);
765 if (eib->ippathid != conn->pathid) {
766 PRINT_INFO("%s: IR Connection Pending; "
767 "pathid %d does not match original pathid %d\n",
768 netdev->name, eib->ippathid, conn->pathid);
769 IUCV_DBF_TEXT_(data, 2,
770 "connreject: IR pathid %d, conn. pathid %d\n",
771 eib->ippathid, conn->pathid);
772 iucv_sever(conn->pathid, udata);
773 }
774} 824}
775 825
776static void 826static void conn_action_connack(fsm_instance *fi, int event, void *arg)
777conn_action_connack(fsm_instance *fi, int event, void *arg)
778{ 827{
779 struct iucv_event *ev = (struct iucv_event *)arg; 828 struct iucv_connection *conn = arg;
780 struct iucv_connection *conn = ev->conn;
781 iucv_ConnectionComplete *eib = (iucv_ConnectionComplete *)ev->data;
782 struct net_device *netdev = conn->netdev; 829 struct net_device *netdev = conn->netdev;
783 struct netiucv_priv *privptr = (struct netiucv_priv *)netdev->priv; 830 struct netiucv_priv *privptr = netdev_priv(netdev);
784 831
785 IUCV_DBF_TEXT(trace, 3, __FUNCTION__); 832 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
786
787 fsm_deltimer(&conn->timer); 833 fsm_deltimer(&conn->timer);
788 fsm_newstate(fi, CONN_STATE_IDLE); 834 fsm_newstate(fi, CONN_STATE_IDLE);
789 if (eib->ippathid != conn->pathid) { 835 netdev->tx_queue_len = conn->path->msglim;
790 PRINT_INFO("%s: IR Connection Complete; "
791 "pathid %d does not match original pathid %d\n",
792 netdev->name, eib->ippathid, conn->pathid);
793 IUCV_DBF_TEXT_(data, 2,
794 "connack: IR pathid %d, conn. pathid %d\n",
795 eib->ippathid, conn->pathid);
796 conn->pathid = eib->ippathid;
797 }
798 netdev->tx_queue_len = eib->ipmsglim;
799 fsm_event(privptr->fsm, DEV_EVENT_CONUP, netdev); 836 fsm_event(privptr->fsm, DEV_EVENT_CONUP, netdev);
800} 837}
801 838
802static void 839static void conn_action_conntimsev(fsm_instance *fi, int event, void *arg)
803conn_action_conntimsev(fsm_instance *fi, int event, void *arg)
804{ 840{
805 struct iucv_connection *conn = (struct iucv_connection *)arg; 841 struct iucv_connection *conn = arg;
806 __u8 udata[16];
807 842
808 IUCV_DBF_TEXT(trace, 3, __FUNCTION__); 843 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
809
810 fsm_deltimer(&conn->timer); 844 fsm_deltimer(&conn->timer);
811 iucv_sever(conn->pathid, udata); 845 iucv_path_sever(conn->path, NULL);
812 fsm_newstate(fi, CONN_STATE_STARTWAIT); 846 fsm_newstate(fi, CONN_STATE_STARTWAIT);
813} 847}
814 848
815static void 849static void conn_action_connsever(fsm_instance *fi, int event, void *arg)
816conn_action_connsever(fsm_instance *fi, int event, void *arg)
817{ 850{
818 struct iucv_event *ev = (struct iucv_event *)arg; 851 struct iucv_connection *conn = arg;
819 struct iucv_connection *conn = ev->conn;
820 struct net_device *netdev = conn->netdev; 852 struct net_device *netdev = conn->netdev;
821 struct netiucv_priv *privptr = (struct netiucv_priv *)netdev->priv; 853 struct netiucv_priv *privptr = netdev_priv(netdev);
822 __u8 udata[16];
823 854
824 IUCV_DBF_TEXT(trace, 3, __FUNCTION__); 855 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
825 856
826 fsm_deltimer(&conn->timer); 857 fsm_deltimer(&conn->timer);
827 iucv_sever(conn->pathid, udata); 858 iucv_path_sever(conn->path, NULL);
828 PRINT_INFO("%s: Remote dropped connection\n", netdev->name); 859 PRINT_INFO("%s: Remote dropped connection\n", netdev->name);
829 IUCV_DBF_TEXT(data, 2, 860 IUCV_DBF_TEXT(data, 2,
830 "conn_action_connsever: Remote dropped connection\n"); 861 "conn_action_connsever: Remote dropped connection\n");
831 fsm_newstate(fi, CONN_STATE_STARTWAIT); 862 fsm_newstate(fi, CONN_STATE_STARTWAIT);
832 fsm_event(privptr->fsm, DEV_EVENT_CONDOWN, netdev); 863 fsm_event(privptr->fsm, DEV_EVENT_CONDOWN, netdev);
833} 864}
834 865
835static void 866static void conn_action_start(fsm_instance *fi, int event, void *arg)
836conn_action_start(fsm_instance *fi, int event, void *arg)
837{ 867{
838 struct iucv_event *ev = (struct iucv_event *)arg; 868 struct iucv_connection *conn = arg;
839 struct iucv_connection *conn = ev->conn;
840 __u16 msglimit;
841 int rc; 869 int rc;
842 870
843 IUCV_DBF_TEXT(trace, 3, __FUNCTION__); 871 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
844 872
845 if (!conn->handle) { 873 fsm_newstate(fi, CONN_STATE_STARTWAIT);
846 IUCV_DBF_TEXT(trace, 5, "calling iucv_register_program\n");
847 conn->handle =
848 iucv_register_program(iucvMagic, conn->userid,
849 netiucv_mask,
850 &netiucv_ops, conn);
851 fsm_newstate(fi, CONN_STATE_STARTWAIT);
852 if (!conn->handle) {
853 fsm_newstate(fi, CONN_STATE_REGERR);
854 conn->handle = NULL;
855 IUCV_DBF_TEXT(setup, 2,
856 "NULL from iucv_register_program\n");
857 return;
858 }
859
860 PRINT_DEBUG("%s('%s'): registered successfully\n",
861 conn->netdev->name, conn->userid);
862 }
863
864 PRINT_DEBUG("%s('%s'): connecting ...\n", 874 PRINT_DEBUG("%s('%s'): connecting ...\n",
865 conn->netdev->name, conn->userid); 875 conn->netdev->name, conn->userid);
866 876
867 /* We must set the state before calling iucv_connect because the callback 877 /*
868 * handler could be called at any point after the connection request is 878 * We must set the state before calling iucv_connect because the
869 * sent */ 879 * callback handler could be called at any point after the connection
880 * request is sent
881 */
870 882
871 fsm_newstate(fi, CONN_STATE_SETUPWAIT); 883 fsm_newstate(fi, CONN_STATE_SETUPWAIT);
872 rc = iucv_connect(&(conn->pathid), NETIUCV_QUEUELEN_DEFAULT, iucvMagic, 884 conn->path = iucv_path_alloc(NETIUCV_QUEUELEN_DEFAULT, 0, GFP_KERNEL);
873 conn->userid, iucv_host, 0, NULL, &msglimit, 885 rc = iucv_path_connect(conn->path, &netiucv_handler, conn->userid,
874 conn->handle, conn); 886 NULL, iucvMagic, conn);
875 switch (rc) { 887 switch (rc) {
876 case 0: 888 case 0:
877 conn->netdev->tx_queue_len = msglimit; 889 conn->netdev->tx_queue_len = conn->path->msglim;
878 fsm_addtimer(&conn->timer, NETIUCV_TIMEOUT_5SEC, 890 fsm_addtimer(&conn->timer, NETIUCV_TIMEOUT_5SEC,
879 CONN_EVENT_TIMER, conn); 891 CONN_EVENT_TIMER, conn);
880 return; 892 return;
881 case 11: 893 case 11:
882 PRINT_INFO("%s: User %s is currently not available.\n", 894 PRINT_INFO("%s: User %s is currently not available.\n",
883 conn->netdev->name, 895 conn->netdev->name,
884 netiucv_printname(conn->userid)); 896 netiucv_printname(conn->userid));
885 fsm_newstate(fi, CONN_STATE_STARTWAIT); 897 fsm_newstate(fi, CONN_STATE_STARTWAIT);
886 return; 898 break;
887 case 12: 899 case 12:
888 PRINT_INFO("%s: User %s is currently not ready.\n", 900 PRINT_INFO("%s: User %s is currently not ready.\n",
889 conn->netdev->name, 901 conn->netdev->name,
890 netiucv_printname(conn->userid)); 902 netiucv_printname(conn->userid));
891 fsm_newstate(fi, CONN_STATE_STARTWAIT); 903 fsm_newstate(fi, CONN_STATE_STARTWAIT);
892 return; 904 break;
893 case 13: 905 case 13:
894 PRINT_WARN("%s: Too many IUCV connections.\n", 906 PRINT_WARN("%s: Too many IUCV connections.\n",
895 conn->netdev->name); 907 conn->netdev->name);
896 fsm_newstate(fi, CONN_STATE_CONNERR); 908 fsm_newstate(fi, CONN_STATE_CONNERR);
897 break; 909 break;
898 case 14: 910 case 14:
899 PRINT_WARN( 911 PRINT_WARN("%s: User %s has too many IUCV connections.\n",
900 "%s: User %s has too many IUCV connections.\n", 912 conn->netdev->name,
901 conn->netdev->name, 913 netiucv_printname(conn->userid));
902 netiucv_printname(conn->userid)); 914 fsm_newstate(fi, CONN_STATE_CONNERR);
903 fsm_newstate(fi, CONN_STATE_CONNERR); 915 break;
904 break; 916 case 15:
905 case 15: 917 PRINT_WARN("%s: No IUCV authorization in CP directory.\n",
906 PRINT_WARN( 918 conn->netdev->name);
907 "%s: No IUCV authorization in CP directory.\n", 919 fsm_newstate(fi, CONN_STATE_CONNERR);
908 conn->netdev->name); 920 break;
909 fsm_newstate(fi, CONN_STATE_CONNERR); 921 default:
910 break; 922 PRINT_WARN("%s: iucv_connect returned error %d\n",
911 default: 923 conn->netdev->name, rc);
912 PRINT_WARN("%s: iucv_connect returned error %d\n", 924 fsm_newstate(fi, CONN_STATE_CONNERR);
913 conn->netdev->name, rc); 925 break;
914 fsm_newstate(fi, CONN_STATE_CONNERR);
915 break;
916 } 926 }
917 IUCV_DBF_TEXT_(setup, 5, "iucv_connect rc is %d\n", rc); 927 IUCV_DBF_TEXT_(setup, 5, "iucv_connect rc is %d\n", rc);
918 IUCV_DBF_TEXT(trace, 5, "calling iucv_unregister_program\n"); 928 kfree(conn->path);
919 iucv_unregister_program(conn->handle); 929 conn->path = NULL;
920 conn->handle = NULL;
921} 930}
922 931
923static void 932static void netiucv_purge_skb_queue(struct sk_buff_head *q)
924netiucv_purge_skb_queue(struct sk_buff_head *q)
925{ 933{
926 struct sk_buff *skb; 934 struct sk_buff *skb;
927 935
@@ -931,36 +939,34 @@ netiucv_purge_skb_queue(struct sk_buff_head *q)
931 } 939 }
932} 940}
933 941
934static void 942static void conn_action_stop(fsm_instance *fi, int event, void *arg)
935conn_action_stop(fsm_instance *fi, int event, void *arg)
936{ 943{
937 struct iucv_event *ev = (struct iucv_event *)arg; 944 struct iucv_event *ev = arg;
938 struct iucv_connection *conn = ev->conn; 945 struct iucv_connection *conn = ev->conn;
939 struct net_device *netdev = conn->netdev; 946 struct net_device *netdev = conn->netdev;
940 struct netiucv_priv *privptr = (struct netiucv_priv *)netdev->priv; 947 struct netiucv_priv *privptr = netdev_priv(netdev);
941 948
942 IUCV_DBF_TEXT(trace, 3, __FUNCTION__); 949 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
943 950
944 fsm_deltimer(&conn->timer); 951 fsm_deltimer(&conn->timer);
945 fsm_newstate(fi, CONN_STATE_STOPPED); 952 fsm_newstate(fi, CONN_STATE_STOPPED);
946 netiucv_purge_skb_queue(&conn->collect_queue); 953 netiucv_purge_skb_queue(&conn->collect_queue);
947 if (conn->handle) 954 if (conn->path) {
948 IUCV_DBF_TEXT(trace, 5, "calling iucv_unregister_program\n"); 955 IUCV_DBF_TEXT(trace, 5, "calling iucv_path_sever\n");
949 iucv_unregister_program(conn->handle); 956 iucv_path_sever(conn->path, iucvMagic);
950 conn->handle = NULL; 957 kfree(conn->path);
958 conn->path = NULL;
959 }
951 netiucv_purge_skb_queue(&conn->commit_queue); 960 netiucv_purge_skb_queue(&conn->commit_queue);
952 fsm_event(privptr->fsm, DEV_EVENT_CONDOWN, netdev); 961 fsm_event(privptr->fsm, DEV_EVENT_CONDOWN, netdev);
953} 962}
954 963
955static void 964static void conn_action_inval(fsm_instance *fi, int event, void *arg)
956conn_action_inval(fsm_instance *fi, int event, void *arg)
957{ 965{
958 struct iucv_event *ev = (struct iucv_event *)arg; 966 struct iucv_connection *conn = arg;
959 struct iucv_connection *conn = ev->conn;
960 struct net_device *netdev = conn->netdev; 967 struct net_device *netdev = conn->netdev;
961 968
962 PRINT_WARN("%s: Cannot connect without username\n", 969 PRINT_WARN("%s: Cannot connect without username\n", netdev->name);
963 netdev->name);
964 IUCV_DBF_TEXT(data, 2, "conn_action_inval called\n"); 970 IUCV_DBF_TEXT(data, 2, "conn_action_inval called\n");
965} 971}
966 972
@@ -999,29 +1005,27 @@ static const fsm_node conn_fsm[] = {
999static const int CONN_FSM_LEN = sizeof(conn_fsm) / sizeof(fsm_node); 1005static const int CONN_FSM_LEN = sizeof(conn_fsm) / sizeof(fsm_node);
1000 1006
1001 1007
1002/** 1008/*
1003 * Actions for interface - statemachine. 1009 * Actions for interface - statemachine.
1004 *****************************************************************************/ 1010 */
1005 1011
1006/** 1012/**
1007 * Startup connection by sending CONN_EVENT_START to it. 1013 * dev_action_start
1014 * @fi: An instance of an interface statemachine.
1015 * @event: The event, just happened.
1016 * @arg: Generic pointer, casted from struct net_device * upon call.
1008 * 1017 *
1009 * @param fi An instance of an interface statemachine. 1018 * Startup connection by sending CONN_EVENT_START to it.
1010 * @param event The event, just happened.
1011 * @param arg Generic pointer, casted from struct net_device * upon call.
1012 */ 1019 */
1013static void 1020static void dev_action_start(fsm_instance *fi, int event, void *arg)
1014dev_action_start(fsm_instance *fi, int event, void *arg)
1015{ 1021{
1016 struct net_device *dev = (struct net_device *)arg; 1022 struct net_device *dev = arg;
1017 struct netiucv_priv *privptr = dev->priv; 1023 struct netiucv_priv *privptr = netdev_priv(dev);
1018 struct iucv_event ev;
1019 1024
1020 IUCV_DBF_TEXT(trace, 3, __FUNCTION__); 1025 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
1021 1026
1022 ev.conn = privptr->conn;
1023 fsm_newstate(fi, DEV_STATE_STARTWAIT); 1027 fsm_newstate(fi, DEV_STATE_STARTWAIT);
1024 fsm_event(privptr->conn->fsm, CONN_EVENT_START, &ev); 1028 fsm_event(privptr->conn->fsm, CONN_EVENT_START, privptr->conn);
1025} 1029}
1026 1030
1027/** 1031/**
@@ -1034,8 +1038,8 @@ dev_action_start(fsm_instance *fi, int event, void *arg)
1034static void 1038static void
1035dev_action_stop(fsm_instance *fi, int event, void *arg) 1039dev_action_stop(fsm_instance *fi, int event, void *arg)
1036{ 1040{
1037 struct net_device *dev = (struct net_device *)arg; 1041 struct net_device *dev = arg;
1038 struct netiucv_priv *privptr = dev->priv; 1042 struct netiucv_priv *privptr = netdev_priv(dev);
1039 struct iucv_event ev; 1043 struct iucv_event ev;
1040 1044
1041 IUCV_DBF_TEXT(trace, 3, __FUNCTION__); 1045 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
@@ -1057,8 +1061,8 @@ dev_action_stop(fsm_instance *fi, int event, void *arg)
1057static void 1061static void
1058dev_action_connup(fsm_instance *fi, int event, void *arg) 1062dev_action_connup(fsm_instance *fi, int event, void *arg)
1059{ 1063{
1060 struct net_device *dev = (struct net_device *)arg; 1064 struct net_device *dev = arg;
1061 struct netiucv_priv *privptr = dev->priv; 1065 struct netiucv_priv *privptr = netdev_priv(dev);
1062 1066
1063 IUCV_DBF_TEXT(trace, 3, __FUNCTION__); 1067 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
1064 1068
@@ -1131,11 +1135,13 @@ static const int DEV_FSM_LEN = sizeof(dev_fsm) / sizeof(fsm_node);
1131 * 1135 *
1132 * @return 0 on success, -ERRNO on failure. (Never fails.) 1136 * @return 0 on success, -ERRNO on failure. (Never fails.)
1133 */ 1137 */
1134static int 1138static int netiucv_transmit_skb(struct iucv_connection *conn,
1135netiucv_transmit_skb(struct iucv_connection *conn, struct sk_buff *skb) { 1139 struct sk_buff *skb)
1140{
1141 struct iucv_message msg;
1136 unsigned long saveflags; 1142 unsigned long saveflags;
1137 ll_header header; 1143 struct ll_header header;
1138 int rc = 0; 1144 int rc;
1139 1145
1140 if (fsm_getstate(conn->fsm) != CONN_STATE_IDLE) { 1146 if (fsm_getstate(conn->fsm) != CONN_STATE_IDLE) {
1141 int l = skb->len + NETIUCV_HDRLEN; 1147 int l = skb->len + NETIUCV_HDRLEN;
@@ -1145,11 +1151,12 @@ netiucv_transmit_skb(struct iucv_connection *conn, struct sk_buff *skb) {
1145 (conn->max_buffsize - NETIUCV_HDRLEN)) { 1151 (conn->max_buffsize - NETIUCV_HDRLEN)) {
1146 rc = -EBUSY; 1152 rc = -EBUSY;
1147 IUCV_DBF_TEXT(data, 2, 1153 IUCV_DBF_TEXT(data, 2,
1148 "EBUSY from netiucv_transmit_skb\n"); 1154 "EBUSY from netiucv_transmit_skb\n");
1149 } else { 1155 } else {
1150 atomic_inc(&skb->users); 1156 atomic_inc(&skb->users);
1151 skb_queue_tail(&conn->collect_queue, skb); 1157 skb_queue_tail(&conn->collect_queue, skb);
1152 conn->collect_len += l; 1158 conn->collect_len += l;
1159 rc = 0;
1153 } 1160 }
1154 spin_unlock_irqrestore(&conn->collect_lock, saveflags); 1161 spin_unlock_irqrestore(&conn->collect_lock, saveflags);
1155 } else { 1162 } else {
@@ -1188,9 +1195,10 @@ netiucv_transmit_skb(struct iucv_connection *conn, struct sk_buff *skb) {
1188 fsm_newstate(conn->fsm, CONN_STATE_TX); 1195 fsm_newstate(conn->fsm, CONN_STATE_TX);
1189 conn->prof.send_stamp = xtime; 1196 conn->prof.send_stamp = xtime;
1190 1197
1191 rc = iucv_send(conn->pathid, NULL, 0, 0, 1 /* single_flag */, 1198 msg.tag = 1;
1192 0, nskb->data, nskb->len); 1199 msg.class = 0;
1193 /* Shut up, gcc! nskb is always below 2G. */ 1200 rc = iucv_message_send(conn->path, &msg, 0, 0,
1201 nskb->data, nskb->len);
1194 conn->prof.doios_single++; 1202 conn->prof.doios_single++;
1195 conn->prof.txlen += skb->len; 1203 conn->prof.txlen += skb->len;
1196 conn->prof.tx_pending++; 1204 conn->prof.tx_pending++;
@@ -1200,7 +1208,7 @@ netiucv_transmit_skb(struct iucv_connection *conn, struct sk_buff *skb) {
1200 struct netiucv_priv *privptr; 1208 struct netiucv_priv *privptr;
1201 fsm_newstate(conn->fsm, CONN_STATE_IDLE); 1209 fsm_newstate(conn->fsm, CONN_STATE_IDLE);
1202 conn->prof.tx_pending--; 1210 conn->prof.tx_pending--;
1203 privptr = (struct netiucv_priv *)conn->netdev->priv; 1211 privptr = netdev_priv(conn->netdev);
1204 if (privptr) 1212 if (privptr)
1205 privptr->stats.tx_errors++; 1213 privptr->stats.tx_errors++;
1206 if (copied) 1214 if (copied)
@@ -1226,9 +1234,9 @@ netiucv_transmit_skb(struct iucv_connection *conn, struct sk_buff *skb) {
1226 return rc; 1234 return rc;
1227} 1235}
1228 1236
1229/** 1237/*
1230 * Interface API for upper network layers 1238 * Interface API for upper network layers
1231 *****************************************************************************/ 1239 */
1232 1240
1233/** 1241/**
1234 * Open an interface. 1242 * Open an interface.
@@ -1238,9 +1246,11 @@ netiucv_transmit_skb(struct iucv_connection *conn, struct sk_buff *skb) {
1238 * 1246 *
1239 * @return 0 on success, -ERRNO on failure. (Never fails.) 1247 * @return 0 on success, -ERRNO on failure. (Never fails.)
1240 */ 1248 */
1241static int 1249static int netiucv_open(struct net_device *dev)
1242netiucv_open(struct net_device *dev) { 1250{
1243 fsm_event(((struct netiucv_priv *)dev->priv)->fsm, DEV_EVENT_START,dev); 1251 struct netiucv_priv *priv = netdev_priv(dev);
1252
1253 fsm_event(priv->fsm, DEV_EVENT_START, dev);
1244 return 0; 1254 return 0;
1245} 1255}
1246 1256
@@ -1252,9 +1262,11 @@ netiucv_open(struct net_device *dev) {
1252 * 1262 *
1253 * @return 0 on success, -ERRNO on failure. (Never fails.) 1263 * @return 0 on success, -ERRNO on failure. (Never fails.)
1254 */ 1264 */
1255static int 1265static int netiucv_close(struct net_device *dev)
1256netiucv_close(struct net_device *dev) { 1266{
1257 fsm_event(((struct netiucv_priv *)dev->priv)->fsm, DEV_EVENT_STOP, dev); 1267 struct netiucv_priv *priv = netdev_priv(dev);
1268
1269 fsm_event(priv->fsm, DEV_EVENT_STOP, dev);
1258 return 0; 1270 return 0;
1259} 1271}
1260 1272
@@ -1271,8 +1283,8 @@ netiucv_close(struct net_device *dev) {
1271 */ 1283 */
1272static int netiucv_tx(struct sk_buff *skb, struct net_device *dev) 1284static int netiucv_tx(struct sk_buff *skb, struct net_device *dev)
1273{ 1285{
1274 int rc = 0; 1286 struct netiucv_priv *privptr = netdev_priv(dev);
1275 struct netiucv_priv *privptr = dev->priv; 1287 int rc;
1276 1288
1277 IUCV_DBF_TEXT(trace, 4, __FUNCTION__); 1289 IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
1278 /** 1290 /**
@@ -1312,40 +1324,41 @@ static int netiucv_tx(struct sk_buff *skb, struct net_device *dev)
1312 return -EBUSY; 1324 return -EBUSY;
1313 } 1325 }
1314 dev->trans_start = jiffies; 1326 dev->trans_start = jiffies;
1315 if (netiucv_transmit_skb(privptr->conn, skb)) 1327 rc = netiucv_transmit_skb(privptr->conn, skb) != 0;
1316 rc = 1;
1317 netiucv_clear_busy(dev); 1328 netiucv_clear_busy(dev);
1318 return rc; 1329 return rc;
1319} 1330}
1320 1331
1321/** 1332/**
1322 * Returns interface statistics of a device. 1333 * netiucv_stats
1334 * @dev: Pointer to interface struct.
1323 * 1335 *
1324 * @param dev Pointer to interface struct. 1336 * Returns interface statistics of a device.
1325 * 1337 *
1326 * @return Pointer to stats struct of this interface. 1338 * Returns pointer to stats struct of this interface.
1327 */ 1339 */
1328static struct net_device_stats * 1340static struct net_device_stats *netiucv_stats (struct net_device * dev)
1329netiucv_stats (struct net_device * dev)
1330{ 1341{
1342 struct netiucv_priv *priv = netdev_priv(dev);
1343
1331 IUCV_DBF_TEXT(trace, 5, __FUNCTION__); 1344 IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
1332 return &((struct netiucv_priv *)dev->priv)->stats; 1345 return &priv->stats;
1333} 1346}
1334 1347
1335/** 1348/**
1336 * Sets MTU of an interface. 1349 * netiucv_change_mtu
1350 * @dev: Pointer to interface struct.
1351 * @new_mtu: The new MTU to use for this interface.
1337 * 1352 *
1338 * @param dev Pointer to interface struct. 1353 * Sets MTU of an interface.
1339 * @param new_mtu The new MTU to use for this interface.
1340 * 1354 *
1341 * @return 0 on success, -EINVAL if MTU is out of valid range. 1355 * Returns 0 on success, -EINVAL if MTU is out of valid range.
1342 * (valid range is 576 .. NETIUCV_MTU_MAX). 1356 * (valid range is 576 .. NETIUCV_MTU_MAX).
1343 */ 1357 */
1344static int 1358static int netiucv_change_mtu(struct net_device * dev, int new_mtu)
1345netiucv_change_mtu (struct net_device * dev, int new_mtu)
1346{ 1359{
1347 IUCV_DBF_TEXT(trace, 3, __FUNCTION__); 1360 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
1348 if ((new_mtu < 576) || (new_mtu > NETIUCV_MTU_MAX)) { 1361 if (new_mtu < 576 || new_mtu > NETIUCV_MTU_MAX) {
1349 IUCV_DBF_TEXT(setup, 2, "given MTU out of valid range\n"); 1362 IUCV_DBF_TEXT(setup, 2, "given MTU out of valid range\n");
1350 return -EINVAL; 1363 return -EINVAL;
1351 } 1364 }
@@ -1353,12 +1366,12 @@ netiucv_change_mtu (struct net_device * dev, int new_mtu)
1353 return 0; 1366 return 0;
1354} 1367}
1355 1368
1356/** 1369/*
1357 * attributes in sysfs 1370 * attributes in sysfs
1358 *****************************************************************************/ 1371 */
1359 1372
1360static ssize_t 1373static ssize_t user_show(struct device *dev, struct device_attribute *attr,
1361user_show (struct device *dev, struct device_attribute *attr, char *buf) 1374 char *buf)
1362{ 1375{
1363 struct netiucv_priv *priv = dev->driver_data; 1376 struct netiucv_priv *priv = dev->driver_data;
1364 1377
@@ -1366,8 +1379,8 @@ user_show (struct device *dev, struct device_attribute *attr, char *buf)
1366 return sprintf(buf, "%s\n", netiucv_printname(priv->conn->userid)); 1379 return sprintf(buf, "%s\n", netiucv_printname(priv->conn->userid));
1367} 1380}
1368 1381
1369static ssize_t 1382static ssize_t user_write(struct device *dev, struct device_attribute *attr,
1370user_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) 1383 const char *buf, size_t count)
1371{ 1384{
1372 struct netiucv_priv *priv = dev->driver_data; 1385 struct netiucv_priv *priv = dev->driver_data;
1373 struct net_device *ndev = priv->conn->netdev; 1386 struct net_device *ndev = priv->conn->netdev;
@@ -1375,80 +1388,70 @@ user_write (struct device *dev, struct device_attribute *attr, const char *buf,
1375 char *tmp; 1388 char *tmp;
1376 char username[9]; 1389 char username[9];
1377 int i; 1390 int i;
1378 struct iucv_connection **clist = &iucv_conns.iucv_connections; 1391 struct iucv_connection *cp;
1379 unsigned long flags;
1380 1392
1381 IUCV_DBF_TEXT(trace, 3, __FUNCTION__); 1393 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
1382 if (count>9) { 1394 if (count > 9) {
1383 PRINT_WARN("netiucv: username too long (%d)!\n", (int)count); 1395 PRINT_WARN("netiucv: username too long (%d)!\n", (int) count);
1384 IUCV_DBF_TEXT_(setup, 2, 1396 IUCV_DBF_TEXT_(setup, 2,
1385 "%d is length of username\n", (int)count); 1397 "%d is length of username\n", (int) count);
1386 return -EINVAL; 1398 return -EINVAL;
1387 } 1399 }
1388 1400
1389 tmp = strsep((char **) &buf, "\n"); 1401 tmp = strsep((char **) &buf, "\n");
1390 for (i=0, p=tmp; i<8 && *p; i++, p++) { 1402 for (i = 0, p = tmp; i < 8 && *p; i++, p++) {
1391 if (isalnum(*p) || (*p == '$')) 1403 if (isalnum(*p) || (*p == '$')) {
1392 username[i]= toupper(*p); 1404 username[i]= toupper(*p);
1393 else if (*p == '\n') { 1405 continue;
1406 }
1407 if (*p == '\n') {
1394 /* trailing lf, grr */ 1408 /* trailing lf, grr */
1395 break; 1409 break;
1396 } else {
1397 PRINT_WARN("netiucv: Invalid char %c in username!\n",
1398 *p);
1399 IUCV_DBF_TEXT_(setup, 2,
1400 "username: invalid character %c\n",
1401 *p);
1402 return -EINVAL;
1403 } 1410 }
1411 PRINT_WARN("netiucv: Invalid char %c in username!\n", *p);
1412 IUCV_DBF_TEXT_(setup, 2,
1413 "username: invalid character %c\n", *p);
1414 return -EINVAL;
1404 } 1415 }
1405 while (i<8) 1416 while (i < 8)
1406 username[i++] = ' '; 1417 username[i++] = ' ';
1407 username[8] = '\0'; 1418 username[8] = '\0';
1408 1419
1409 if (memcmp(username, priv->conn->userid, 9)) { 1420 if (memcmp(username, priv->conn->userid, 9) &&
1410 /* username changed */ 1421 (ndev->flags & (IFF_UP | IFF_RUNNING))) {
1411 if (ndev->flags & (IFF_UP | IFF_RUNNING)) { 1422 /* username changed while the interface is active. */
1412 PRINT_WARN( 1423 PRINT_WARN("netiucv: device %s active, connected to %s\n",
1413 "netiucv: device %s active, connected to %s\n", 1424 dev->bus_id, priv->conn->userid);
1414 dev->bus_id, priv->conn->userid); 1425 PRINT_WARN("netiucv: user cannot be updated\n");
1415 PRINT_WARN("netiucv: user cannot be updated\n"); 1426 IUCV_DBF_TEXT(setup, 2, "user_write: device active\n");
1416 IUCV_DBF_TEXT(setup, 2, "user_write: device active\n"); 1427 return -EBUSY;
1417 return -EBUSY; 1428 }
1429 read_lock_bh(&iucv_connection_rwlock);
1430 list_for_each_entry(cp, &iucv_connection_list, list) {
1431 if (!strncmp(username, cp->userid, 9) && cp->netdev != ndev) {
1432 read_unlock_bh(&iucv_connection_rwlock);
1433 PRINT_WARN("netiucv: Connection to %s already "
1434 "exists\n", username);
1435 return -EEXIST;
1418 } 1436 }
1419 } 1437 }
1420 read_lock_irqsave(&iucv_conns.iucv_rwlock, flags); 1438 read_unlock_bh(&iucv_connection_rwlock);
1421 while (*clist) {
1422 if (!strncmp(username, (*clist)->userid, 9) ||
1423 ((*clist)->netdev != ndev))
1424 break;
1425 clist = &((*clist)->next);
1426 }
1427 read_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags);
1428 if (*clist) {
1429 PRINT_WARN("netiucv: Connection to %s already exists\n",
1430 username);
1431 return -EEXIST;
1432 }
1433 memcpy(priv->conn->userid, username, 9); 1439 memcpy(priv->conn->userid, username, 9);
1434
1435 return count; 1440 return count;
1436
1437} 1441}
1438 1442
1439static DEVICE_ATTR(user, 0644, user_show, user_write); 1443static DEVICE_ATTR(user, 0644, user_show, user_write);
1440 1444
1441static ssize_t 1445static ssize_t buffer_show (struct device *dev, struct device_attribute *attr,
1442buffer_show (struct device *dev, struct device_attribute *attr, char *buf) 1446 char *buf)
1443{ 1447{ struct netiucv_priv *priv = dev->driver_data;
1444 struct netiucv_priv *priv = dev->driver_data;
1445 1448
1446 IUCV_DBF_TEXT(trace, 5, __FUNCTION__); 1449 IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
1447 return sprintf(buf, "%d\n", priv->conn->max_buffsize); 1450 return sprintf(buf, "%d\n", priv->conn->max_buffsize);
1448} 1451}
1449 1452
1450static ssize_t 1453static ssize_t buffer_write (struct device *dev, struct device_attribute *attr,
1451buffer_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) 1454 const char *buf, size_t count)
1452{ 1455{
1453 struct netiucv_priv *priv = dev->driver_data; 1456 struct netiucv_priv *priv = dev->driver_data;
1454 struct net_device *ndev = priv->conn->netdev; 1457 struct net_device *ndev = priv->conn->netdev;
@@ -1502,8 +1505,8 @@ buffer_write (struct device *dev, struct device_attribute *attr, const char *buf
1502 1505
1503static DEVICE_ATTR(buffer, 0644, buffer_show, buffer_write); 1506static DEVICE_ATTR(buffer, 0644, buffer_show, buffer_write);
1504 1507
1505static ssize_t 1508static ssize_t dev_fsm_show (struct device *dev, struct device_attribute *attr,
1506dev_fsm_show (struct device *dev, struct device_attribute *attr, char *buf) 1509 char *buf)
1507{ 1510{
1508 struct netiucv_priv *priv = dev->driver_data; 1511 struct netiucv_priv *priv = dev->driver_data;
1509 1512
@@ -1513,8 +1516,8 @@ dev_fsm_show (struct device *dev, struct device_attribute *attr, char *buf)
1513 1516
1514static DEVICE_ATTR(device_fsm_state, 0444, dev_fsm_show, NULL); 1517static DEVICE_ATTR(device_fsm_state, 0444, dev_fsm_show, NULL);
1515 1518
1516static ssize_t 1519static ssize_t conn_fsm_show (struct device *dev,
1517conn_fsm_show (struct device *dev, struct device_attribute *attr, char *buf) 1520 struct device_attribute *attr, char *buf)
1518{ 1521{
1519 struct netiucv_priv *priv = dev->driver_data; 1522 struct netiucv_priv *priv = dev->driver_data;
1520 1523
@@ -1524,8 +1527,8 @@ conn_fsm_show (struct device *dev, struct device_attribute *attr, char *buf)
1524 1527
1525static DEVICE_ATTR(connection_fsm_state, 0444, conn_fsm_show, NULL); 1528static DEVICE_ATTR(connection_fsm_state, 0444, conn_fsm_show, NULL);
1526 1529
1527static ssize_t 1530static ssize_t maxmulti_show (struct device *dev,
1528maxmulti_show (struct device *dev, struct device_attribute *attr, char *buf) 1531 struct device_attribute *attr, char *buf)
1529{ 1532{
1530 struct netiucv_priv *priv = dev->driver_data; 1533 struct netiucv_priv *priv = dev->driver_data;
1531 1534
@@ -1533,8 +1536,9 @@ maxmulti_show (struct device *dev, struct device_attribute *attr, char *buf)
1533 return sprintf(buf, "%ld\n", priv->conn->prof.maxmulti); 1536 return sprintf(buf, "%ld\n", priv->conn->prof.maxmulti);
1534} 1537}
1535 1538
1536static ssize_t 1539static ssize_t maxmulti_write (struct device *dev,
1537maxmulti_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) 1540 struct device_attribute *attr,
1541 const char *buf, size_t count)
1538{ 1542{
1539 struct netiucv_priv *priv = dev->driver_data; 1543 struct netiucv_priv *priv = dev->driver_data;
1540 1544
@@ -1545,8 +1549,8 @@ maxmulti_write (struct device *dev, struct device_attribute *attr, const char *b
1545 1549
1546static DEVICE_ATTR(max_tx_buffer_used, 0644, maxmulti_show, maxmulti_write); 1550static DEVICE_ATTR(max_tx_buffer_used, 0644, maxmulti_show, maxmulti_write);
1547 1551
1548static ssize_t 1552static ssize_t maxcq_show (struct device *dev, struct device_attribute *attr,
1549maxcq_show (struct device *dev, struct device_attribute *attr, char *buf) 1553 char *buf)
1550{ 1554{
1551 struct netiucv_priv *priv = dev->driver_data; 1555 struct netiucv_priv *priv = dev->driver_data;
1552 1556
@@ -1554,8 +1558,8 @@ maxcq_show (struct device *dev, struct device_attribute *attr, char *buf)
1554 return sprintf(buf, "%ld\n", priv->conn->prof.maxcqueue); 1558 return sprintf(buf, "%ld\n", priv->conn->prof.maxcqueue);
1555} 1559}
1556 1560
1557static ssize_t 1561static ssize_t maxcq_write (struct device *dev, struct device_attribute *attr,
1558maxcq_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) 1562 const char *buf, size_t count)
1559{ 1563{
1560 struct netiucv_priv *priv = dev->driver_data; 1564 struct netiucv_priv *priv = dev->driver_data;
1561 1565
@@ -1566,8 +1570,8 @@ maxcq_write (struct device *dev, struct device_attribute *attr, const char *buf,
1566 1570
1567static DEVICE_ATTR(max_chained_skbs, 0644, maxcq_show, maxcq_write); 1571static DEVICE_ATTR(max_chained_skbs, 0644, maxcq_show, maxcq_write);
1568 1572
1569static ssize_t 1573static ssize_t sdoio_show (struct device *dev, struct device_attribute *attr,
1570sdoio_show (struct device *dev, struct device_attribute *attr, char *buf) 1574 char *buf)
1571{ 1575{
1572 struct netiucv_priv *priv = dev->driver_data; 1576 struct netiucv_priv *priv = dev->driver_data;
1573 1577
@@ -1575,8 +1579,8 @@ sdoio_show (struct device *dev, struct device_attribute *attr, char *buf)
1575 return sprintf(buf, "%ld\n", priv->conn->prof.doios_single); 1579 return sprintf(buf, "%ld\n", priv->conn->prof.doios_single);
1576} 1580}
1577 1581
1578static ssize_t 1582static ssize_t sdoio_write (struct device *dev, struct device_attribute *attr,
1579sdoio_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) 1583 const char *buf, size_t count)
1580{ 1584{
1581 struct netiucv_priv *priv = dev->driver_data; 1585 struct netiucv_priv *priv = dev->driver_data;
1582 1586
@@ -1587,8 +1591,8 @@ sdoio_write (struct device *dev, struct device_attribute *attr, const char *buf,
1587 1591
1588static DEVICE_ATTR(tx_single_write_ops, 0644, sdoio_show, sdoio_write); 1592static DEVICE_ATTR(tx_single_write_ops, 0644, sdoio_show, sdoio_write);
1589 1593
1590static ssize_t 1594static ssize_t mdoio_show (struct device *dev, struct device_attribute *attr,
1591mdoio_show (struct device *dev, struct device_attribute *attr, char *buf) 1595 char *buf)
1592{ 1596{
1593 struct netiucv_priv *priv = dev->driver_data; 1597 struct netiucv_priv *priv = dev->driver_data;
1594 1598
@@ -1596,8 +1600,8 @@ mdoio_show (struct device *dev, struct device_attribute *attr, char *buf)
1596 return sprintf(buf, "%ld\n", priv->conn->prof.doios_multi); 1600 return sprintf(buf, "%ld\n", priv->conn->prof.doios_multi);
1597} 1601}
1598 1602
1599static ssize_t 1603static ssize_t mdoio_write (struct device *dev, struct device_attribute *attr,
1600mdoio_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) 1604 const char *buf, size_t count)
1601{ 1605{
1602 struct netiucv_priv *priv = dev->driver_data; 1606 struct netiucv_priv *priv = dev->driver_data;
1603 1607
@@ -1608,8 +1612,8 @@ mdoio_write (struct device *dev, struct device_attribute *attr, const char *buf,
1608 1612
1609static DEVICE_ATTR(tx_multi_write_ops, 0644, mdoio_show, mdoio_write); 1613static DEVICE_ATTR(tx_multi_write_ops, 0644, mdoio_show, mdoio_write);
1610 1614
1611static ssize_t 1615static ssize_t txlen_show (struct device *dev, struct device_attribute *attr,
1612txlen_show (struct device *dev, struct device_attribute *attr, char *buf) 1616 char *buf)
1613{ 1617{
1614 struct netiucv_priv *priv = dev->driver_data; 1618 struct netiucv_priv *priv = dev->driver_data;
1615 1619
@@ -1617,8 +1621,8 @@ txlen_show (struct device *dev, struct device_attribute *attr, char *buf)
1617 return sprintf(buf, "%ld\n", priv->conn->prof.txlen); 1621 return sprintf(buf, "%ld\n", priv->conn->prof.txlen);
1618} 1622}
1619 1623
1620static ssize_t 1624static ssize_t txlen_write (struct device *dev, struct device_attribute *attr,
1621txlen_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) 1625 const char *buf, size_t count)
1622{ 1626{
1623 struct netiucv_priv *priv = dev->driver_data; 1627 struct netiucv_priv *priv = dev->driver_data;
1624 1628
@@ -1629,8 +1633,8 @@ txlen_write (struct device *dev, struct device_attribute *attr, const char *buf,
1629 1633
1630static DEVICE_ATTR(netto_bytes, 0644, txlen_show, txlen_write); 1634static DEVICE_ATTR(netto_bytes, 0644, txlen_show, txlen_write);
1631 1635
1632static ssize_t 1636static ssize_t txtime_show (struct device *dev, struct device_attribute *attr,
1633txtime_show (struct device *dev, struct device_attribute *attr, char *buf) 1637 char *buf)
1634{ 1638{
1635 struct netiucv_priv *priv = dev->driver_data; 1639 struct netiucv_priv *priv = dev->driver_data;
1636 1640
@@ -1638,8 +1642,8 @@ txtime_show (struct device *dev, struct device_attribute *attr, char *buf)
1638 return sprintf(buf, "%ld\n", priv->conn->prof.tx_time); 1642 return sprintf(buf, "%ld\n", priv->conn->prof.tx_time);
1639} 1643}
1640 1644
1641static ssize_t 1645static ssize_t txtime_write (struct device *dev, struct device_attribute *attr,
1642txtime_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) 1646 const char *buf, size_t count)
1643{ 1647{
1644 struct netiucv_priv *priv = dev->driver_data; 1648 struct netiucv_priv *priv = dev->driver_data;
1645 1649
@@ -1650,8 +1654,8 @@ txtime_write (struct device *dev, struct device_attribute *attr, const char *buf
1650 1654
1651static DEVICE_ATTR(max_tx_io_time, 0644, txtime_show, txtime_write); 1655static DEVICE_ATTR(max_tx_io_time, 0644, txtime_show, txtime_write);
1652 1656
1653static ssize_t 1657static ssize_t txpend_show (struct device *dev, struct device_attribute *attr,
1654txpend_show (struct device *dev, struct device_attribute *attr, char *buf) 1658 char *buf)
1655{ 1659{
1656 struct netiucv_priv *priv = dev->driver_data; 1660 struct netiucv_priv *priv = dev->driver_data;
1657 1661
@@ -1659,8 +1663,8 @@ txpend_show (struct device *dev, struct device_attribute *attr, char *buf)
1659 return sprintf(buf, "%ld\n", priv->conn->prof.tx_pending); 1663 return sprintf(buf, "%ld\n", priv->conn->prof.tx_pending);
1660} 1664}
1661 1665
1662static ssize_t 1666static ssize_t txpend_write (struct device *dev, struct device_attribute *attr,
1663txpend_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) 1667 const char *buf, size_t count)
1664{ 1668{
1665 struct netiucv_priv *priv = dev->driver_data; 1669 struct netiucv_priv *priv = dev->driver_data;
1666 1670
@@ -1671,8 +1675,8 @@ txpend_write (struct device *dev, struct device_attribute *attr, const char *buf
1671 1675
1672static DEVICE_ATTR(tx_pending, 0644, txpend_show, txpend_write); 1676static DEVICE_ATTR(tx_pending, 0644, txpend_show, txpend_write);
1673 1677
1674static ssize_t 1678static ssize_t txmpnd_show (struct device *dev, struct device_attribute *attr,
1675txmpnd_show (struct device *dev, struct device_attribute *attr, char *buf) 1679 char *buf)
1676{ 1680{
1677 struct netiucv_priv *priv = dev->driver_data; 1681 struct netiucv_priv *priv = dev->driver_data;
1678 1682
@@ -1680,8 +1684,8 @@ txmpnd_show (struct device *dev, struct device_attribute *attr, char *buf)
1680 return sprintf(buf, "%ld\n", priv->conn->prof.tx_max_pending); 1684 return sprintf(buf, "%ld\n", priv->conn->prof.tx_max_pending);
1681} 1685}
1682 1686
1683static ssize_t 1687static ssize_t txmpnd_write (struct device *dev, struct device_attribute *attr,
1684txmpnd_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) 1688 const char *buf, size_t count)
1685{ 1689{
1686 struct netiucv_priv *priv = dev->driver_data; 1690 struct netiucv_priv *priv = dev->driver_data;
1687 1691
@@ -1721,8 +1725,7 @@ static struct attribute_group netiucv_stat_attr_group = {
1721 .attrs = netiucv_stat_attrs, 1725 .attrs = netiucv_stat_attrs,
1722}; 1726};
1723 1727
1724static inline int 1728static inline int netiucv_add_files(struct device *dev)
1725netiucv_add_files(struct device *dev)
1726{ 1729{
1727 int ret; 1730 int ret;
1728 1731
@@ -1736,18 +1739,16 @@ netiucv_add_files(struct device *dev)
1736 return ret; 1739 return ret;
1737} 1740}
1738 1741
1739static inline void 1742static inline void netiucv_remove_files(struct device *dev)
1740netiucv_remove_files(struct device *dev)
1741{ 1743{
1742 IUCV_DBF_TEXT(trace, 3, __FUNCTION__); 1744 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
1743 sysfs_remove_group(&dev->kobj, &netiucv_stat_attr_group); 1745 sysfs_remove_group(&dev->kobj, &netiucv_stat_attr_group);
1744 sysfs_remove_group(&dev->kobj, &netiucv_attr_group); 1746 sysfs_remove_group(&dev->kobj, &netiucv_attr_group);
1745} 1747}
1746 1748
1747static int 1749static int netiucv_register_device(struct net_device *ndev)
1748netiucv_register_device(struct net_device *ndev)
1749{ 1750{
1750 struct netiucv_priv *priv = ndev->priv; 1751 struct netiucv_priv *priv = netdev_priv(ndev);
1751 struct device *dev = kzalloc(sizeof(struct device), GFP_KERNEL); 1752 struct device *dev = kzalloc(sizeof(struct device), GFP_KERNEL);
1752 int ret; 1753 int ret;
1753 1754
@@ -1786,8 +1787,7 @@ out_unreg:
1786 return ret; 1787 return ret;
1787} 1788}
1788 1789
1789static void 1790static void netiucv_unregister_device(struct device *dev)
1790netiucv_unregister_device(struct device *dev)
1791{ 1791{
1792 IUCV_DBF_TEXT(trace, 3, __FUNCTION__); 1792 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
1793 netiucv_remove_files(dev); 1793 netiucv_remove_files(dev);
@@ -1798,107 +1798,89 @@ netiucv_unregister_device(struct device *dev)
1798 * Allocate and initialize a new connection structure. 1798 * Allocate and initialize a new connection structure.
1799 * Add it to the list of netiucv connections; 1799 * Add it to the list of netiucv connections;
1800 */ 1800 */
1801static struct iucv_connection * 1801static struct iucv_connection *netiucv_new_connection(struct net_device *dev,
1802netiucv_new_connection(struct net_device *dev, char *username) 1802 char *username)
1803{ 1803{
1804 unsigned long flags; 1804 struct iucv_connection *conn;
1805 struct iucv_connection **clist = &iucv_conns.iucv_connections;
1806 struct iucv_connection *conn =
1807 kzalloc(sizeof(struct iucv_connection), GFP_KERNEL);
1808
1809 if (conn) {
1810 skb_queue_head_init(&conn->collect_queue);
1811 skb_queue_head_init(&conn->commit_queue);
1812 spin_lock_init(&conn->collect_lock);
1813 conn->max_buffsize = NETIUCV_BUFSIZE_DEFAULT;
1814 conn->netdev = dev;
1815
1816 conn->rx_buff = alloc_skb(NETIUCV_BUFSIZE_DEFAULT,
1817 GFP_KERNEL | GFP_DMA);
1818 if (!conn->rx_buff) {
1819 kfree(conn);
1820 return NULL;
1821 }
1822 conn->tx_buff = alloc_skb(NETIUCV_BUFSIZE_DEFAULT,
1823 GFP_KERNEL | GFP_DMA);
1824 if (!conn->tx_buff) {
1825 kfree_skb(conn->rx_buff);
1826 kfree(conn);
1827 return NULL;
1828 }
1829 conn->fsm = init_fsm("netiucvconn", conn_state_names,
1830 conn_event_names, NR_CONN_STATES,
1831 NR_CONN_EVENTS, conn_fsm, CONN_FSM_LEN,
1832 GFP_KERNEL);
1833 if (!conn->fsm) {
1834 kfree_skb(conn->tx_buff);
1835 kfree_skb(conn->rx_buff);
1836 kfree(conn);
1837 return NULL;
1838 }
1839 fsm_settimer(conn->fsm, &conn->timer);
1840 fsm_newstate(conn->fsm, CONN_STATE_INVALID);
1841
1842 if (username) {
1843 memcpy(conn->userid, username, 9);
1844 fsm_newstate(conn->fsm, CONN_STATE_STOPPED);
1845 }
1846 1805
1847 write_lock_irqsave(&iucv_conns.iucv_rwlock, flags); 1806 conn = kzalloc(sizeof(*conn), GFP_KERNEL);
1848 conn->next = *clist; 1807 if (!conn)
1849 *clist = conn; 1808 goto out;
1850 write_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags); 1809 skb_queue_head_init(&conn->collect_queue);
1810 skb_queue_head_init(&conn->commit_queue);
1811 spin_lock_init(&conn->collect_lock);
1812 conn->max_buffsize = NETIUCV_BUFSIZE_DEFAULT;
1813 conn->netdev = dev;
1814
1815 conn->rx_buff = alloc_skb(conn->max_buffsize, GFP_KERNEL | GFP_DMA);
1816 if (!conn->rx_buff)
1817 goto out_conn;
1818 conn->tx_buff = alloc_skb(conn->max_buffsize, GFP_KERNEL | GFP_DMA);
1819 if (!conn->tx_buff)
1820 goto out_rx;
1821 conn->fsm = init_fsm("netiucvconn", conn_state_names,
1822 conn_event_names, NR_CONN_STATES,
1823 NR_CONN_EVENTS, conn_fsm, CONN_FSM_LEN,
1824 GFP_KERNEL);
1825 if (!conn->fsm)
1826 goto out_tx;
1827
1828 fsm_settimer(conn->fsm, &conn->timer);
1829 fsm_newstate(conn->fsm, CONN_STATE_INVALID);
1830
1831 if (username) {
1832 memcpy(conn->userid, username, 9);
1833 fsm_newstate(conn->fsm, CONN_STATE_STOPPED);
1851 } 1834 }
1835
1836 write_lock_bh(&iucv_connection_rwlock);
1837 list_add_tail(&conn->list, &iucv_connection_list);
1838 write_unlock_bh(&iucv_connection_rwlock);
1852 return conn; 1839 return conn;
1840
1841out_tx:
1842 kfree_skb(conn->tx_buff);
1843out_rx:
1844 kfree_skb(conn->rx_buff);
1845out_conn:
1846 kfree(conn);
1847out:
1848 return NULL;
1853} 1849}
1854 1850
1855/** 1851/**
1856 * Release a connection structure and remove it from the 1852 * Release a connection structure and remove it from the
1857 * list of netiucv connections. 1853 * list of netiucv connections.
1858 */ 1854 */
1859static void 1855static void netiucv_remove_connection(struct iucv_connection *conn)
1860netiucv_remove_connection(struct iucv_connection *conn)
1861{ 1856{
1862 struct iucv_connection **clist = &iucv_conns.iucv_connections;
1863 unsigned long flags;
1864
1865 IUCV_DBF_TEXT(trace, 3, __FUNCTION__); 1857 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
1866 if (conn == NULL) 1858 write_lock_bh(&iucv_connection_rwlock);
1867 return; 1859 list_del_init(&conn->list);
1868 write_lock_irqsave(&iucv_conns.iucv_rwlock, flags); 1860 write_unlock_bh(&iucv_connection_rwlock);
1869 while (*clist) { 1861 if (conn->path) {
1870 if (*clist == conn) { 1862 iucv_path_sever(conn->path, iucvMagic);
1871 *clist = conn->next; 1863 kfree(conn->path);
1872 write_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags); 1864 conn->path = NULL;
1873 if (conn->handle) {
1874 iucv_unregister_program(conn->handle);
1875 conn->handle = NULL;
1876 }
1877 fsm_deltimer(&conn->timer);
1878 kfree_fsm(conn->fsm);
1879 kfree_skb(conn->rx_buff);
1880 kfree_skb(conn->tx_buff);
1881 return;
1882 }
1883 clist = &((*clist)->next);
1884 } 1865 }
1885 write_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags); 1866 fsm_deltimer(&conn->timer);
1867 kfree_fsm(conn->fsm);
1868 kfree_skb(conn->rx_buff);
1869 kfree_skb(conn->tx_buff);
1886} 1870}
1887 1871
1888/** 1872/**
1889 * Release everything of a net device. 1873 * Release everything of a net device.
1890 */ 1874 */
1891static void 1875static void netiucv_free_netdevice(struct net_device *dev)
1892netiucv_free_netdevice(struct net_device *dev)
1893{ 1876{
1894 struct netiucv_priv *privptr; 1877 struct netiucv_priv *privptr = netdev_priv(dev);
1895 1878
1896 IUCV_DBF_TEXT(trace, 3, __FUNCTION__); 1879 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
1897 1880
1898 if (!dev) 1881 if (!dev)
1899 return; 1882 return;
1900 1883
1901 privptr = (struct netiucv_priv *)dev->priv;
1902 if (privptr) { 1884 if (privptr) {
1903 if (privptr->conn) 1885 if (privptr->conn)
1904 netiucv_remove_connection(privptr->conn); 1886 netiucv_remove_connection(privptr->conn);
@@ -1913,11 +1895,8 @@ netiucv_free_netdevice(struct net_device *dev)
1913/** 1895/**
1914 * Initialize a net device. (Called from kernel in alloc_netdev()) 1896 * Initialize a net device. (Called from kernel in alloc_netdev())
1915 */ 1897 */
1916static void 1898static void netiucv_setup_netdevice(struct net_device *dev)
1917netiucv_setup_netdevice(struct net_device *dev)
1918{ 1899{
1919 memset(dev->priv, 0, sizeof(struct netiucv_priv));
1920
1921 dev->mtu = NETIUCV_MTU_DEFAULT; 1900 dev->mtu = NETIUCV_MTU_DEFAULT;
1922 dev->hard_start_xmit = netiucv_tx; 1901 dev->hard_start_xmit = netiucv_tx;
1923 dev->open = netiucv_open; 1902 dev->open = netiucv_open;
@@ -1936,8 +1915,7 @@ netiucv_setup_netdevice(struct net_device *dev)
1936/** 1915/**
1937 * Allocate and initialize everything of a net device. 1916 * Allocate and initialize everything of a net device.
1938 */ 1917 */
1939static struct net_device * 1918static struct net_device *netiucv_init_netdevice(char *username)
1940netiucv_init_netdevice(char *username)
1941{ 1919{
1942 struct netiucv_priv *privptr; 1920 struct netiucv_priv *privptr;
1943 struct net_device *dev; 1921 struct net_device *dev;
@@ -1946,40 +1924,40 @@ netiucv_init_netdevice(char *username)
1946 netiucv_setup_netdevice); 1924 netiucv_setup_netdevice);
1947 if (!dev) 1925 if (!dev)
1948 return NULL; 1926 return NULL;
1949 if (dev_alloc_name(dev, dev->name) < 0) { 1927 if (dev_alloc_name(dev, dev->name) < 0)
1950 free_netdev(dev); 1928 goto out_netdev;
1951 return NULL;
1952 }
1953 1929
1954 privptr = (struct netiucv_priv *)dev->priv; 1930 privptr = netdev_priv(dev);
1955 privptr->fsm = init_fsm("netiucvdev", dev_state_names, 1931 privptr->fsm = init_fsm("netiucvdev", dev_state_names,
1956 dev_event_names, NR_DEV_STATES, NR_DEV_EVENTS, 1932 dev_event_names, NR_DEV_STATES, NR_DEV_EVENTS,
1957 dev_fsm, DEV_FSM_LEN, GFP_KERNEL); 1933 dev_fsm, DEV_FSM_LEN, GFP_KERNEL);
1958 if (!privptr->fsm) { 1934 if (!privptr->fsm)
1959 free_netdev(dev); 1935 goto out_netdev;
1960 return NULL; 1936
1961 }
1962 privptr->conn = netiucv_new_connection(dev, username); 1937 privptr->conn = netiucv_new_connection(dev, username);
1963 if (!privptr->conn) { 1938 if (!privptr->conn) {
1964 kfree_fsm(privptr->fsm);
1965 free_netdev(dev);
1966 IUCV_DBF_TEXT(setup, 2, "NULL from netiucv_new_connection\n"); 1939 IUCV_DBF_TEXT(setup, 2, "NULL from netiucv_new_connection\n");
1967 return NULL; 1940 goto out_fsm;
1968 } 1941 }
1969 fsm_newstate(privptr->fsm, DEV_STATE_STOPPED); 1942 fsm_newstate(privptr->fsm, DEV_STATE_STOPPED);
1970
1971 return dev; 1943 return dev;
1944
1945out_fsm:
1946 kfree_fsm(privptr->fsm);
1947out_netdev:
1948 free_netdev(dev);
1949 return NULL;
1972} 1950}
1973 1951
1974static ssize_t 1952static ssize_t conn_write(struct device_driver *drv,
1975conn_write(struct device_driver *drv, const char *buf, size_t count) 1953 const char *buf, size_t count)
1976{ 1954{
1977 char *p; 1955 const char *p;
1978 char username[9]; 1956 char username[9];
1979 int i, ret; 1957 int i, rc;
1980 struct net_device *dev; 1958 struct net_device *dev;
1981 struct iucv_connection **clist = &iucv_conns.iucv_connections; 1959 struct netiucv_priv *priv;
1982 unsigned long flags; 1960 struct iucv_connection *cp;
1983 1961
1984 IUCV_DBF_TEXT(trace, 3, __FUNCTION__); 1962 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
1985 if (count>9) { 1963 if (count>9) {
@@ -1988,83 +1966,82 @@ conn_write(struct device_driver *drv, const char *buf, size_t count)
1988 return -EINVAL; 1966 return -EINVAL;
1989 } 1967 }
1990 1968
1991 for (i=0, p=(char *)buf; i<8 && *p; i++, p++) { 1969 for (i = 0, p = buf; i < 8 && *p; i++, p++) {
1992 if (isalnum(*p) || (*p == '$')) 1970 if (isalnum(*p) || *p == '$') {
1993 username[i]= toupper(*p); 1971 username[i] = toupper(*p);
1994 else if (*p == '\n') { 1972 continue;
1973 }
1974 if (*p == '\n')
1995 /* trailing lf, grr */ 1975 /* trailing lf, grr */
1996 break; 1976 break;
1997 } else { 1977 PRINT_WARN("netiucv: Invalid character in username!\n");
1998 PRINT_WARN("netiucv: Invalid character in username!\n"); 1978 IUCV_DBF_TEXT_(setup, 2,
1999 IUCV_DBF_TEXT_(setup, 2, 1979 "conn_write: invalid character %c\n", *p);
2000 "conn_write: invalid character %c\n", *p); 1980 return -EINVAL;
2001 return -EINVAL;
2002 }
2003 } 1981 }
2004 while (i<8) 1982 while (i < 8)
2005 username[i++] = ' '; 1983 username[i++] = ' ';
2006 username[8] = '\0'; 1984 username[8] = '\0';
2007 1985
2008 read_lock_irqsave(&iucv_conns.iucv_rwlock, flags); 1986 read_lock_bh(&iucv_connection_rwlock);
2009 while (*clist) { 1987 list_for_each_entry(cp, &iucv_connection_list, list) {
2010 if (!strncmp(username, (*clist)->userid, 9)) 1988 if (!strncmp(username, cp->userid, 9)) {
2011 break; 1989 read_unlock_bh(&iucv_connection_rwlock);
2012 clist = &((*clist)->next); 1990 PRINT_WARN("netiucv: Connection to %s already "
2013 } 1991 "exists\n", username);
2014 read_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags); 1992 return -EEXIST;
2015 if (*clist) { 1993 }
2016 PRINT_WARN("netiucv: Connection to %s already exists\n",
2017 username);
2018 return -EEXIST;
2019 } 1994 }
1995 read_unlock_bh(&iucv_connection_rwlock);
1996
2020 dev = netiucv_init_netdevice(username); 1997 dev = netiucv_init_netdevice(username);
2021 if (!dev) { 1998 if (!dev) {
2022 PRINT_WARN( 1999 PRINT_WARN("netiucv: Could not allocate network device "
2023 "netiucv: Could not allocate network device structure " 2000 "structure for user '%s'\n",
2024 "for user '%s'\n", netiucv_printname(username)); 2001 netiucv_printname(username));
2025 IUCV_DBF_TEXT(setup, 2, "NULL from netiucv_init_netdevice\n"); 2002 IUCV_DBF_TEXT(setup, 2, "NULL from netiucv_init_netdevice\n");
2026 return -ENODEV; 2003 return -ENODEV;
2027 } 2004 }
2028 2005
2029 if ((ret = netiucv_register_device(dev))) { 2006 rc = netiucv_register_device(dev);
2007 if (rc) {
2030 IUCV_DBF_TEXT_(setup, 2, 2008 IUCV_DBF_TEXT_(setup, 2,
2031 "ret %d from netiucv_register_device\n", ret); 2009 "ret %d from netiucv_register_device\n", rc);
2032 goto out_free_ndev; 2010 goto out_free_ndev;
2033 } 2011 }
2034 2012
2035 /* sysfs magic */ 2013 /* sysfs magic */
2036 SET_NETDEV_DEV(dev, 2014 priv = netdev_priv(dev);
2037 (struct device*)((struct netiucv_priv*)dev->priv)->dev); 2015 SET_NETDEV_DEV(dev, priv->dev);
2038 2016
2039 if ((ret = register_netdev(dev))) { 2017 rc = register_netdev(dev);
2040 netiucv_unregister_device((struct device*) 2018 if (rc)
2041 ((struct netiucv_priv*)dev->priv)->dev); 2019 goto out_unreg;
2042 goto out_free_ndev;
2043 }
2044 2020
2045 PRINT_INFO("%s: '%s'\n", dev->name, netiucv_printname(username)); 2021 PRINT_INFO("%s: '%s'\n", dev->name, netiucv_printname(username));
2046 2022
2047 return count; 2023 return count;
2048 2024
2025out_unreg:
2026 netiucv_unregister_device(priv->dev);
2049out_free_ndev: 2027out_free_ndev:
2050 PRINT_WARN("netiucv: Could not register '%s'\n", dev->name); 2028 PRINT_WARN("netiucv: Could not register '%s'\n", dev->name);
2051 IUCV_DBF_TEXT(setup, 2, "conn_write: could not register\n"); 2029 IUCV_DBF_TEXT(setup, 2, "conn_write: could not register\n");
2052 netiucv_free_netdevice(dev); 2030 netiucv_free_netdevice(dev);
2053 return ret; 2031 return rc;
2054} 2032}
2055 2033
2056static DRIVER_ATTR(connection, 0200, NULL, conn_write); 2034static DRIVER_ATTR(connection, 0200, NULL, conn_write);
2057 2035
2058static ssize_t 2036static ssize_t remove_write (struct device_driver *drv,
2059remove_write (struct device_driver *drv, const char *buf, size_t count) 2037 const char *buf, size_t count)
2060{ 2038{
2061 struct iucv_connection **clist = &iucv_conns.iucv_connections; 2039 struct iucv_connection *cp;
2062 unsigned long flags;
2063 struct net_device *ndev; 2040 struct net_device *ndev;
2064 struct netiucv_priv *priv; 2041 struct netiucv_priv *priv;
2065 struct device *dev; 2042 struct device *dev;
2066 char name[IFNAMSIZ]; 2043 char name[IFNAMSIZ];
2067 char *p; 2044 const char *p;
2068 int i; 2045 int i;
2069 2046
2070 IUCV_DBF_TEXT(trace, 3, __FUNCTION__); 2047 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
@@ -2072,33 +2049,27 @@ remove_write (struct device_driver *drv, const char *buf, size_t count)
2072 if (count >= IFNAMSIZ) 2049 if (count >= IFNAMSIZ)
2073 count = IFNAMSIZ - 1;; 2050 count = IFNAMSIZ - 1;;
2074 2051
2075 for (i=0, p=(char *)buf; i<count && *p; i++, p++) { 2052 for (i = 0, p = buf; i < count && *p; i++, p++) {
2076 if ((*p == '\n') || (*p == ' ')) { 2053 if (*p == '\n' || *p == ' ')
2077 /* trailing lf, grr */ 2054 /* trailing lf, grr */
2078 break; 2055 break;
2079 } else { 2056 name[i] = *p;
2080 name[i]=*p;
2081 }
2082 } 2057 }
2083 name[i] = '\0'; 2058 name[i] = '\0';
2084 2059
2085 read_lock_irqsave(&iucv_conns.iucv_rwlock, flags); 2060 read_lock_bh(&iucv_connection_rwlock);
2086 while (*clist) { 2061 list_for_each_entry(cp, &iucv_connection_list, list) {
2087 ndev = (*clist)->netdev; 2062 ndev = cp->netdev;
2088 priv = (struct netiucv_priv*)ndev->priv; 2063 priv = netdev_priv(ndev);
2089 dev = priv->dev; 2064 dev = priv->dev;
2090 2065 if (strncmp(name, ndev->name, count))
2091 if (strncmp(name, ndev->name, count)) { 2066 continue;
2092 clist = &((*clist)->next); 2067 read_unlock_bh(&iucv_connection_rwlock);
2093 continue;
2094 }
2095 read_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags);
2096 if (ndev->flags & (IFF_UP | IFF_RUNNING)) { 2068 if (ndev->flags & (IFF_UP | IFF_RUNNING)) {
2097 PRINT_WARN( 2069 PRINT_WARN("netiucv: net device %s active with peer "
2098 "netiucv: net device %s active with peer %s\n", 2070 "%s\n", ndev->name, priv->conn->userid);
2099 ndev->name, priv->conn->userid);
2100 PRINT_WARN("netiucv: %s cannot be removed\n", 2071 PRINT_WARN("netiucv: %s cannot be removed\n",
2101 ndev->name); 2072 ndev->name);
2102 IUCV_DBF_TEXT(data, 2, "remove_write: still active\n"); 2073 IUCV_DBF_TEXT(data, 2, "remove_write: still active\n");
2103 return -EBUSY; 2074 return -EBUSY;
2104 } 2075 }
@@ -2106,7 +2077,7 @@ remove_write (struct device_driver *drv, const char *buf, size_t count)
2106 netiucv_unregister_device(dev); 2077 netiucv_unregister_device(dev);
2107 return count; 2078 return count;
2108 } 2079 }
2109 read_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags); 2080 read_unlock_bh(&iucv_connection_rwlock);
2110 PRINT_WARN("netiucv: net device %s unknown\n", name); 2081 PRINT_WARN("netiucv: net device %s unknown\n", name);
2111 IUCV_DBF_TEXT(data, 2, "remove_write: unknown device\n"); 2082 IUCV_DBF_TEXT(data, 2, "remove_write: unknown device\n");
2112 return -EINVAL; 2083 return -EINVAL;
@@ -2114,67 +2085,86 @@ remove_write (struct device_driver *drv, const char *buf, size_t count)
2114 2085
2115static DRIVER_ATTR(remove, 0200, NULL, remove_write); 2086static DRIVER_ATTR(remove, 0200, NULL, remove_write);
2116 2087
2117static void 2088static struct attribute * netiucv_drv_attrs[] = {
2118netiucv_banner(void) 2089 &driver_attr_connection.attr,
2090 &driver_attr_remove.attr,
2091 NULL,
2092};
2093
2094static struct attribute_group netiucv_drv_attr_group = {
2095 .attrs = netiucv_drv_attrs,
2096};
2097
2098static void netiucv_banner(void)
2119{ 2099{
2120 PRINT_INFO("NETIUCV driver initialized\n"); 2100 PRINT_INFO("NETIUCV driver initialized\n");
2121} 2101}
2122 2102
2123static void __exit 2103static void __exit netiucv_exit(void)
2124netiucv_exit(void)
2125{ 2104{
2105 struct iucv_connection *cp;
2106 struct net_device *ndev;
2107 struct netiucv_priv *priv;
2108 struct device *dev;
2109
2126 IUCV_DBF_TEXT(trace, 3, __FUNCTION__); 2110 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
2127 while (iucv_conns.iucv_connections) { 2111 while (!list_empty(&iucv_connection_list)) {
2128 struct net_device *ndev = iucv_conns.iucv_connections->netdev; 2112 cp = list_entry(iucv_connection_list.next,
2129 struct netiucv_priv *priv = (struct netiucv_priv*)ndev->priv; 2113 struct iucv_connection, list);
2130 struct device *dev = priv->dev; 2114 list_del(&cp->list);
2115 ndev = cp->netdev;
2116 priv = netdev_priv(ndev);
2117 dev = priv->dev;
2131 2118
2132 unregister_netdev(ndev); 2119 unregister_netdev(ndev);
2133 netiucv_unregister_device(dev); 2120 netiucv_unregister_device(dev);
2134 } 2121 }
2135 2122
2136 driver_remove_file(&netiucv_driver, &driver_attr_connection); 2123 sysfs_remove_group(&netiucv_driver.kobj, &netiucv_drv_attr_group);
2137 driver_remove_file(&netiucv_driver, &driver_attr_remove);
2138 driver_unregister(&netiucv_driver); 2124 driver_unregister(&netiucv_driver);
2125 iucv_unregister(&netiucv_handler, 1);
2139 iucv_unregister_dbf_views(); 2126 iucv_unregister_dbf_views();
2140 2127
2141 PRINT_INFO("NETIUCV driver unloaded\n"); 2128 PRINT_INFO("NETIUCV driver unloaded\n");
2142 return; 2129 return;
2143} 2130}
2144 2131
2145static int __init 2132static int __init netiucv_init(void)
2146netiucv_init(void)
2147{ 2133{
2148 int ret; 2134 int rc;
2149 2135
2150 ret = iucv_register_dbf_views(); 2136 rc = iucv_register_dbf_views();
2151 if (ret) { 2137 if (rc)
2152 PRINT_WARN("netiucv_init failed, " 2138 goto out;
2153 "iucv_register_dbf_views rc = %d\n", ret); 2139 rc = iucv_register(&netiucv_handler, 1);
2154 return ret; 2140 if (rc)
2155 } 2141 goto out_dbf;
2156 IUCV_DBF_TEXT(trace, 3, __FUNCTION__); 2142 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
2157 ret = driver_register(&netiucv_driver); 2143 rc = driver_register(&netiucv_driver);
2158 if (ret) { 2144 if (rc) {
2159 PRINT_ERR("NETIUCV: failed to register driver.\n"); 2145 PRINT_ERR("NETIUCV: failed to register driver.\n");
2160 IUCV_DBF_TEXT_(setup, 2, "ret %d from driver_register\n", ret); 2146 IUCV_DBF_TEXT_(setup, 2, "ret %d from driver_register\n", rc);
2161 iucv_unregister_dbf_views(); 2147 goto out_iucv;
2162 return ret;
2163 } 2148 }
2164 2149
2165 /* Add entry for specifying connections. */ 2150 rc = sysfs_create_group(&netiucv_driver.kobj, &netiucv_drv_attr_group);
2166 ret = driver_create_file(&netiucv_driver, &driver_attr_connection); 2151 if (rc) {
2167 if (!ret) { 2152 PRINT_ERR("NETIUCV: failed to add driver attributes.\n");
2168 ret = driver_create_file(&netiucv_driver, &driver_attr_remove); 2153 IUCV_DBF_TEXT_(setup, 2,
2169 netiucv_banner(); 2154 "ret %d - netiucv_drv_attr_group\n", rc);
2170 rwlock_init(&iucv_conns.iucv_rwlock); 2155 goto out_driver;
2171 } else {
2172 PRINT_ERR("NETIUCV: failed to add driver attribute.\n");
2173 IUCV_DBF_TEXT_(setup, 2, "ret %d from driver_create_file\n", ret);
2174 driver_unregister(&netiucv_driver);
2175 iucv_unregister_dbf_views();
2176 } 2156 }
2177 return ret; 2157 netiucv_banner();
2158 return rc;
2159
2160out_driver:
2161 driver_unregister(&netiucv_driver);
2162out_iucv:
2163 iucv_unregister(&netiucv_handler, 1);
2164out_dbf:
2165 iucv_unregister_dbf_views();
2166out:
2167 return rc;
2178} 2168}
2179 2169
2180module_init(netiucv_init); 2170module_init(netiucv_init);
diff --git a/drivers/s390/net/smsgiucv.c b/drivers/s390/net/smsgiucv.c
index b8179c27ceb6..3ccca5871fdf 100644
--- a/drivers/s390/net/smsgiucv.c
+++ b/drivers/s390/net/smsgiucv.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * IUCV special message driver 2 * IUCV special message driver
3 * 3 *
4 * Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation 4 * Copyright 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
5 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) 5 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
@@ -23,10 +23,10 @@
23#include <linux/init.h> 23#include <linux/init.h>
24#include <linux/errno.h> 24#include <linux/errno.h>
25#include <linux/device.h> 25#include <linux/device.h>
26#include <net/iucv/iucv.h>
26#include <asm/cpcmd.h> 27#include <asm/cpcmd.h>
27#include <asm/ebcdic.h> 28#include <asm/ebcdic.h>
28 29#include "smsgiucv.h"
29#include "iucv.h"
30 30
31struct smsg_callback { 31struct smsg_callback {
32 struct list_head list; 32 struct list_head list;
@@ -39,38 +39,46 @@ MODULE_AUTHOR
39 ("(C) 2003 IBM Corporation by Martin Schwidefsky (schwidefsky@de.ibm.com)"); 39 ("(C) 2003 IBM Corporation by Martin Schwidefsky (schwidefsky@de.ibm.com)");
40MODULE_DESCRIPTION ("Linux for S/390 IUCV special message driver"); 40MODULE_DESCRIPTION ("Linux for S/390 IUCV special message driver");
41 41
42static iucv_handle_t smsg_handle; 42static struct iucv_path *smsg_path;
43static unsigned short smsg_pathid; 43
44static DEFINE_SPINLOCK(smsg_list_lock); 44static DEFINE_SPINLOCK(smsg_list_lock);
45static struct list_head smsg_list = LIST_HEAD_INIT(smsg_list); 45static struct list_head smsg_list = LIST_HEAD_INIT(smsg_list);
46 46
47static void 47static int smsg_path_pending(struct iucv_path *, u8 ipvmid[8], u8 ipuser[16]);
48smsg_connection_complete(iucv_ConnectionComplete *eib, void *pgm_data) 48static void smsg_message_pending(struct iucv_path *, struct iucv_message *);
49
50static struct iucv_handler smsg_handler = {
51 .path_pending = smsg_path_pending,
52 .message_pending = smsg_message_pending,
53};
54
55static int smsg_path_pending(struct iucv_path *path, u8 ipvmid[8],
56 u8 ipuser[16])
49{ 57{
58 if (strncmp(ipvmid, "*MSG ", sizeof(ipvmid)) != 0)
59 return -EINVAL;
60 /* Path pending from *MSG. */
61 return iucv_path_accept(path, &smsg_handler, "SMSGIUCV ", NULL);
50} 62}
51 63
52 64static void smsg_message_pending(struct iucv_path *path,
53static void 65 struct iucv_message *msg)
54smsg_message_pending(iucv_MessagePending *eib, void *pgm_data)
55{ 66{
56 struct smsg_callback *cb; 67 struct smsg_callback *cb;
57 unsigned char *msg; 68 unsigned char *buffer;
58 unsigned char sender[9]; 69 unsigned char sender[9];
59 unsigned short len;
60 int rc, i; 70 int rc, i;
61 71
62 len = eib->ln1msg2.ipbfln1f; 72 buffer = kmalloc(msg->length + 1, GFP_ATOMIC | GFP_DMA);
63 msg = kmalloc(len + 1, GFP_ATOMIC|GFP_DMA); 73 if (!buffer) {
64 if (!msg) { 74 iucv_message_reject(path, msg);
65 iucv_reject(eib->ippathid, eib->ipmsgid, eib->iptrgcls);
66 return; 75 return;
67 } 76 }
68 rc = iucv_receive(eib->ippathid, eib->ipmsgid, eib->iptrgcls, 77 rc = iucv_message_receive(path, msg, 0, buffer, msg->length, NULL);
69 msg, len, NULL, NULL, NULL);
70 if (rc == 0) { 78 if (rc == 0) {
71 msg[len] = 0; 79 buffer[msg->length] = 0;
72 EBCASC(msg, len); 80 EBCASC(buffer, msg->length);
73 memcpy(sender, msg, 8); 81 memcpy(sender, buffer, 8);
74 sender[8] = 0; 82 sender[8] = 0;
75 /* Remove trailing whitespace from the sender name. */ 83 /* Remove trailing whitespace from the sender name. */
76 for (i = 7; i >= 0; i--) { 84 for (i = 7; i >= 0; i--) {
@@ -80,27 +88,17 @@ smsg_message_pending(iucv_MessagePending *eib, void *pgm_data)
80 } 88 }
81 spin_lock(&smsg_list_lock); 89 spin_lock(&smsg_list_lock);
82 list_for_each_entry(cb, &smsg_list, list) 90 list_for_each_entry(cb, &smsg_list, list)
83 if (strncmp(msg + 8, cb->prefix, cb->len) == 0) { 91 if (strncmp(buffer + 8, cb->prefix, cb->len) == 0) {
84 cb->callback(sender, msg + 8); 92 cb->callback(sender, buffer + 8);
85 break; 93 break;
86 } 94 }
87 spin_unlock(&smsg_list_lock); 95 spin_unlock(&smsg_list_lock);
88 } 96 }
89 kfree(msg); 97 kfree(buffer);
90} 98}
91 99
92static iucv_interrupt_ops_t smsg_ops = { 100int smsg_register_callback(char *prefix,
93 .ConnectionComplete = smsg_connection_complete, 101 void (*callback)(char *from, char *str))
94 .MessagePending = smsg_message_pending,
95};
96
97static struct device_driver smsg_driver = {
98 .name = "SMSGIUCV",
99 .bus = &iucv_bus,
100};
101
102int
103smsg_register_callback(char *prefix, void (*callback)(char *from, char *str))
104{ 102{
105 struct smsg_callback *cb; 103 struct smsg_callback *cb;
106 104
@@ -110,18 +108,18 @@ smsg_register_callback(char *prefix, void (*callback)(char *from, char *str))
110 cb->prefix = prefix; 108 cb->prefix = prefix;
111 cb->len = strlen(prefix); 109 cb->len = strlen(prefix);
112 cb->callback = callback; 110 cb->callback = callback;
113 spin_lock(&smsg_list_lock); 111 spin_lock_bh(&smsg_list_lock);
114 list_add_tail(&cb->list, &smsg_list); 112 list_add_tail(&cb->list, &smsg_list);
115 spin_unlock(&smsg_list_lock); 113 spin_unlock_bh(&smsg_list_lock);
116 return 0; 114 return 0;
117} 115}
118 116
119void 117void smsg_unregister_callback(char *prefix,
120smsg_unregister_callback(char *prefix, void (*callback)(char *from, char *str)) 118 void (*callback)(char *from, char *str))
121{ 119{
122 struct smsg_callback *cb, *tmp; 120 struct smsg_callback *cb, *tmp;
123 121
124 spin_lock(&smsg_list_lock); 122 spin_lock_bh(&smsg_list_lock);
125 cb = NULL; 123 cb = NULL;
126 list_for_each_entry(tmp, &smsg_list, list) 124 list_for_each_entry(tmp, &smsg_list, list)
127 if (tmp->callback == callback && 125 if (tmp->callback == callback &&
@@ -130,55 +128,58 @@ smsg_unregister_callback(char *prefix, void (*callback)(char *from, char *str))
130 list_del(&cb->list); 128 list_del(&cb->list);
131 break; 129 break;
132 } 130 }
133 spin_unlock(&smsg_list_lock); 131 spin_unlock_bh(&smsg_list_lock);
134 kfree(cb); 132 kfree(cb);
135} 133}
136 134
137static void __exit 135static struct device_driver smsg_driver = {
138smsg_exit(void) 136 .name = "SMSGIUCV",
137 .bus = &iucv_bus,
138};
139
140static void __exit smsg_exit(void)
139{ 141{
140 if (smsg_handle > 0) { 142 cpcmd("SET SMSG IUCV", NULL, 0, NULL);
141 cpcmd("SET SMSG OFF", NULL, 0, NULL); 143 iucv_unregister(&smsg_handler, 1);
142 iucv_sever(smsg_pathid, NULL); 144 driver_unregister(&smsg_driver);
143 iucv_unregister_program(smsg_handle);
144 driver_unregister(&smsg_driver);
145 }
146 return;
147} 145}
148 146
149static int __init 147static int __init smsg_init(void)
150smsg_init(void)
151{ 148{
152 static unsigned char pgmmask[24] = {
153 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
154 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
155 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
156 };
157 int rc; 149 int rc;
158 150
159 rc = driver_register(&smsg_driver); 151 rc = driver_register(&smsg_driver);
160 if (rc != 0) { 152 if (rc != 0)
161 printk(KERN_ERR "SMSGIUCV: failed to register driver.\n"); 153 goto out;
162 return rc; 154 rc = iucv_register(&smsg_handler, 1);
163 } 155 if (rc) {
164 smsg_handle = iucv_register_program("SMSGIUCV ", "*MSG ",
165 pgmmask, &smsg_ops, NULL);
166 if (!smsg_handle) {
167 printk(KERN_ERR "SMSGIUCV: failed to register to iucv"); 156 printk(KERN_ERR "SMSGIUCV: failed to register to iucv");
168 driver_unregister(&smsg_driver); 157 rc = -EIO; /* better errno ? */
169 return -EIO; /* better errno ? */ 158 goto out_driver;
159 }
160 smsg_path = iucv_path_alloc(255, 0, GFP_KERNEL);
161 if (!smsg_path) {
162 rc = -ENOMEM;
163 goto out_register;
170 } 164 }
171 rc = iucv_connect (&smsg_pathid, 255, NULL, "*MSG ", NULL, 0, 165 rc = iucv_path_connect(smsg_path, &smsg_handler, "*MSG ",
172 NULL, NULL, smsg_handle, NULL); 166 NULL, NULL, NULL);
173 if (rc) { 167 if (rc) {
174 printk(KERN_ERR "SMSGIUCV: failed to connect to *MSG"); 168 printk(KERN_ERR "SMSGIUCV: failed to connect to *MSG");
175 iucv_unregister_program(smsg_handle); 169 rc = -EIO; /* better errno ? */
176 driver_unregister(&smsg_driver); 170 goto out_free;
177 smsg_handle = NULL;
178 return -EIO;
179 } 171 }
180 cpcmd("SET SMSG IUCV", NULL, 0, NULL); 172 cpcmd("SET SMSG IUCV", NULL, 0, NULL);
181 return 0; 173 return 0;
174
175out_free:
176 iucv_path_free(smsg_path);
177out_register:
178 iucv_unregister(&smsg_handler, 1);
179out_driver:
180 driver_unregister(&smsg_driver);
181out:
182 return rc;
182} 183}
183 184
184module_init(smsg_init); 185module_init(smsg_init);