Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v3.11-rc4 2033 lines 56 kB view raw
1/********************************************************************* 2 * 3 * Filename: irlmp.c 4 * Version: 1.0 5 * Description: IrDA Link Management Protocol (LMP) layer 6 * Status: Stable. 7 * Author: Dag Brattli <dagb@cs.uit.no> 8 * Created at: Sun Aug 17 20:54:32 1997 9 * Modified at: Wed Jan 5 11:26:03 2000 10 * Modified by: Dag Brattli <dagb@cs.uit.no> 11 * 12 * Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>, 13 * All Rights Reserved. 14 * Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.com> 15 * 16 * This program is free software; you can redistribute it and/or 17 * modify it under the terms of the GNU General Public License as 18 * published by the Free Software Foundation; either version 2 of 19 * the License, or (at your option) any later version. 20 * 21 * Neither Dag Brattli nor University of Tromsø admit liability nor 22 * provide warranty for any of this software. This material is 23 * provided "AS-IS" and at no charge. 24 * 25 ********************************************************************/ 26 27#include <linux/module.h> 28#include <linux/slab.h> 29#include <linux/string.h> 30#include <linux/skbuff.h> 31#include <linux/types.h> 32#include <linux/proc_fs.h> 33#include <linux/init.h> 34#include <linux/kmod.h> 35#include <linux/random.h> 36#include <linux/seq_file.h> 37 38#include <net/irda/irda.h> 39#include <net/irda/timer.h> 40#include <net/irda/qos.h> 41#include <net/irda/irlap.h> 42#include <net/irda/iriap.h> 43#include <net/irda/irlmp.h> 44#include <net/irda/irlmp_frame.h> 45 46#include <asm/unaligned.h> 47 48static __u8 irlmp_find_free_slsap(void); 49static int irlmp_slsap_inuse(__u8 slsap_sel); 50 51/* Master structure */ 52struct irlmp_cb *irlmp = NULL; 53 54/* These can be altered by the sysctl interface */ 55int sysctl_discovery = 0; 56int sysctl_discovery_timeout = 3; /* 3 seconds by default */ 57int sysctl_discovery_slots = 6; /* 6 slots by default */ 58int sysctl_lap_keepalive_time = LM_IDLE_TIMEOUT * 1000 / HZ; 59char sysctl_devname[65]; 60 61static const char *irlmp_reasons[] = { 62 "ERROR, NOT USED", 63 "LM_USER_REQUEST", 64 "LM_LAP_DISCONNECT", 65 "LM_CONNECT_FAILURE", 66 "LM_LAP_RESET", 67 "LM_INIT_DISCONNECT", 68 "ERROR, NOT USED", 69 "UNKNOWN", 70}; 71 72const char *irlmp_reason_str(LM_REASON reason) 73{ 74 reason = min_t(size_t, reason, ARRAY_SIZE(irlmp_reasons) - 1); 75 return irlmp_reasons[reason]; 76} 77 78/* 79 * Function irlmp_init (void) 80 * 81 * Create (allocate) the main IrLMP structure 82 * 83 */ 84int __init irlmp_init(void) 85{ 86 IRDA_DEBUG(1, "%s()\n", __func__); 87 /* Initialize the irlmp structure. */ 88 irlmp = kzalloc( sizeof(struct irlmp_cb), GFP_KERNEL); 89 if (irlmp == NULL) 90 return -ENOMEM; 91 92 irlmp->magic = LMP_MAGIC; 93 94 irlmp->clients = hashbin_new(HB_LOCK); 95 irlmp->services = hashbin_new(HB_LOCK); 96 irlmp->links = hashbin_new(HB_LOCK); 97 irlmp->unconnected_lsaps = hashbin_new(HB_LOCK); 98 irlmp->cachelog = hashbin_new(HB_NOLOCK); 99 100 if ((irlmp->clients == NULL) || 101 (irlmp->services == NULL) || 102 (irlmp->links == NULL) || 103 (irlmp->unconnected_lsaps == NULL) || 104 (irlmp->cachelog == NULL)) { 105 return -ENOMEM; 106 } 107 108 spin_lock_init(&irlmp->cachelog->hb_spinlock); 109 110 irlmp->last_lsap_sel = 0x0f; /* Reserved 0x00-0x0f */ 111 strcpy(sysctl_devname, "Linux"); 112 113 init_timer(&irlmp->discovery_timer); 114 115 /* Do discovery every 3 seconds, conditionally */ 116 if (sysctl_discovery) 117 irlmp_start_discovery_timer(irlmp, 118 sysctl_discovery_timeout*HZ); 119 120 return 0; 121} 122 123/* 124 * Function irlmp_cleanup (void) 125 * 126 * Remove IrLMP layer 127 * 128 */ 129void irlmp_cleanup(void) 130{ 131 /* Check for main structure */ 132 IRDA_ASSERT(irlmp != NULL, return;); 133 IRDA_ASSERT(irlmp->magic == LMP_MAGIC, return;); 134 135 del_timer(&irlmp->discovery_timer); 136 137 hashbin_delete(irlmp->links, (FREE_FUNC) kfree); 138 hashbin_delete(irlmp->unconnected_lsaps, (FREE_FUNC) kfree); 139 hashbin_delete(irlmp->clients, (FREE_FUNC) kfree); 140 hashbin_delete(irlmp->services, (FREE_FUNC) kfree); 141 hashbin_delete(irlmp->cachelog, (FREE_FUNC) kfree); 142 143 /* De-allocate main structure */ 144 kfree(irlmp); 145 irlmp = NULL; 146} 147 148/* 149 * Function irlmp_open_lsap (slsap, notify) 150 * 151 * Register with IrLMP and create a local LSAP, 152 * returns handle to LSAP. 153 */ 154struct lsap_cb *irlmp_open_lsap(__u8 slsap_sel, notify_t *notify, __u8 pid) 155{ 156 struct lsap_cb *self; 157 158 IRDA_ASSERT(notify != NULL, return NULL;); 159 IRDA_ASSERT(irlmp != NULL, return NULL;); 160 IRDA_ASSERT(irlmp->magic == LMP_MAGIC, return NULL;); 161 IRDA_ASSERT(notify->instance != NULL, return NULL;); 162 163 /* Does the client care which Source LSAP selector it gets? */ 164 if (slsap_sel == LSAP_ANY) { 165 slsap_sel = irlmp_find_free_slsap(); 166 if (!slsap_sel) 167 return NULL; 168 } else if (irlmp_slsap_inuse(slsap_sel)) 169 return NULL; 170 171 /* Allocate new instance of a LSAP connection */ 172 self = kzalloc(sizeof(struct lsap_cb), GFP_ATOMIC); 173 if (self == NULL) { 174 IRDA_ERROR("%s: can't allocate memory\n", __func__); 175 return NULL; 176 } 177 178 self->magic = LMP_LSAP_MAGIC; 179 self->slsap_sel = slsap_sel; 180 181 /* Fix connectionless LSAP's */ 182 if (slsap_sel == LSAP_CONNLESS) { 183#ifdef CONFIG_IRDA_ULTRA 184 self->dlsap_sel = LSAP_CONNLESS; 185 self->pid = pid; 186#endif /* CONFIG_IRDA_ULTRA */ 187 } else 188 self->dlsap_sel = LSAP_ANY; 189 /* self->connected = FALSE; -> already NULL via memset() */ 190 191 init_timer(&self->watchdog_timer); 192 193 self->notify = *notify; 194 195 self->lsap_state = LSAP_DISCONNECTED; 196 197 /* Insert into queue of unconnected LSAPs */ 198 hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) self, 199 (long) self, NULL); 200 201 return self; 202} 203EXPORT_SYMBOL(irlmp_open_lsap); 204 205/* 206 * Function __irlmp_close_lsap (self) 207 * 208 * Remove an instance of LSAP 209 */ 210static void __irlmp_close_lsap(struct lsap_cb *self) 211{ 212 IRDA_DEBUG(4, "%s()\n", __func__); 213 214 IRDA_ASSERT(self != NULL, return;); 215 IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;); 216 217 /* 218 * Set some of the variables to preset values 219 */ 220 self->magic = 0; 221 del_timer(&self->watchdog_timer); /* Important! */ 222 223 if (self->conn_skb) 224 dev_kfree_skb(self->conn_skb); 225 226 kfree(self); 227} 228 229/* 230 * Function irlmp_close_lsap (self) 231 * 232 * Close and remove LSAP 233 * 234 */ 235void irlmp_close_lsap(struct lsap_cb *self) 236{ 237 struct lap_cb *lap; 238 struct lsap_cb *lsap = NULL; 239 240 IRDA_ASSERT(self != NULL, return;); 241 IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;); 242 243 /* 244 * Find out if we should remove this LSAP from a link or from the 245 * list of unconnected lsaps (not associated with a link) 246 */ 247 lap = self->lap; 248 if (lap) { 249 IRDA_ASSERT(lap->magic == LMP_LAP_MAGIC, return;); 250 /* We might close a LSAP before it has completed the 251 * connection setup. In those case, higher layers won't 252 * send a proper disconnect request. Harmless, except 253 * that we will forget to close LAP... - Jean II */ 254 if(self->lsap_state != LSAP_DISCONNECTED) { 255 self->lsap_state = LSAP_DISCONNECTED; 256 irlmp_do_lap_event(self->lap, 257 LM_LAP_DISCONNECT_REQUEST, NULL); 258 } 259 /* Now, remove from the link */ 260 lsap = hashbin_remove(lap->lsaps, (long) self, NULL); 261#ifdef CONFIG_IRDA_CACHE_LAST_LSAP 262 lap->cache.valid = FALSE; 263#endif 264 } 265 self->lap = NULL; 266 /* Check if we found the LSAP! If not then try the unconnected lsaps */ 267 if (!lsap) { 268 lsap = hashbin_remove(irlmp->unconnected_lsaps, (long) self, 269 NULL); 270 } 271 if (!lsap) { 272 IRDA_DEBUG(0, 273 "%s(), Looks like somebody has removed me already!\n", 274 __func__); 275 return; 276 } 277 __irlmp_close_lsap(self); 278} 279EXPORT_SYMBOL(irlmp_close_lsap); 280 281/* 282 * Function irlmp_register_irlap (saddr, notify) 283 * 284 * Register IrLAP layer with IrLMP. There is possible to have multiple 285 * instances of the IrLAP layer, each connected to different IrDA ports 286 * 287 */ 288void irlmp_register_link(struct irlap_cb *irlap, __u32 saddr, notify_t *notify) 289{ 290 struct lap_cb *lap; 291 292 IRDA_ASSERT(irlmp != NULL, return;); 293 IRDA_ASSERT(irlmp->magic == LMP_MAGIC, return;); 294 IRDA_ASSERT(notify != NULL, return;); 295 296 /* 297 * Allocate new instance of a LSAP connection 298 */ 299 lap = kzalloc(sizeof(struct lap_cb), GFP_KERNEL); 300 if (lap == NULL) { 301 IRDA_ERROR("%s: unable to kmalloc\n", __func__); 302 return; 303 } 304 305 lap->irlap = irlap; 306 lap->magic = LMP_LAP_MAGIC; 307 lap->saddr = saddr; 308 lap->daddr = DEV_ADDR_ANY; 309#ifdef CONFIG_IRDA_CACHE_LAST_LSAP 310 lap->cache.valid = FALSE; 311#endif 312 lap->lsaps = hashbin_new(HB_LOCK); 313 if (lap->lsaps == NULL) { 314 IRDA_WARNING("%s(), unable to kmalloc lsaps\n", __func__); 315 kfree(lap); 316 return; 317 } 318 319 lap->lap_state = LAP_STANDBY; 320 321 init_timer(&lap->idle_timer); 322 323 /* 324 * Insert into queue of LMP links 325 */ 326 hashbin_insert(irlmp->links, (irda_queue_t *) lap, lap->saddr, NULL); 327 328 /* 329 * We set only this variable so IrLAP can tell us on which link the 330 * different events happened on 331 */ 332 irda_notify_init(notify); 333 notify->instance = lap; 334} 335 336/* 337 * Function irlmp_unregister_irlap (saddr) 338 * 339 * IrLAP layer has been removed! 340 * 341 */ 342void irlmp_unregister_link(__u32 saddr) 343{ 344 struct lap_cb *link; 345 346 IRDA_DEBUG(4, "%s()\n", __func__); 347 348 /* We must remove ourselves from the hashbin *first*. This ensure 349 * that no more LSAPs will be open on this link and no discovery 350 * will be triggered anymore. Jean II */ 351 link = hashbin_remove(irlmp->links, saddr, NULL); 352 if (link) { 353 IRDA_ASSERT(link->magic == LMP_LAP_MAGIC, return;); 354 355 /* Kill all the LSAPs on this link. Jean II */ 356 link->reason = LAP_DISC_INDICATION; 357 link->daddr = DEV_ADDR_ANY; 358 irlmp_do_lap_event(link, LM_LAP_DISCONNECT_INDICATION, NULL); 359 360 /* Remove all discoveries discovered at this link */ 361 irlmp_expire_discoveries(irlmp->cachelog, link->saddr, TRUE); 362 363 /* Final cleanup */ 364 del_timer(&link->idle_timer); 365 link->magic = 0; 366 hashbin_delete(link->lsaps, (FREE_FUNC) __irlmp_close_lsap); 367 kfree(link); 368 } 369} 370 371/* 372 * Function irlmp_connect_request (handle, dlsap, userdata) 373 * 374 * Connect with a peer LSAP 375 * 376 */ 377int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel, 378 __u32 saddr, __u32 daddr, 379 struct qos_info *qos, struct sk_buff *userdata) 380{ 381 struct sk_buff *tx_skb = userdata; 382 struct lap_cb *lap; 383 struct lsap_cb *lsap; 384 int ret; 385 386 IRDA_ASSERT(self != NULL, return -EBADR;); 387 IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -EBADR;); 388 389 IRDA_DEBUG(2, 390 "%s(), slsap_sel=%02x, dlsap_sel=%02x, saddr=%08x, daddr=%08x\n", 391 __func__, self->slsap_sel, dlsap_sel, saddr, daddr); 392 393 if (test_bit(0, &self->connected)) { 394 ret = -EISCONN; 395 goto err; 396 } 397 398 /* Client must supply destination device address */ 399 if (!daddr) { 400 ret = -EINVAL; 401 goto err; 402 } 403 404 /* Any userdata? */ 405 if (tx_skb == NULL) { 406 tx_skb = alloc_skb(LMP_MAX_HEADER, GFP_ATOMIC); 407 if (!tx_skb) 408 return -ENOMEM; 409 410 skb_reserve(tx_skb, LMP_MAX_HEADER); 411 } 412 413 /* Make room for MUX control header (3 bytes) */ 414 IRDA_ASSERT(skb_headroom(tx_skb) >= LMP_CONTROL_HEADER, return -1;); 415 skb_push(tx_skb, LMP_CONTROL_HEADER); 416 417 self->dlsap_sel = dlsap_sel; 418 419 /* 420 * Find the link to where we should try to connect since there may 421 * be more than one IrDA port on this machine. If the client has 422 * passed us the saddr (and already knows which link to use), then 423 * we use that to find the link, if not then we have to look in the 424 * discovery log and check if any of the links has discovered a 425 * device with the given daddr 426 */ 427 if ((!saddr) || (saddr == DEV_ADDR_ANY)) { 428 discovery_t *discovery; 429 unsigned long flags; 430 431 spin_lock_irqsave(&irlmp->cachelog->hb_spinlock, flags); 432 if (daddr != DEV_ADDR_ANY) 433 discovery = hashbin_find(irlmp->cachelog, daddr, NULL); 434 else { 435 IRDA_DEBUG(2, "%s(), no daddr\n", __func__); 436 discovery = (discovery_t *) 437 hashbin_get_first(irlmp->cachelog); 438 } 439 440 if (discovery) { 441 saddr = discovery->data.saddr; 442 daddr = discovery->data.daddr; 443 } 444 spin_unlock_irqrestore(&irlmp->cachelog->hb_spinlock, flags); 445 } 446 lap = hashbin_lock_find(irlmp->links, saddr, NULL); 447 if (lap == NULL) { 448 IRDA_DEBUG(1, "%s(), Unable to find a usable link!\n", __func__); 449 ret = -EHOSTUNREACH; 450 goto err; 451 } 452 453 /* Check if LAP is disconnected or already connected */ 454 if (lap->daddr == DEV_ADDR_ANY) 455 lap->daddr = daddr; 456 else if (lap->daddr != daddr) { 457 /* Check if some LSAPs are active on this LAP */ 458 if (HASHBIN_GET_SIZE(lap->lsaps) == 0) { 459 /* No active connection, but LAP hasn't been 460 * disconnected yet (waiting for timeout in LAP). 461 * Maybe we could give LAP a bit of help in this case. 462 */ 463 IRDA_DEBUG(0, "%s(), sorry, but I'm waiting for LAP to timeout!\n", __func__); 464 ret = -EAGAIN; 465 goto err; 466 } 467 468 /* LAP is already connected to a different node, and LAP 469 * can only talk to one node at a time */ 470 IRDA_DEBUG(0, "%s(), sorry, but link is busy!\n", __func__); 471 ret = -EBUSY; 472 goto err; 473 } 474 475 self->lap = lap; 476 477 /* 478 * Remove LSAP from list of unconnected LSAPs and insert it into the 479 * list of connected LSAPs for the particular link 480 */ 481 lsap = hashbin_remove(irlmp->unconnected_lsaps, (long) self, NULL); 482 483 IRDA_ASSERT(lsap != NULL, return -1;); 484 IRDA_ASSERT(lsap->magic == LMP_LSAP_MAGIC, return -1;); 485 IRDA_ASSERT(lsap->lap != NULL, return -1;); 486 IRDA_ASSERT(lsap->lap->magic == LMP_LAP_MAGIC, return -1;); 487 488 hashbin_insert(self->lap->lsaps, (irda_queue_t *) self, (long) self, 489 NULL); 490 491 set_bit(0, &self->connected); /* TRUE */ 492 493 /* 494 * User supplied qos specifications? 495 */ 496 if (qos) 497 self->qos = *qos; 498 499 irlmp_do_lsap_event(self, LM_CONNECT_REQUEST, tx_skb); 500 501 /* Drop reference count - see irlap_data_request(). */ 502 dev_kfree_skb(tx_skb); 503 504 return 0; 505 506err: 507 /* Cleanup */ 508 if(tx_skb) 509 dev_kfree_skb(tx_skb); 510 return ret; 511} 512EXPORT_SYMBOL(irlmp_connect_request); 513 514/* 515 * Function irlmp_connect_indication (self) 516 * 517 * Incoming connection 518 * 519 */ 520void irlmp_connect_indication(struct lsap_cb *self, struct sk_buff *skb) 521{ 522 int max_seg_size; 523 int lap_header_size; 524 int max_header_size; 525 526 IRDA_ASSERT(self != NULL, return;); 527 IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;); 528 IRDA_ASSERT(skb != NULL, return;); 529 IRDA_ASSERT(self->lap != NULL, return;); 530 531 IRDA_DEBUG(2, "%s(), slsap_sel=%02x, dlsap_sel=%02x\n", 532 __func__, self->slsap_sel, self->dlsap_sel); 533 534 /* Note : self->lap is set in irlmp_link_data_indication(), 535 * (case CONNECT_CMD:) because we have no way to set it here. 536 * Similarly, self->dlsap_sel is usually set in irlmp_find_lsap(). 537 * Jean II */ 538 539 self->qos = *self->lap->qos; 540 541 max_seg_size = self->lap->qos->data_size.value-LMP_HEADER; 542 lap_header_size = IRLAP_GET_HEADER_SIZE(self->lap->irlap); 543 max_header_size = LMP_HEADER + lap_header_size; 544 545 /* Hide LMP_CONTROL_HEADER header from layer above */ 546 skb_pull(skb, LMP_CONTROL_HEADER); 547 548 if (self->notify.connect_indication) { 549 /* Don't forget to refcount it - see irlap_driver_rcv(). */ 550 skb_get(skb); 551 self->notify.connect_indication(self->notify.instance, self, 552 &self->qos, max_seg_size, 553 max_header_size, skb); 554 } 555} 556 557/* 558 * Function irlmp_connect_response (handle, userdata) 559 * 560 * Service user is accepting connection 561 * 562 */ 563int irlmp_connect_response(struct lsap_cb *self, struct sk_buff *userdata) 564{ 565 IRDA_ASSERT(self != NULL, return -1;); 566 IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;); 567 IRDA_ASSERT(userdata != NULL, return -1;); 568 569 /* We set the connected bit and move the lsap to the connected list 570 * in the state machine itself. Jean II */ 571 572 IRDA_DEBUG(2, "%s(), slsap_sel=%02x, dlsap_sel=%02x\n", 573 __func__, self->slsap_sel, self->dlsap_sel); 574 575 /* Make room for MUX control header (3 bytes) */ 576 IRDA_ASSERT(skb_headroom(userdata) >= LMP_CONTROL_HEADER, return -1;); 577 skb_push(userdata, LMP_CONTROL_HEADER); 578 579 irlmp_do_lsap_event(self, LM_CONNECT_RESPONSE, userdata); 580 581 /* Drop reference count - see irlap_data_request(). */ 582 dev_kfree_skb(userdata); 583 584 return 0; 585} 586EXPORT_SYMBOL(irlmp_connect_response); 587 588/* 589 * Function irlmp_connect_confirm (handle, skb) 590 * 591 * LSAP connection confirmed peer device! 592 */ 593void irlmp_connect_confirm(struct lsap_cb *self, struct sk_buff *skb) 594{ 595 int max_header_size; 596 int lap_header_size; 597 int max_seg_size; 598 599 IRDA_DEBUG(3, "%s()\n", __func__); 600 601 IRDA_ASSERT(skb != NULL, return;); 602 IRDA_ASSERT(self != NULL, return;); 603 IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;); 604 IRDA_ASSERT(self->lap != NULL, return;); 605 606 self->qos = *self->lap->qos; 607 608 max_seg_size = self->lap->qos->data_size.value-LMP_HEADER; 609 lap_header_size = IRLAP_GET_HEADER_SIZE(self->lap->irlap); 610 max_header_size = LMP_HEADER + lap_header_size; 611 612 IRDA_DEBUG(2, "%s(), max_header_size=%d\n", 613 __func__, max_header_size); 614 615 /* Hide LMP_CONTROL_HEADER header from layer above */ 616 skb_pull(skb, LMP_CONTROL_HEADER); 617 618 if (self->notify.connect_confirm) { 619 /* Don't forget to refcount it - see irlap_driver_rcv() */ 620 skb_get(skb); 621 self->notify.connect_confirm(self->notify.instance, self, 622 &self->qos, max_seg_size, 623 max_header_size, skb); 624 } 625} 626 627/* 628 * Function irlmp_dup (orig, instance) 629 * 630 * Duplicate LSAP, can be used by servers to confirm a connection on a 631 * new LSAP so it can keep listening on the old one. 632 * 633 */ 634struct lsap_cb *irlmp_dup(struct lsap_cb *orig, void *instance) 635{ 636 struct lsap_cb *new; 637 unsigned long flags; 638 639 IRDA_DEBUG(1, "%s()\n", __func__); 640 641 spin_lock_irqsave(&irlmp->unconnected_lsaps->hb_spinlock, flags); 642 643 /* Only allowed to duplicate unconnected LSAP's, and only LSAPs 644 * that have received a connect indication. Jean II */ 645 if ((!hashbin_find(irlmp->unconnected_lsaps, (long) orig, NULL)) || 646 (orig->lap == NULL)) { 647 IRDA_DEBUG(0, "%s(), invalid LSAP (wrong state)\n", 648 __func__); 649 spin_unlock_irqrestore(&irlmp->unconnected_lsaps->hb_spinlock, 650 flags); 651 return NULL; 652 } 653 654 /* Allocate a new instance */ 655 new = kmemdup(orig, sizeof(*new), GFP_ATOMIC); 656 if (!new) { 657 IRDA_DEBUG(0, "%s(), unable to kmalloc\n", __func__); 658 spin_unlock_irqrestore(&irlmp->unconnected_lsaps->hb_spinlock, 659 flags); 660 return NULL; 661 } 662 /* new->lap = orig->lap; => done in the memcpy() */ 663 /* new->slsap_sel = orig->slsap_sel; => done in the memcpy() */ 664 new->conn_skb = NULL; 665 666 spin_unlock_irqrestore(&irlmp->unconnected_lsaps->hb_spinlock, flags); 667 668 /* Not everything is the same */ 669 new->notify.instance = instance; 670 671 init_timer(&new->watchdog_timer); 672 673 hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) new, 674 (long) new, NULL); 675 676#ifdef CONFIG_IRDA_CACHE_LAST_LSAP 677 /* Make sure that we invalidate the LSAP cache */ 678 new->lap->cache.valid = FALSE; 679#endif /* CONFIG_IRDA_CACHE_LAST_LSAP */ 680 681 return new; 682} 683 684/* 685 * Function irlmp_disconnect_request (handle, userdata) 686 * 687 * The service user is requesting disconnection, this will not remove the 688 * LSAP, but only mark it as disconnected 689 */ 690int irlmp_disconnect_request(struct lsap_cb *self, struct sk_buff *userdata) 691{ 692 struct lsap_cb *lsap; 693 694 IRDA_ASSERT(self != NULL, return -1;); 695 IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;); 696 IRDA_ASSERT(userdata != NULL, return -1;); 697 698 /* Already disconnected ? 699 * There is a race condition between irlmp_disconnect_indication() 700 * and us that might mess up the hashbins below. This fixes it. 701 * Jean II */ 702 if (! test_and_clear_bit(0, &self->connected)) { 703 IRDA_DEBUG(0, "%s(), already disconnected!\n", __func__); 704 dev_kfree_skb(userdata); 705 return -1; 706 } 707 708 skb_push(userdata, LMP_CONTROL_HEADER); 709 710 /* 711 * Do the event before the other stuff since we must know 712 * which lap layer that the frame should be transmitted on 713 */ 714 irlmp_do_lsap_event(self, LM_DISCONNECT_REQUEST, userdata); 715 716 /* Drop reference count - see irlap_data_request(). */ 717 dev_kfree_skb(userdata); 718 719 /* 720 * Remove LSAP from list of connected LSAPs for the particular link 721 * and insert it into the list of unconnected LSAPs 722 */ 723 IRDA_ASSERT(self->lap != NULL, return -1;); 724 IRDA_ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;); 725 IRDA_ASSERT(self->lap->lsaps != NULL, return -1;); 726 727 lsap = hashbin_remove(self->lap->lsaps, (long) self, NULL); 728#ifdef CONFIG_IRDA_CACHE_LAST_LSAP 729 self->lap->cache.valid = FALSE; 730#endif 731 732 IRDA_ASSERT(lsap != NULL, return -1;); 733 IRDA_ASSERT(lsap->magic == LMP_LSAP_MAGIC, return -1;); 734 IRDA_ASSERT(lsap == self, return -1;); 735 736 hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) self, 737 (long) self, NULL); 738 739 /* Reset some values */ 740 self->dlsap_sel = LSAP_ANY; 741 self->lap = NULL; 742 743 return 0; 744} 745EXPORT_SYMBOL(irlmp_disconnect_request); 746 747/* 748 * Function irlmp_disconnect_indication (reason, userdata) 749 * 750 * LSAP is being closed! 751 */ 752void irlmp_disconnect_indication(struct lsap_cb *self, LM_REASON reason, 753 struct sk_buff *skb) 754{ 755 struct lsap_cb *lsap; 756 757 IRDA_DEBUG(1, "%s(), reason=%s [%d]\n", __func__, 758 irlmp_reason_str(reason), reason); 759 IRDA_ASSERT(self != NULL, return;); 760 IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;); 761 762 IRDA_DEBUG(3, "%s(), slsap_sel=%02x, dlsap_sel=%02x\n", 763 __func__, self->slsap_sel, self->dlsap_sel); 764 765 /* Already disconnected ? 766 * There is a race condition between irlmp_disconnect_request() 767 * and us that might mess up the hashbins below. This fixes it. 768 * Jean II */ 769 if (! test_and_clear_bit(0, &self->connected)) { 770 IRDA_DEBUG(0, "%s(), already disconnected!\n", __func__); 771 return; 772 } 773 774 /* 775 * Remove association between this LSAP and the link it used 776 */ 777 IRDA_ASSERT(self->lap != NULL, return;); 778 IRDA_ASSERT(self->lap->lsaps != NULL, return;); 779 780 lsap = hashbin_remove(self->lap->lsaps, (long) self, NULL); 781#ifdef CONFIG_IRDA_CACHE_LAST_LSAP 782 self->lap->cache.valid = FALSE; 783#endif 784 785 IRDA_ASSERT(lsap != NULL, return;); 786 IRDA_ASSERT(lsap == self, return;); 787 hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) lsap, 788 (long) lsap, NULL); 789 790 self->dlsap_sel = LSAP_ANY; 791 self->lap = NULL; 792 793 /* 794 * Inform service user 795 */ 796 if (self->notify.disconnect_indication) { 797 /* Don't forget to refcount it - see irlap_driver_rcv(). */ 798 if(skb) 799 skb_get(skb); 800 self->notify.disconnect_indication(self->notify.instance, 801 self, reason, skb); 802 } else { 803 IRDA_DEBUG(0, "%s(), no handler\n", __func__); 804 } 805} 806 807/* 808 * Function irlmp_do_expiry (void) 809 * 810 * Do a cleanup of the discovery log (remove old entries) 811 * 812 * Note : separate from irlmp_do_discovery() so that we can handle 813 * passive discovery properly. 814 */ 815void irlmp_do_expiry(void) 816{ 817 struct lap_cb *lap; 818 819 /* 820 * Expire discovery on all links which are *not* connected. 821 * On links which are connected, we can't do discovery 822 * anymore and can't refresh the log, so we freeze the 823 * discovery log to keep info about the device we are 824 * connected to. 825 * This info is mandatory if we want irlmp_connect_request() 826 * to work properly. - Jean II 827 */ 828 lap = (struct lap_cb *) hashbin_get_first(irlmp->links); 829 while (lap != NULL) { 830 IRDA_ASSERT(lap->magic == LMP_LAP_MAGIC, return;); 831 832 if (lap->lap_state == LAP_STANDBY) { 833 /* Expire discoveries discovered on this link */ 834 irlmp_expire_discoveries(irlmp->cachelog, lap->saddr, 835 FALSE); 836 } 837 lap = (struct lap_cb *) hashbin_get_next(irlmp->links); 838 } 839} 840 841/* 842 * Function irlmp_do_discovery (nslots) 843 * 844 * Do some discovery on all links 845 * 846 * Note : log expiry is done above. 847 */ 848void irlmp_do_discovery(int nslots) 849{ 850 struct lap_cb *lap; 851 __u16 *data_hintsp; 852 853 /* Make sure the value is sane */ 854 if ((nslots != 1) && (nslots != 6) && (nslots != 8) && (nslots != 16)){ 855 IRDA_WARNING("%s: invalid value for number of slots!\n", 856 __func__); 857 nslots = sysctl_discovery_slots = 8; 858 } 859 860 /* Construct new discovery info to be used by IrLAP, */ 861 data_hintsp = (__u16 *) irlmp->discovery_cmd.data.hints; 862 put_unaligned(irlmp->hints.word, data_hintsp); 863 864 /* 865 * Set character set for device name (we use ASCII), and 866 * copy device name. Remember to make room for a \0 at the 867 * end 868 */ 869 irlmp->discovery_cmd.data.charset = CS_ASCII; 870 strncpy(irlmp->discovery_cmd.data.info, sysctl_devname, 871 NICKNAME_MAX_LEN); 872 irlmp->discovery_cmd.name_len = strlen(irlmp->discovery_cmd.data.info); 873 irlmp->discovery_cmd.nslots = nslots; 874 875 /* 876 * Try to send discovery packets on all links 877 */ 878 lap = (struct lap_cb *) hashbin_get_first(irlmp->links); 879 while (lap != NULL) { 880 IRDA_ASSERT(lap->magic == LMP_LAP_MAGIC, return;); 881 882 if (lap->lap_state == LAP_STANDBY) { 883 /* Try to discover */ 884 irlmp_do_lap_event(lap, LM_LAP_DISCOVERY_REQUEST, 885 NULL); 886 } 887 lap = (struct lap_cb *) hashbin_get_next(irlmp->links); 888 } 889} 890 891/* 892 * Function irlmp_discovery_request (nslots) 893 * 894 * Do a discovery of devices in front of the computer 895 * 896 * If the caller has registered a client discovery callback, this 897 * allow him to receive the full content of the discovery log through 898 * this callback (as normally he will receive only new discoveries). 899 */ 900void irlmp_discovery_request(int nslots) 901{ 902 /* Return current cached discovery log (in full) */ 903 irlmp_discovery_confirm(irlmp->cachelog, DISCOVERY_LOG); 904 905 /* 906 * Start a single discovery operation if discovery is not already 907 * running 908 */ 909 if (!sysctl_discovery) { 910 /* Check if user wants to override the default */ 911 if (nslots == DISCOVERY_DEFAULT_SLOTS) 912 nslots = sysctl_discovery_slots; 913 914 irlmp_do_discovery(nslots); 915 /* Note : we never do expiry here. Expiry will run on the 916 * discovery timer regardless of the state of sysctl_discovery 917 * Jean II */ 918 } 919} 920EXPORT_SYMBOL(irlmp_discovery_request); 921 922/* 923 * Function irlmp_get_discoveries (pn, mask, slots) 924 * 925 * Return the current discovery log 926 * 927 * If discovery is not enabled, you should call this function again 928 * after 1 or 2 seconds (i.e. after discovery has been done). 929 */ 930struct irda_device_info *irlmp_get_discoveries(int *pn, __u16 mask, int nslots) 931{ 932 /* If discovery is not enabled, it's likely that the discovery log 933 * will be empty. So, we trigger a single discovery, so that next 934 * time the user call us there might be some results in the log. 935 * Jean II 936 */ 937 if (!sysctl_discovery) { 938 /* Check if user wants to override the default */ 939 if (nslots == DISCOVERY_DEFAULT_SLOTS) 940 nslots = sysctl_discovery_slots; 941 942 /* Start discovery - will complete sometime later */ 943 irlmp_do_discovery(nslots); 944 /* Note : we never do expiry here. Expiry will run on the 945 * discovery timer regardless of the state of sysctl_discovery 946 * Jean II */ 947 } 948 949 /* Return current cached discovery log */ 950 return irlmp_copy_discoveries(irlmp->cachelog, pn, mask, TRUE); 951} 952EXPORT_SYMBOL(irlmp_get_discoveries); 953 954/* 955 * Function irlmp_notify_client (log) 956 * 957 * Notify all about discovered devices 958 * 959 * Clients registered with IrLMP are : 960 * o IrComm 961 * o IrLAN 962 * o Any socket (in any state - ouch, that may be a lot !) 963 * The client may have defined a callback to be notified in case of 964 * partial/selective discovery based on the hints that it passed to IrLMP. 965 */ 966static inline void 967irlmp_notify_client(irlmp_client_t *client, 968 hashbin_t *log, DISCOVERY_MODE mode) 969{ 970 discinfo_t *discoveries; /* Copy of the discovery log */ 971 int number; /* Number of nodes in the log */ 972 int i; 973 974 IRDA_DEBUG(3, "%s()\n", __func__); 975 976 /* Check if client wants or not partial/selective log (optimisation) */ 977 if (!client->disco_callback) 978 return; 979 980 /* 981 * Locking notes : 982 * the old code was manipulating the log directly, which was 983 * very racy. Now, we use copy_discoveries, that protects 984 * itself while dumping the log for us. 985 * The overhead of the copy is compensated by the fact that 986 * we only pass new discoveries in normal mode and don't 987 * pass the same old entry every 3s to the caller as we used 988 * to do (virtual function calling is expensive). 989 * Jean II 990 */ 991 992 /* 993 * Now, check all discovered devices (if any), and notify client 994 * only about the services that the client is interested in 995 * We also notify only about the new devices unless the caller 996 * explicitly request a dump of the log. Jean II 997 */ 998 discoveries = irlmp_copy_discoveries(log, &number, 999 client->hint_mask.word, 1000 (mode == DISCOVERY_LOG)); 1001 /* Check if the we got some results */ 1002 if (discoveries == NULL) 1003 return; /* No nodes discovered */ 1004 1005 /* Pass all entries to the listener */ 1006 for(i = 0; i < number; i++) 1007 client->disco_callback(&(discoveries[i]), mode, client->priv); 1008 1009 /* Free up our buffer */ 1010 kfree(discoveries); 1011} 1012 1013/* 1014 * Function irlmp_discovery_confirm ( self, log) 1015 * 1016 * Some device(s) answered to our discovery request! Check to see which 1017 * device it is, and give indication to the client(s) 1018 * 1019 */ 1020void irlmp_discovery_confirm(hashbin_t *log, DISCOVERY_MODE mode) 1021{ 1022 irlmp_client_t *client; 1023 irlmp_client_t *client_next; 1024 1025 IRDA_DEBUG(3, "%s()\n", __func__); 1026 1027 IRDA_ASSERT(log != NULL, return;); 1028 1029 if (!(HASHBIN_GET_SIZE(log))) 1030 return; 1031 1032 /* For each client - notify callback may touch client list */ 1033 client = (irlmp_client_t *) hashbin_get_first(irlmp->clients); 1034 while (NULL != hashbin_find_next(irlmp->clients, (long) client, NULL, 1035 (void *) &client_next) ) { 1036 /* Check if we should notify client */ 1037 irlmp_notify_client(client, log, mode); 1038 1039 client = client_next; 1040 } 1041} 1042 1043/* 1044 * Function irlmp_discovery_expiry (expiry) 1045 * 1046 * This device is no longer been discovered, and therefore it is being 1047 * purged from the discovery log. Inform all clients who have 1048 * registered for this event... 1049 * 1050 * Note : called exclusively from discovery.c 1051 * Note : this is no longer called under discovery spinlock, so the 1052 * client can do whatever he wants in the callback. 1053 */ 1054void irlmp_discovery_expiry(discinfo_t *expiries, int number) 1055{ 1056 irlmp_client_t *client; 1057 irlmp_client_t *client_next; 1058 int i; 1059 1060 IRDA_DEBUG(3, "%s()\n", __func__); 1061 1062 IRDA_ASSERT(expiries != NULL, return;); 1063 1064 /* For each client - notify callback may touch client list */ 1065 client = (irlmp_client_t *) hashbin_get_first(irlmp->clients); 1066 while (NULL != hashbin_find_next(irlmp->clients, (long) client, NULL, 1067 (void *) &client_next) ) { 1068 1069 /* Pass all entries to the listener */ 1070 for(i = 0; i < number; i++) { 1071 /* Check if we should notify client */ 1072 if ((client->expir_callback) && 1073 (client->hint_mask.word & 1074 get_unaligned((__u16 *)expiries[i].hints) 1075 & 0x7f7f) ) 1076 client->expir_callback(&(expiries[i]), 1077 EXPIRY_TIMEOUT, 1078 client->priv); 1079 } 1080 1081 /* Next client */ 1082 client = client_next; 1083 } 1084} 1085 1086/* 1087 * Function irlmp_get_discovery_response () 1088 * 1089 * Used by IrLAP to get the discovery info it needs when answering 1090 * discovery requests by other devices. 1091 */ 1092discovery_t *irlmp_get_discovery_response(void) 1093{ 1094 IRDA_DEBUG(4, "%s()\n", __func__); 1095 1096 IRDA_ASSERT(irlmp != NULL, return NULL;); 1097 1098 put_unaligned(irlmp->hints.word, (__u16 *)irlmp->discovery_rsp.data.hints); 1099 1100 /* 1101 * Set character set for device name (we use ASCII), and 1102 * copy device name. Remember to make room for a \0 at the 1103 * end 1104 */ 1105 irlmp->discovery_rsp.data.charset = CS_ASCII; 1106 1107 strncpy(irlmp->discovery_rsp.data.info, sysctl_devname, 1108 NICKNAME_MAX_LEN); 1109 irlmp->discovery_rsp.name_len = strlen(irlmp->discovery_rsp.data.info); 1110 1111 return &irlmp->discovery_rsp; 1112} 1113 1114/* 1115 * Function irlmp_data_request (self, skb) 1116 * 1117 * Send some data to peer device 1118 * 1119 * Note on skb management : 1120 * After calling the lower layers of the IrDA stack, we always 1121 * kfree() the skb, which drop the reference count (and potentially 1122 * destroy it). 1123 * IrLMP and IrLAP may queue the packet, and in those cases will need 1124 * to use skb_get() to keep it around. 1125 * Jean II 1126 */ 1127int irlmp_data_request(struct lsap_cb *self, struct sk_buff *userdata) 1128{ 1129 int ret; 1130 1131 IRDA_ASSERT(self != NULL, return -1;); 1132 IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;); 1133 1134 /* Make room for MUX header */ 1135 IRDA_ASSERT(skb_headroom(userdata) >= LMP_HEADER, return -1;); 1136 skb_push(userdata, LMP_HEADER); 1137 1138 ret = irlmp_do_lsap_event(self, LM_DATA_REQUEST, userdata); 1139 1140 /* Drop reference count - see irlap_data_request(). */ 1141 dev_kfree_skb(userdata); 1142 1143 return ret; 1144} 1145EXPORT_SYMBOL(irlmp_data_request); 1146 1147/* 1148 * Function irlmp_data_indication (handle, skb) 1149 * 1150 * Got data from LAP layer so pass it up to upper layer 1151 * 1152 */ 1153void irlmp_data_indication(struct lsap_cb *self, struct sk_buff *skb) 1154{ 1155 /* Hide LMP header from layer above */ 1156 skb_pull(skb, LMP_HEADER); 1157 1158 if (self->notify.data_indication) { 1159 /* Don't forget to refcount it - see irlap_driver_rcv(). */ 1160 skb_get(skb); 1161 self->notify.data_indication(self->notify.instance, self, skb); 1162 } 1163} 1164 1165/* 1166 * Function irlmp_udata_request (self, skb) 1167 */ 1168int irlmp_udata_request(struct lsap_cb *self, struct sk_buff *userdata) 1169{ 1170 int ret; 1171 1172 IRDA_DEBUG(4, "%s()\n", __func__); 1173 1174 IRDA_ASSERT(userdata != NULL, return -1;); 1175 1176 /* Make room for MUX header */ 1177 IRDA_ASSERT(skb_headroom(userdata) >= LMP_HEADER, return -1;); 1178 skb_push(userdata, LMP_HEADER); 1179 1180 ret = irlmp_do_lsap_event(self, LM_UDATA_REQUEST, userdata); 1181 1182 /* Drop reference count - see irlap_data_request(). */ 1183 dev_kfree_skb(userdata); 1184 1185 return ret; 1186} 1187 1188/* 1189 * Function irlmp_udata_indication (self, skb) 1190 * 1191 * Send unreliable data (but still within the connection) 1192 * 1193 */ 1194void irlmp_udata_indication(struct lsap_cb *self, struct sk_buff *skb) 1195{ 1196 IRDA_DEBUG(4, "%s()\n", __func__); 1197 1198 IRDA_ASSERT(self != NULL, return;); 1199 IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;); 1200 IRDA_ASSERT(skb != NULL, return;); 1201 1202 /* Hide LMP header from layer above */ 1203 skb_pull(skb, LMP_HEADER); 1204 1205 if (self->notify.udata_indication) { 1206 /* Don't forget to refcount it - see irlap_driver_rcv(). */ 1207 skb_get(skb); 1208 self->notify.udata_indication(self->notify.instance, self, 1209 skb); 1210 } 1211} 1212 1213/* 1214 * Function irlmp_connless_data_request (self, skb) 1215 */ 1216#ifdef CONFIG_IRDA_ULTRA 1217int irlmp_connless_data_request(struct lsap_cb *self, struct sk_buff *userdata, 1218 __u8 pid) 1219{ 1220 struct sk_buff *clone_skb; 1221 struct lap_cb *lap; 1222 1223 IRDA_DEBUG(4, "%s()\n", __func__); 1224 1225 IRDA_ASSERT(userdata != NULL, return -1;); 1226 1227 /* Make room for MUX and PID header */ 1228 IRDA_ASSERT(skb_headroom(userdata) >= LMP_HEADER+LMP_PID_HEADER, 1229 return -1;); 1230 1231 /* Insert protocol identifier */ 1232 skb_push(userdata, LMP_PID_HEADER); 1233 if(self != NULL) 1234 userdata->data[0] = self->pid; 1235 else 1236 userdata->data[0] = pid; 1237 1238 /* Connectionless sockets must use 0x70 */ 1239 skb_push(userdata, LMP_HEADER); 1240 userdata->data[0] = userdata->data[1] = LSAP_CONNLESS; 1241 1242 /* Try to send Connectionless packets out on all links */ 1243 lap = (struct lap_cb *) hashbin_get_first(irlmp->links); 1244 while (lap != NULL) { 1245 IRDA_ASSERT(lap->magic == LMP_LAP_MAGIC, return -1;); 1246 1247 clone_skb = skb_clone(userdata, GFP_ATOMIC); 1248 if (!clone_skb) { 1249 dev_kfree_skb(userdata); 1250 return -ENOMEM; 1251 } 1252 1253 irlap_unitdata_request(lap->irlap, clone_skb); 1254 /* irlap_unitdata_request() don't increase refcount, 1255 * so no dev_kfree_skb() - Jean II */ 1256 1257 lap = (struct lap_cb *) hashbin_get_next(irlmp->links); 1258 } 1259 dev_kfree_skb(userdata); 1260 1261 return 0; 1262} 1263#endif /* CONFIG_IRDA_ULTRA */ 1264 1265/* 1266 * Function irlmp_connless_data_indication (self, skb) 1267 * 1268 * Receive unreliable data outside any connection. Mostly used by Ultra 1269 * 1270 */ 1271#ifdef CONFIG_IRDA_ULTRA 1272void irlmp_connless_data_indication(struct lsap_cb *self, struct sk_buff *skb) 1273{ 1274 IRDA_DEBUG(4, "%s()\n", __func__); 1275 1276 IRDA_ASSERT(self != NULL, return;); 1277 IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;); 1278 IRDA_ASSERT(skb != NULL, return;); 1279 1280 /* Hide LMP and PID header from layer above */ 1281 skb_pull(skb, LMP_HEADER+LMP_PID_HEADER); 1282 1283 if (self->notify.udata_indication) { 1284 /* Don't forget to refcount it - see irlap_driver_rcv(). */ 1285 skb_get(skb); 1286 self->notify.udata_indication(self->notify.instance, self, 1287 skb); 1288 } 1289} 1290#endif /* CONFIG_IRDA_ULTRA */ 1291 1292/* 1293 * Propagate status indication from LAP to LSAPs (via LMP) 1294 * This don't trigger any change of state in lap_cb, lmp_cb or lsap_cb, 1295 * and the event is stateless, therefore we can bypass both state machines 1296 * and send the event direct to the LSAP user. 1297 * Jean II 1298 */ 1299void irlmp_status_indication(struct lap_cb *self, 1300 LINK_STATUS link, LOCK_STATUS lock) 1301{ 1302 struct lsap_cb *next; 1303 struct lsap_cb *curr; 1304 1305 /* Send status_indication to all LSAPs using this link */ 1306 curr = (struct lsap_cb *) hashbin_get_first( self->lsaps); 1307 while (NULL != hashbin_find_next(self->lsaps, (long) curr, NULL, 1308 (void *) &next) ) { 1309 IRDA_ASSERT(curr->magic == LMP_LSAP_MAGIC, return;); 1310 /* 1311 * Inform service user if he has requested it 1312 */ 1313 if (curr->notify.status_indication != NULL) 1314 curr->notify.status_indication(curr->notify.instance, 1315 link, lock); 1316 else 1317 IRDA_DEBUG(2, "%s(), no handler\n", __func__); 1318 1319 curr = next; 1320 } 1321} 1322 1323/* 1324 * Receive flow control indication from LAP. 1325 * LAP want us to send it one more frame. We implement a simple round 1326 * robin scheduler between the active sockets so that we get a bit of 1327 * fairness. Note that the round robin is far from perfect, but it's 1328 * better than nothing. 1329 * We then poll the selected socket so that we can do synchronous 1330 * refilling of IrLAP (which allow to minimise the number of buffers). 1331 * Jean II 1332 */ 1333void irlmp_flow_indication(struct lap_cb *self, LOCAL_FLOW flow) 1334{ 1335 struct lsap_cb *next; 1336 struct lsap_cb *curr; 1337 int lsap_todo; 1338 1339 IRDA_ASSERT(self->magic == LMP_LAP_MAGIC, return;); 1340 IRDA_ASSERT(flow == FLOW_START, return;); 1341 1342 /* Get the number of lsap. That's the only safe way to know 1343 * that we have looped around... - Jean II */ 1344 lsap_todo = HASHBIN_GET_SIZE(self->lsaps); 1345 IRDA_DEBUG(4, "%s() : %d lsaps to scan\n", __func__, lsap_todo); 1346 1347 /* Poll lsap in order until the queue is full or until we 1348 * tried them all. 1349 * Most often, the current LSAP will have something to send, 1350 * so we will go through this loop only once. - Jean II */ 1351 while((lsap_todo--) && 1352 (IRLAP_GET_TX_QUEUE_LEN(self->irlap) < LAP_HIGH_THRESHOLD)) { 1353 /* Try to find the next lsap we should poll. */ 1354 next = self->flow_next; 1355 /* If we have no lsap, restart from first one */ 1356 if(next == NULL) 1357 next = (struct lsap_cb *) hashbin_get_first(self->lsaps); 1358 /* Verify current one and find the next one */ 1359 curr = hashbin_find_next(self->lsaps, (long) next, NULL, 1360 (void *) &self->flow_next); 1361 /* Uh-oh... Paranoia */ 1362 if(curr == NULL) 1363 break; 1364 IRDA_DEBUG(4, "%s() : curr is %p, next was %p and is now %p, still %d to go - queue len = %d\n", __func__, curr, next, self->flow_next, lsap_todo, IRLAP_GET_TX_QUEUE_LEN(self->irlap)); 1365 1366 /* Inform lsap user that it can send one more packet. */ 1367 if (curr->notify.flow_indication != NULL) 1368 curr->notify.flow_indication(curr->notify.instance, 1369 curr, flow); 1370 else 1371 IRDA_DEBUG(1, "%s(), no handler\n", __func__); 1372 } 1373} 1374 1375#if 0 1376/* 1377 * Function irlmp_hint_to_service (hint) 1378 * 1379 * Returns a list of all servics contained in the given hint bits. This 1380 * function assumes that the hint bits have the size of two bytes only 1381 */ 1382__u8 *irlmp_hint_to_service(__u8 *hint) 1383{ 1384 __u8 *service; 1385 int i = 0; 1386 1387 /* 1388 * Allocate array to store services in. 16 entries should be safe 1389 * since we currently only support 2 hint bytes 1390 */ 1391 service = kmalloc(16, GFP_ATOMIC); 1392 if (!service) { 1393 IRDA_DEBUG(1, "%s(), Unable to kmalloc!\n", __func__); 1394 return NULL; 1395 } 1396 1397 if (!hint[0]) { 1398 IRDA_DEBUG(1, "<None>\n"); 1399 kfree(service); 1400 return NULL; 1401 } 1402 if (hint[0] & HINT_PNP) 1403 IRDA_DEBUG(1, "PnP Compatible "); 1404 if (hint[0] & HINT_PDA) 1405 IRDA_DEBUG(1, "PDA/Palmtop "); 1406 if (hint[0] & HINT_COMPUTER) 1407 IRDA_DEBUG(1, "Computer "); 1408 if (hint[0] & HINT_PRINTER) { 1409 IRDA_DEBUG(1, "Printer "); 1410 service[i++] = S_PRINTER; 1411 } 1412 if (hint[0] & HINT_MODEM) 1413 IRDA_DEBUG(1, "Modem "); 1414 if (hint[0] & HINT_FAX) 1415 IRDA_DEBUG(1, "Fax "); 1416 if (hint[0] & HINT_LAN) { 1417 IRDA_DEBUG(1, "LAN Access "); 1418 service[i++] = S_LAN; 1419 } 1420 /* 1421 * Test if extension byte exists. This byte will usually be 1422 * there, but this is not really required by the standard. 1423 * (IrLMP p. 29) 1424 */ 1425 if (hint[0] & HINT_EXTENSION) { 1426 if (hint[1] & HINT_TELEPHONY) { 1427 IRDA_DEBUG(1, "Telephony "); 1428 service[i++] = S_TELEPHONY; 1429 } if (hint[1] & HINT_FILE_SERVER) 1430 IRDA_DEBUG(1, "File Server "); 1431 1432 if (hint[1] & HINT_COMM) { 1433 IRDA_DEBUG(1, "IrCOMM "); 1434 service[i++] = S_COMM; 1435 } 1436 if (hint[1] & HINT_OBEX) { 1437 IRDA_DEBUG(1, "IrOBEX "); 1438 service[i++] = S_OBEX; 1439 } 1440 } 1441 IRDA_DEBUG(1, "\n"); 1442 1443 /* So that client can be notified about any discovery */ 1444 service[i++] = S_ANY; 1445 1446 service[i] = S_END; 1447 1448 return service; 1449} 1450#endif 1451 1452static const __u16 service_hint_mapping[S_END][2] = { 1453 { HINT_PNP, 0 }, /* S_PNP */ 1454 { HINT_PDA, 0 }, /* S_PDA */ 1455 { HINT_COMPUTER, 0 }, /* S_COMPUTER */ 1456 { HINT_PRINTER, 0 }, /* S_PRINTER */ 1457 { HINT_MODEM, 0 }, /* S_MODEM */ 1458 { HINT_FAX, 0 }, /* S_FAX */ 1459 { HINT_LAN, 0 }, /* S_LAN */ 1460 { HINT_EXTENSION, HINT_TELEPHONY }, /* S_TELEPHONY */ 1461 { HINT_EXTENSION, HINT_COMM }, /* S_COMM */ 1462 { HINT_EXTENSION, HINT_OBEX }, /* S_OBEX */ 1463 { 0xFF, 0xFF }, /* S_ANY */ 1464}; 1465 1466/* 1467 * Function irlmp_service_to_hint (service) 1468 * 1469 * Converts a service type, to a hint bit 1470 * 1471 * Returns: a 16 bit hint value, with the service bit set 1472 */ 1473__u16 irlmp_service_to_hint(int service) 1474{ 1475 __u16_host_order hint; 1476 1477 hint.byte[0] = service_hint_mapping[service][0]; 1478 hint.byte[1] = service_hint_mapping[service][1]; 1479 1480 return hint.word; 1481} 1482EXPORT_SYMBOL(irlmp_service_to_hint); 1483 1484/* 1485 * Function irlmp_register_service (service) 1486 * 1487 * Register local service with IrLMP 1488 * 1489 */ 1490void *irlmp_register_service(__u16 hints) 1491{ 1492 irlmp_service_t *service; 1493 1494 IRDA_DEBUG(4, "%s(), hints = %04x\n", __func__, hints); 1495 1496 /* Make a new registration */ 1497 service = kmalloc(sizeof(irlmp_service_t), GFP_ATOMIC); 1498 if (!service) { 1499 IRDA_DEBUG(1, "%s(), Unable to kmalloc!\n", __func__); 1500 return NULL; 1501 } 1502 service->hints.word = hints; 1503 hashbin_insert(irlmp->services, (irda_queue_t *) service, 1504 (long) service, NULL); 1505 1506 irlmp->hints.word |= hints; 1507 1508 return (void *)service; 1509} 1510EXPORT_SYMBOL(irlmp_register_service); 1511 1512/* 1513 * Function irlmp_unregister_service (handle) 1514 * 1515 * Unregister service with IrLMP. 1516 * 1517 * Returns: 0 on success, -1 on error 1518 */ 1519int irlmp_unregister_service(void *handle) 1520{ 1521 irlmp_service_t *service; 1522 unsigned long flags; 1523 1524 IRDA_DEBUG(4, "%s()\n", __func__); 1525 1526 if (!handle) 1527 return -1; 1528 1529 /* Caller may call with invalid handle (it's legal) - Jean II */ 1530 service = hashbin_lock_find(irlmp->services, (long) handle, NULL); 1531 if (!service) { 1532 IRDA_DEBUG(1, "%s(), Unknown service!\n", __func__); 1533 return -1; 1534 } 1535 1536 hashbin_remove_this(irlmp->services, (irda_queue_t *) service); 1537 kfree(service); 1538 1539 /* Remove old hint bits */ 1540 irlmp->hints.word = 0; 1541 1542 /* Refresh current hint bits */ 1543 spin_lock_irqsave(&irlmp->services->hb_spinlock, flags); 1544 service = (irlmp_service_t *) hashbin_get_first(irlmp->services); 1545 while (service) { 1546 irlmp->hints.word |= service->hints.word; 1547 1548 service = (irlmp_service_t *)hashbin_get_next(irlmp->services); 1549 } 1550 spin_unlock_irqrestore(&irlmp->services->hb_spinlock, flags); 1551 return 0; 1552} 1553EXPORT_SYMBOL(irlmp_unregister_service); 1554 1555/* 1556 * Function irlmp_register_client (hint_mask, callback1, callback2) 1557 * 1558 * Register a local client with IrLMP 1559 * First callback is selective discovery (based on hints) 1560 * Second callback is for selective discovery expiries 1561 * 1562 * Returns: handle > 0 on success, 0 on error 1563 */ 1564void *irlmp_register_client(__u16 hint_mask, DISCOVERY_CALLBACK1 disco_clb, 1565 DISCOVERY_CALLBACK2 expir_clb, void *priv) 1566{ 1567 irlmp_client_t *client; 1568 1569 IRDA_DEBUG(1, "%s()\n", __func__); 1570 IRDA_ASSERT(irlmp != NULL, return NULL;); 1571 1572 /* Make a new registration */ 1573 client = kmalloc(sizeof(irlmp_client_t), GFP_ATOMIC); 1574 if (!client) { 1575 IRDA_DEBUG( 1, "%s(), Unable to kmalloc!\n", __func__); 1576 return NULL; 1577 } 1578 1579 /* Register the details */ 1580 client->hint_mask.word = hint_mask; 1581 client->disco_callback = disco_clb; 1582 client->expir_callback = expir_clb; 1583 client->priv = priv; 1584 1585 hashbin_insert(irlmp->clients, (irda_queue_t *) client, 1586 (long) client, NULL); 1587 1588 return (void *) client; 1589} 1590EXPORT_SYMBOL(irlmp_register_client); 1591 1592/* 1593 * Function irlmp_update_client (handle, hint_mask, callback1, callback2) 1594 * 1595 * Updates specified client (handle) with possibly new hint_mask and 1596 * callback 1597 * 1598 * Returns: 0 on success, -1 on error 1599 */ 1600int irlmp_update_client(void *handle, __u16 hint_mask, 1601 DISCOVERY_CALLBACK1 disco_clb, 1602 DISCOVERY_CALLBACK2 expir_clb, void *priv) 1603{ 1604 irlmp_client_t *client; 1605 1606 if (!handle) 1607 return -1; 1608 1609 client = hashbin_lock_find(irlmp->clients, (long) handle, NULL); 1610 if (!client) { 1611 IRDA_DEBUG(1, "%s(), Unknown client!\n", __func__); 1612 return -1; 1613 } 1614 1615 client->hint_mask.word = hint_mask; 1616 client->disco_callback = disco_clb; 1617 client->expir_callback = expir_clb; 1618 client->priv = priv; 1619 1620 return 0; 1621} 1622EXPORT_SYMBOL(irlmp_update_client); 1623 1624/* 1625 * Function irlmp_unregister_client (handle) 1626 * 1627 * Returns: 0 on success, -1 on error 1628 * 1629 */ 1630int irlmp_unregister_client(void *handle) 1631{ 1632 struct irlmp_client *client; 1633 1634 IRDA_DEBUG(4, "%s()\n", __func__); 1635 1636 if (!handle) 1637 return -1; 1638 1639 /* Caller may call with invalid handle (it's legal) - Jean II */ 1640 client = hashbin_lock_find(irlmp->clients, (long) handle, NULL); 1641 if (!client) { 1642 IRDA_DEBUG(1, "%s(), Unknown client!\n", __func__); 1643 return -1; 1644 } 1645 1646 IRDA_DEBUG(4, "%s(), removing client!\n", __func__); 1647 hashbin_remove_this(irlmp->clients, (irda_queue_t *) client); 1648 kfree(client); 1649 1650 return 0; 1651} 1652EXPORT_SYMBOL(irlmp_unregister_client); 1653 1654/* 1655 * Function irlmp_slsap_inuse (slsap) 1656 * 1657 * Check if the given source LSAP selector is in use 1658 * 1659 * This function is clearly not very efficient. On the mitigating side, the 1660 * stack make sure that in 99% of the cases, we are called only once 1661 * for each socket allocation. We could probably keep a bitmap 1662 * of the allocated LSAP, but I'm not sure the complexity is worth it. 1663 * Jean II 1664 */ 1665static int irlmp_slsap_inuse(__u8 slsap_sel) 1666{ 1667 struct lsap_cb *self; 1668 struct lap_cb *lap; 1669 unsigned long flags; 1670 1671 IRDA_ASSERT(irlmp != NULL, return TRUE;); 1672 IRDA_ASSERT(irlmp->magic == LMP_MAGIC, return TRUE;); 1673 IRDA_ASSERT(slsap_sel != LSAP_ANY, return TRUE;); 1674 1675 IRDA_DEBUG(4, "%s()\n", __func__); 1676 1677#ifdef CONFIG_IRDA_ULTRA 1678 /* Accept all bindings to the connectionless LSAP */ 1679 if (slsap_sel == LSAP_CONNLESS) 1680 return FALSE; 1681#endif /* CONFIG_IRDA_ULTRA */ 1682 1683 /* Valid values are between 0 and 127 (0x0-0x6F) */ 1684 if (slsap_sel > LSAP_MAX) 1685 return TRUE; 1686 1687 /* 1688 * Check if slsap is already in use. To do this we have to loop over 1689 * every IrLAP connection and check every LSAP associated with each 1690 * the connection. 1691 */ 1692 spin_lock_irqsave_nested(&irlmp->links->hb_spinlock, flags, 1693 SINGLE_DEPTH_NESTING); 1694 lap = (struct lap_cb *) hashbin_get_first(irlmp->links); 1695 while (lap != NULL) { 1696 IRDA_ASSERT(lap->magic == LMP_LAP_MAGIC, goto errlap;); 1697 1698 /* Careful for priority inversions here ! 1699 * irlmp->links is never taken while another IrDA 1700 * spinlock is held, so we are safe. Jean II */ 1701 spin_lock(&lap->lsaps->hb_spinlock); 1702 1703 /* For this IrLAP, check all the LSAPs */ 1704 self = (struct lsap_cb *) hashbin_get_first(lap->lsaps); 1705 while (self != NULL) { 1706 IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, 1707 goto errlsap;); 1708 1709 if ((self->slsap_sel == slsap_sel)) { 1710 IRDA_DEBUG(4, "Source LSAP selector=%02x in use\n", 1711 self->slsap_sel); 1712 goto errlsap; 1713 } 1714 self = (struct lsap_cb*) hashbin_get_next(lap->lsaps); 1715 } 1716 spin_unlock(&lap->lsaps->hb_spinlock); 1717 1718 /* Next LAP */ 1719 lap = (struct lap_cb *) hashbin_get_next(irlmp->links); 1720 } 1721 spin_unlock_irqrestore(&irlmp->links->hb_spinlock, flags); 1722 1723 /* 1724 * Server sockets are typically waiting for connections and 1725 * therefore reside in the unconnected list. We don't want 1726 * to give out their LSAPs for obvious reasons... 1727 * Jean II 1728 */ 1729 spin_lock_irqsave(&irlmp->unconnected_lsaps->hb_spinlock, flags); 1730 1731 self = (struct lsap_cb *) hashbin_get_first(irlmp->unconnected_lsaps); 1732 while (self != NULL) { 1733 IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, goto erruncon;); 1734 if ((self->slsap_sel == slsap_sel)) { 1735 IRDA_DEBUG(4, "Source LSAP selector=%02x in use (unconnected)\n", 1736 self->slsap_sel); 1737 goto erruncon; 1738 } 1739 self = (struct lsap_cb*) hashbin_get_next(irlmp->unconnected_lsaps); 1740 } 1741 spin_unlock_irqrestore(&irlmp->unconnected_lsaps->hb_spinlock, flags); 1742 1743 return FALSE; 1744 1745 /* Error exit from within one of the two nested loops. 1746 * Make sure we release the right spinlock in the righ order. 1747 * Jean II */ 1748errlsap: 1749 spin_unlock(&lap->lsaps->hb_spinlock); 1750IRDA_ASSERT_LABEL(errlap:) 1751 spin_unlock_irqrestore(&irlmp->links->hb_spinlock, flags); 1752 return TRUE; 1753 1754 /* Error exit from within the unconnected loop. 1755 * Just one spinlock to release... Jean II */ 1756erruncon: 1757 spin_unlock_irqrestore(&irlmp->unconnected_lsaps->hb_spinlock, flags); 1758 return TRUE; 1759} 1760 1761/* 1762 * Function irlmp_find_free_slsap () 1763 * 1764 * Find a free source LSAP to use. This function is called if the service 1765 * user has requested a source LSAP equal to LM_ANY 1766 */ 1767static __u8 irlmp_find_free_slsap(void) 1768{ 1769 __u8 lsap_sel; 1770 int wrapped = 0; 1771 1772 IRDA_ASSERT(irlmp != NULL, return -1;); 1773 IRDA_ASSERT(irlmp->magic == LMP_MAGIC, return -1;); 1774 1775 /* Most users don't really care which LSAPs they are given, 1776 * and therefore we automatically give them a free LSAP. 1777 * This function try to find a suitable LSAP, i.e. which is 1778 * not in use and is within the acceptable range. Jean II */ 1779 1780 do { 1781 /* Always increment to LSAP number before using it. 1782 * In theory, we could reuse the last LSAP number, as long 1783 * as it is no longer in use. Some IrDA stack do that. 1784 * However, the previous socket may be half closed, i.e. 1785 * we closed it, we think it's no longer in use, but the 1786 * other side did not receive our close and think it's 1787 * active and still send data on it. 1788 * This is similar to what is done with PIDs and TCP ports. 1789 * Also, this reduce the number of calls to irlmp_slsap_inuse() 1790 * which is an expensive function to call. 1791 * Jean II */ 1792 irlmp->last_lsap_sel++; 1793 1794 /* Check if we need to wraparound (0x70-0x7f are reserved) */ 1795 if (irlmp->last_lsap_sel > LSAP_MAX) { 1796 /* 0x00-0x10 are also reserved for well know ports */ 1797 irlmp->last_lsap_sel = 0x10; 1798 1799 /* Make sure we terminate the loop */ 1800 if (wrapped++) { 1801 IRDA_ERROR("%s: no more free LSAPs !\n", 1802 __func__); 1803 return 0; 1804 } 1805 } 1806 1807 /* If the LSAP is in use, try the next one. 1808 * Despite the autoincrement, we need to check if the lsap 1809 * is really in use or not, first because LSAP may be 1810 * directly allocated in irlmp_open_lsap(), and also because 1811 * we may wraparound on old sockets. Jean II */ 1812 } while (irlmp_slsap_inuse(irlmp->last_lsap_sel)); 1813 1814 /* Got it ! */ 1815 lsap_sel = irlmp->last_lsap_sel; 1816 IRDA_DEBUG(4, "%s(), found free lsap_sel=%02x\n", 1817 __func__, lsap_sel); 1818 1819 return lsap_sel; 1820} 1821 1822/* 1823 * Function irlmp_convert_lap_reason (lap_reason) 1824 * 1825 * Converts IrLAP disconnect reason codes to IrLMP disconnect reason 1826 * codes 1827 * 1828 */ 1829LM_REASON irlmp_convert_lap_reason( LAP_REASON lap_reason) 1830{ 1831 int reason = LM_LAP_DISCONNECT; 1832 1833 switch (lap_reason) { 1834 case LAP_DISC_INDICATION: /* Received a disconnect request from peer */ 1835 IRDA_DEBUG( 1, "%s(), LAP_DISC_INDICATION\n", __func__); 1836 reason = LM_USER_REQUEST; 1837 break; 1838 case LAP_NO_RESPONSE: /* To many retransmits without response */ 1839 IRDA_DEBUG( 1, "%s(), LAP_NO_RESPONSE\n", __func__); 1840 reason = LM_LAP_DISCONNECT; 1841 break; 1842 case LAP_RESET_INDICATION: 1843 IRDA_DEBUG( 1, "%s(), LAP_RESET_INDICATION\n", __func__); 1844 reason = LM_LAP_RESET; 1845 break; 1846 case LAP_FOUND_NONE: 1847 case LAP_MEDIA_BUSY: 1848 case LAP_PRIMARY_CONFLICT: 1849 IRDA_DEBUG(1, "%s(), LAP_FOUND_NONE, LAP_MEDIA_BUSY or LAP_PRIMARY_CONFLICT\n", __func__); 1850 reason = LM_CONNECT_FAILURE; 1851 break; 1852 default: 1853 IRDA_DEBUG(1, "%s(), Unknown IrLAP disconnect reason %d!\n", 1854 __func__, lap_reason); 1855 reason = LM_LAP_DISCONNECT; 1856 break; 1857 } 1858 1859 return reason; 1860} 1861 1862#ifdef CONFIG_PROC_FS 1863 1864struct irlmp_iter_state { 1865 hashbin_t *hashbin; 1866}; 1867 1868#define LSAP_START_TOKEN ((void *)1) 1869#define LINK_START_TOKEN ((void *)2) 1870 1871static void *irlmp_seq_hb_idx(struct irlmp_iter_state *iter, loff_t *off) 1872{ 1873 void *element; 1874 1875 spin_lock_irq(&iter->hashbin->hb_spinlock); 1876 for (element = hashbin_get_first(iter->hashbin); 1877 element != NULL; 1878 element = hashbin_get_next(iter->hashbin)) { 1879 if (!off || *off-- == 0) { 1880 /* NB: hashbin left locked */ 1881 return element; 1882 } 1883 } 1884 spin_unlock_irq(&iter->hashbin->hb_spinlock); 1885 iter->hashbin = NULL; 1886 return NULL; 1887} 1888 1889 1890static void *irlmp_seq_start(struct seq_file *seq, loff_t *pos) 1891{ 1892 struct irlmp_iter_state *iter = seq->private; 1893 void *v; 1894 loff_t off = *pos; 1895 1896 iter->hashbin = NULL; 1897 if (off-- == 0) 1898 return LSAP_START_TOKEN; 1899 1900 iter->hashbin = irlmp->unconnected_lsaps; 1901 v = irlmp_seq_hb_idx(iter, &off); 1902 if (v) 1903 return v; 1904 1905 if (off-- == 0) 1906 return LINK_START_TOKEN; 1907 1908 iter->hashbin = irlmp->links; 1909 return irlmp_seq_hb_idx(iter, &off); 1910} 1911 1912static void *irlmp_seq_next(struct seq_file *seq, void *v, loff_t *pos) 1913{ 1914 struct irlmp_iter_state *iter = seq->private; 1915 1916 ++*pos; 1917 1918 if (v == LSAP_START_TOKEN) { /* start of list of lsaps */ 1919 iter->hashbin = irlmp->unconnected_lsaps; 1920 v = irlmp_seq_hb_idx(iter, NULL); 1921 return v ? v : LINK_START_TOKEN; 1922 } 1923 1924 if (v == LINK_START_TOKEN) { /* start of list of links */ 1925 iter->hashbin = irlmp->links; 1926 return irlmp_seq_hb_idx(iter, NULL); 1927 } 1928 1929 v = hashbin_get_next(iter->hashbin); 1930 1931 if (v == NULL) { /* no more in this hash bin */ 1932 spin_unlock_irq(&iter->hashbin->hb_spinlock); 1933 1934 if (iter->hashbin == irlmp->unconnected_lsaps) 1935 v = LINK_START_TOKEN; 1936 1937 iter->hashbin = NULL; 1938 } 1939 return v; 1940} 1941 1942static void irlmp_seq_stop(struct seq_file *seq, void *v) 1943{ 1944 struct irlmp_iter_state *iter = seq->private; 1945 1946 if (iter->hashbin) 1947 spin_unlock_irq(&iter->hashbin->hb_spinlock); 1948} 1949 1950static int irlmp_seq_show(struct seq_file *seq, void *v) 1951{ 1952 const struct irlmp_iter_state *iter = seq->private; 1953 struct lsap_cb *self = v; 1954 1955 if (v == LSAP_START_TOKEN) 1956 seq_puts(seq, "Unconnected LSAPs:\n"); 1957 else if (v == LINK_START_TOKEN) 1958 seq_puts(seq, "\nRegistered Link Layers:\n"); 1959 else if (iter->hashbin == irlmp->unconnected_lsaps) { 1960 self = v; 1961 IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -EINVAL; ); 1962 seq_printf(seq, "lsap state: %s, ", 1963 irlsap_state[ self->lsap_state]); 1964 seq_printf(seq, 1965 "slsap_sel: %#02x, dlsap_sel: %#02x, ", 1966 self->slsap_sel, self->dlsap_sel); 1967 seq_printf(seq, "(%s)", self->notify.name); 1968 seq_printf(seq, "\n"); 1969 } else if (iter->hashbin == irlmp->links) { 1970 struct lap_cb *lap = v; 1971 1972 seq_printf(seq, "lap state: %s, ", 1973 irlmp_state[lap->lap_state]); 1974 1975 seq_printf(seq, "saddr: %#08x, daddr: %#08x, ", 1976 lap->saddr, lap->daddr); 1977 seq_printf(seq, "num lsaps: %d", 1978 HASHBIN_GET_SIZE(lap->lsaps)); 1979 seq_printf(seq, "\n"); 1980 1981 /* Careful for priority inversions here ! 1982 * All other uses of attrib spinlock are independent of 1983 * the object spinlock, so we are safe. Jean II */ 1984 spin_lock(&lap->lsaps->hb_spinlock); 1985 1986 seq_printf(seq, "\n Connected LSAPs:\n"); 1987 for (self = (struct lsap_cb *) hashbin_get_first(lap->lsaps); 1988 self != NULL; 1989 self = (struct lsap_cb *)hashbin_get_next(lap->lsaps)) { 1990 IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, 1991 goto outloop;); 1992 seq_printf(seq, " lsap state: %s, ", 1993 irlsap_state[ self->lsap_state]); 1994 seq_printf(seq, 1995 "slsap_sel: %#02x, dlsap_sel: %#02x, ", 1996 self->slsap_sel, self->dlsap_sel); 1997 seq_printf(seq, "(%s)", self->notify.name); 1998 seq_putc(seq, '\n'); 1999 2000 } 2001 IRDA_ASSERT_LABEL(outloop:) 2002 spin_unlock(&lap->lsaps->hb_spinlock); 2003 seq_putc(seq, '\n'); 2004 } else 2005 return -EINVAL; 2006 2007 return 0; 2008} 2009 2010static const struct seq_operations irlmp_seq_ops = { 2011 .start = irlmp_seq_start, 2012 .next = irlmp_seq_next, 2013 .stop = irlmp_seq_stop, 2014 .show = irlmp_seq_show, 2015}; 2016 2017static int irlmp_seq_open(struct inode *inode, struct file *file) 2018{ 2019 IRDA_ASSERT(irlmp != NULL, return -EINVAL;); 2020 2021 return seq_open_private(file, &irlmp_seq_ops, 2022 sizeof(struct irlmp_iter_state)); 2023} 2024 2025const struct file_operations irlmp_seq_fops = { 2026 .owner = THIS_MODULE, 2027 .open = irlmp_seq_open, 2028 .read = seq_read, 2029 .llseek = seq_lseek, 2030 .release = seq_release_private, 2031}; 2032 2033#endif /* PROC_FS */