st_core.c 24.8 KB
Newer Older
P
Pavan Savoy 已提交
1 2 3
/*
 *  Shared Transport Line discipline driver Core
 *	This hooks up ST KIM driver and ST LL driver
4 5
 *  Copyright (C) 2009-2010 Texas Instruments
 *  Author: Pavan Savoy <pavan_savoy@ti.com>
P
Pavan Savoy 已提交
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 2 as
 *  published by the Free Software Foundation.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#define pr_fmt(fmt)	"(stc): " fmt
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/tty.h>

27 28 29
#include <linux/seq_file.h>
#include <linux/skbuff.h>

30
#include <linux/ti_wilink_st.h>
P
Pavan Savoy 已提交
31

32 33
extern void st_kim_recv(void *, const unsigned char *, long);
void st_int_recv(void *, const unsigned char *, long);
P
Pavan Savoy 已提交
34 35 36 37
/* function pointer pointing to either,
 * st_kim_recv during registration to receive fw download responses
 * st_int_recv after registration to receive proto stack responses
 */
38
static void (*st_recv) (void *, const unsigned char *, long);
P
Pavan Savoy 已提交
39 40

/********************************************************************/
41 42
static void add_channel_to_table(struct st_data_s *st_gdata,
		struct st_proto_s *new_proto)
P
Pavan Savoy 已提交
43
{
44 45 46
	pr_info("%s: id %d\n", __func__, new_proto->chnl_id);
	/* list now has the channel id as index itself */
	st_gdata->list[new_proto->chnl_id] = new_proto;
47
	st_gdata->is_registered[new_proto->chnl_id] = true;
48 49 50 51 52 53
}

static void remove_channel_from_table(struct st_data_s *st_gdata,
		struct st_proto_s *proto)
{
	pr_info("%s: id %d\n", __func__, proto->chnl_id);
54 55
/*	st_gdata->list[proto->chnl_id] = NULL; */
	st_gdata->is_registered[proto->chnl_id] = false;
P
Pavan Savoy 已提交
56
}
57

58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
/*
 * called from KIM during firmware download.
 *
 * This is a wrapper function to tty->ops->write_room.
 * It returns number of free space available in
 * uart tx buffer.
 */
int st_get_uart_wr_room(struct st_data_s *st_gdata)
{
	struct tty_struct *tty;
	if (unlikely(st_gdata == NULL || st_gdata->tty == NULL)) {
		pr_err("tty unavailable to perform write");
		return -1;
	}
	tty = st_gdata->tty;
	return tty->ops->write_room(tty);
}

P
Pavan Savoy 已提交
76 77 78 79 80 81 82 83 84 85 86 87 88
/* can be called in from
 * -- KIM (during fw download)
 * -- ST Core (during st_write)
 *
 *  This is the internal write function - a wrapper
 *  to tty->ops->write
 */
int st_int_write(struct st_data_s *st_gdata,
	const unsigned char *data, int count)
{
	struct tty_struct *tty;
	if (unlikely(st_gdata == NULL || st_gdata->tty == NULL)) {
		pr_err("tty unavailable to perform write");
89
		return -EINVAL;
P
Pavan Savoy 已提交
90 91 92
	}
	tty = st_gdata->tty;
#ifdef VERBOSE
93 94
	print_hex_dump(KERN_DEBUG, "<out<", DUMP_PREFIX_NONE,
		16, 1, data, count, 0);
P
Pavan Savoy 已提交
95 96 97 98 99 100 101 102 103
#endif
	return tty->ops->write(tty, data, count);

}

/*
 * push the skb received to relevant
 * protocol stacks
 */
104
static void st_send_frame(unsigned char chnl_id, struct st_data_s *st_gdata)
P
Pavan Savoy 已提交
105
{
106
	pr_debug(" %s(prot:%d) ", __func__, chnl_id);
P
Pavan Savoy 已提交
107 108 109

	if (unlikely
	    (st_gdata == NULL || st_gdata->rx_skb == NULL
110
	     || st_gdata->is_registered[chnl_id] == false)) {
111 112
		pr_err("chnl_id %d not registered, no data to send?",
			   chnl_id);
P
Pavan Savoy 已提交
113 114 115 116 117 118 119 120
		kfree_skb(st_gdata->rx_skb);
		return;
	}
	/* this cannot fail
	 * this shouldn't take long
	 * - should be just skb_queue_tail for the
	 *   protocol stack driver
	 */
121
	if (likely(st_gdata->list[chnl_id]->recv != NULL)) {
122
		if (unlikely
123 124
			(st_gdata->list[chnl_id]->recv
			(st_gdata->list[chnl_id]->priv_data, st_gdata->rx_skb)
125
			     != 0)) {
126
			pr_err(" proto stack %d's ->recv failed", chnl_id);
P
Pavan Savoy 已提交
127 128 129 130
			kfree_skb(st_gdata->rx_skb);
			return;
		}
	} else {
131
		pr_err(" proto stack %d's ->recv null", chnl_id);
P
Pavan Savoy 已提交
132 133 134 135 136
		kfree_skb(st_gdata->rx_skb);
	}
	return;
}

137 138
/**
 * st_reg_complete -
P
Pavan Savoy 已提交
139 140
 * to call registration complete callbacks
 * of all protocol stack drivers
141 142
 * This function is being called with spin lock held, protocol drivers are
 * only expected to complete their waits and do nothing more than that.
P
Pavan Savoy 已提交
143
 */
144
static void st_reg_complete(struct st_data_s *st_gdata, char err)
P
Pavan Savoy 已提交
145 146 147
{
	unsigned char i = 0;
	pr_info(" %s ", __func__);
148
	for (i = 0; i < ST_MAX_CHANNELS; i++) {
149 150 151
		if (likely(st_gdata != NULL &&
			st_gdata->is_registered[i] == true &&
				st_gdata->list[i]->reg_complete_cb != NULL)) {
152 153
			st_gdata->list[i]->reg_complete_cb
				(st_gdata->list[i]->priv_data, err);
154 155
			pr_info("protocol %d's cb sent %d\n", i, err);
			if (err) { /* cleanup registered protocol */
156
				st_gdata->is_registered[i] = false;
157 158
				if (st_gdata->protos_registered)
					st_gdata->protos_registered--;
159 160
			}
		}
P
Pavan Savoy 已提交
161 162 163 164
	}
}

static inline int st_check_data_len(struct st_data_s *st_gdata,
165
	unsigned char chnl_id, int len)
P
Pavan Savoy 已提交
166
{
167
	int room = skb_tailroom(st_gdata->rx_skb);
P
Pavan Savoy 已提交
168

169
	pr_debug("len %d room %d", len, room);
P
Pavan Savoy 已提交
170 171 172 173 174 175

	if (!len) {
		/* Received packet has only packet header and
		 * has zero length payload. So, ask ST CORE to
		 * forward the packet to protocol driver (BT/FM/GPS)
		 */
176
		st_send_frame(chnl_id, st_gdata);
P
Pavan Savoy 已提交
177 178 179 180 181 182 183 184 185 186 187 188

	} else if (len > room) {
		/* Received packet's payload length is larger.
		 * We can't accommodate it in created skb.
		 */
		pr_err("Data length is too large len %d room %d", len,
			   room);
		kfree_skb(st_gdata->rx_skb);
	} else {
		/* Packet header has non-zero payload length and
		 * we have enough space in created skb. Lets read
		 * payload data */
189
		st_gdata->rx_state = ST_W4_DATA;
P
Pavan Savoy 已提交
190 191 192 193 194 195 196 197 198
		st_gdata->rx_count = len;
		return len;
	}

	/* Change ST state to continue to process next
	 * packet */
	st_gdata->rx_state = ST_W4_PACKET_TYPE;
	st_gdata->rx_skb = NULL;
	st_gdata->rx_count = 0;
199
	st_gdata->rx_chnl = 0;
P
Pavan Savoy 已提交
200 201 202 203

	return 0;
}

204 205 206
/**
 * st_wakeup_ack - internal function for action when wake-up ack
 *	received
P
Pavan Savoy 已提交
207 208 209 210
 */
static inline void st_wakeup_ack(struct st_data_s *st_gdata,
	unsigned char cmd)
{
211
	struct sk_buff *waiting_skb;
P
Pavan Savoy 已提交
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
	unsigned long flags = 0;

	spin_lock_irqsave(&st_gdata->lock, flags);
	/* de-Q from waitQ and Q in txQ now that the
	 * chip is awake
	 */
	while ((waiting_skb = skb_dequeue(&st_gdata->tx_waitq)))
		skb_queue_tail(&st_gdata->txq, waiting_skb);

	/* state forwarded to ST LL */
	st_ll_sleep_state(st_gdata, (unsigned long)cmd);
	spin_unlock_irqrestore(&st_gdata->lock, flags);

	/* wake up to send the recently copied skbs from waitQ */
	st_tx_wakeup(st_gdata);
}

229 230 231 232 233 234 235
/**
 * st_int_recv - ST's internal receive function.
 *	Decodes received RAW data and forwards to corresponding
 *	client drivers (Bluetooth,FM,GPS..etc).
 *	This can receive various types of packets,
 *	HCI-Events, ACL, SCO, 4 types of HCI-LL PM packets
 *	CH-8 packets from FM, CH-9 packets from GPS cores.
P
Pavan Savoy 已提交
236 237 238 239
 */
void st_int_recv(void *disc_data,
	const unsigned char *data, long count)
{
240
	char *ptr;
241 242
	struct st_proto_s *proto;
	unsigned short payload_len = 0;
243 244
	int len = 0;
	unsigned char type = 0;
245
	unsigned char *plen;
P
Pavan Savoy 已提交
246
	struct st_data_s *st_gdata = (struct st_data_s *)disc_data;
247
	unsigned long flags;
P
Pavan Savoy 已提交
248 249 250 251 252 253 254 255

	ptr = (char *)data;
	/* tty_receive sent null ? */
	if (unlikely(ptr == NULL) || (st_gdata == NULL)) {
		pr_err(" received null from TTY ");
		return;
	}

256
	pr_debug("count %ld rx_state %ld"
P
Pavan Savoy 已提交
257 258 259
		   "rx_count %ld", count, st_gdata->rx_state,
		   st_gdata->rx_count);

260
	spin_lock_irqsave(&st_gdata->lock, flags);
P
Pavan Savoy 已提交
261 262 263 264 265 266 267 268 269 270 271 272 273 274
	/* Decode received bytes here */
	while (count) {
		if (st_gdata->rx_count) {
			len = min_t(unsigned int, st_gdata->rx_count, count);
			memcpy(skb_put(st_gdata->rx_skb, len), ptr, len);
			st_gdata->rx_count -= len;
			count -= len;
			ptr += len;

			if (st_gdata->rx_count)
				continue;

			/* Check ST RX state machine , where are we? */
			switch (st_gdata->rx_state) {
275 276
			/* Waiting for complete packet ? */
			case ST_W4_DATA:
277
				pr_debug("Complete pkt received");
P
Pavan Savoy 已提交
278 279
				/* Ask ST CORE to forward
				 * the packet to protocol driver */
280
				st_send_frame(st_gdata->rx_chnl, st_gdata);
P
Pavan Savoy 已提交
281 282 283 284

				st_gdata->rx_state = ST_W4_PACKET_TYPE;
				st_gdata->rx_skb = NULL;
				continue;
285 286 287 288 289 290
			/* parse the header to know details */
			case ST_W4_HEADER:
				proto = st_gdata->list[st_gdata->rx_chnl];
				plen =
				&st_gdata->rx_skb->data
				[proto->offset_len_in_hdr];
291
				pr_debug("plen pointing to %x\n", *plen);
292 293 294 295 296 297 298 299 300 301 302
				if (proto->len_size == 1)/* 1 byte len field */
					payload_len = *(unsigned char *)plen;
				else if (proto->len_size == 2)
					payload_len =
					__le16_to_cpu(*(unsigned short *)plen);
				else
					pr_info("%s: invalid length "
					"for id %d\n",
					__func__, proto->chnl_id);
				st_check_data_len(st_gdata, proto->chnl_id,
						payload_len);
303
				pr_debug("off %d, pay len %d\n",
304
					proto->offset_len_in_hdr, payload_len);
P
Pavan Savoy 已提交
305 306 307 308 309 310 311 312 313 314 315
				continue;
			}	/* end of switch rx_state */
		}

		/* end of if rx_count */
		/* Check first byte of packet and identify module
		 * owner (BT/FM/GPS) */
		switch (*ptr) {
		case LL_SLEEP_IND:
		case LL_SLEEP_ACK:
		case LL_WAKE_UP_IND:
316
			pr_debug("PM packet");
P
Pavan Savoy 已提交
317 318 319 320
			/* this takes appropriate action based on
			 * sleep state received --
			 */
			st_ll_sleep_state(st_gdata, *ptr);
321 322 323 324 325 326 327 328
			/* if WAKEUP_IND collides copy from waitq to txq
			 * and assume chip awake
			 */
			spin_unlock_irqrestore(&st_gdata->lock, flags);
			if (st_ll_getstate(st_gdata) == ST_LL_AWAKE)
				st_wakeup_ack(st_gdata, LL_WAKE_UP_ACK);
			spin_lock_irqsave(&st_gdata->lock, flags);

P
Pavan Savoy 已提交
329 330 331 332
			ptr++;
			count--;
			continue;
		case LL_WAKE_UP_ACK:
333
			pr_debug("PM packet");
334 335

			spin_unlock_irqrestore(&st_gdata->lock, flags);
P
Pavan Savoy 已提交
336 337
			/* wake up ack received */
			st_wakeup_ack(st_gdata, *ptr);
338 339
			spin_lock_irqsave(&st_gdata->lock, flags);

P
Pavan Savoy 已提交
340 341 342 343 344
			ptr++;
			count--;
			continue;
			/* Unknow packet? */
		default:
345
			type = *ptr;
346

347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363
			/* Default case means non-HCILL packets,
			 * possibilities are packets for:
			 * (a) valid protocol -  Supported Protocols within
			 *     the ST_MAX_CHANNELS.
			 * (b) registered protocol - Checked by
			 *     "st_gdata->list[type] == NULL)" are supported
			 *     protocols only.
			 *  Rules out any invalid protocol and
			 *  unregistered protocols with channel ID < 16.
			 */

			if ((type >= ST_MAX_CHANNELS) ||
					(st_gdata->list[type] == NULL)) {
				pr_err("chip/interface misbehavior: "
						"dropping frame starting "
						"with 0x%02x\n", type);
				goto done;
364
			}
365

366 367 368
			st_gdata->rx_skb = alloc_skb(
					st_gdata->list[type]->max_frame_size,
					GFP_ATOMIC);
369 370 371 372 373
			if (st_gdata->rx_skb == NULL) {
				pr_err("out of memory: dropping\n");
				goto done;
			}

374 375 376 377 378 379 380 381
			skb_reserve(st_gdata->rx_skb,
					st_gdata->list[type]->reserve);
			/* next 2 required for BT only */
			st_gdata->rx_skb->cb[0] = type; /*pkt_type*/
			st_gdata->rx_skb->cb[1] = 0; /*incoming*/
			st_gdata->rx_chnl = *ptr;
			st_gdata->rx_state = ST_W4_HEADER;
			st_gdata->rx_count = st_gdata->list[type]->hdr_len;
382
			pr_debug("rx_count %ld\n", st_gdata->rx_count);
P
Pavan Savoy 已提交
383 384 385 386
		};
		ptr++;
		count--;
	}
387
done:
388
	spin_unlock_irqrestore(&st_gdata->lock, flags);
389
	pr_debug("done %s", __func__);
P
Pavan Savoy 已提交
390 391 392
	return;
}

393 394 395 396 397
/**
 * st_int_dequeue - internal de-Q function.
 *	If the previous data set was not written
 *	completely, return that skb which has the pending data.
 *	In normal cases, return top of txq.
P
Pavan Savoy 已提交
398
 */
399
static struct sk_buff *st_int_dequeue(struct st_data_s *st_gdata)
P
Pavan Savoy 已提交
400 401 402
{
	struct sk_buff *returning_skb;

403
	pr_debug("%s", __func__);
P
Pavan Savoy 已提交
404 405 406 407 408 409 410 411
	if (st_gdata->tx_skb != NULL) {
		returning_skb = st_gdata->tx_skb;
		st_gdata->tx_skb = NULL;
		return returning_skb;
	}
	return skb_dequeue(&st_gdata->txq);
}

412 413 414 415 416 417 418 419
/**
 * st_int_enqueue - internal Q-ing function.
 *	Will either Q the skb to txq or the tx_waitq
 *	depending on the ST LL state.
 *	If the chip is asleep, then Q it onto waitq and
 *	wakeup the chip.
 *	txq and waitq needs protection since the other contexts
 *	may be sending data, waking up chip.
P
Pavan Savoy 已提交
420
 */
421
static void st_int_enqueue(struct st_data_s *st_gdata, struct sk_buff *skb)
P
Pavan Savoy 已提交
422 423 424
{
	unsigned long flags = 0;

425
	pr_debug("%s", __func__);
P
Pavan Savoy 已提交
426 427 428 429
	spin_lock_irqsave(&st_gdata->lock, flags);

	switch (st_ll_getstate(st_gdata)) {
	case ST_LL_AWAKE:
430
		pr_debug("ST LL is AWAKE, sending normally");
P
Pavan Savoy 已提交
431 432 433 434 435
		skb_queue_tail(&st_gdata->txq, skb);
		break;
	case ST_LL_ASLEEP_TO_AWAKE:
		skb_queue_tail(&st_gdata->tx_waitq, skb);
		break;
436
	case ST_LL_AWAKE_TO_ASLEEP:
P
Pavan Savoy 已提交
437 438 439 440 441 442 443 444 445 446 447 448 449 450
		pr_err("ST LL is illegal state(%ld),"
			   "purging received skb.", st_ll_getstate(st_gdata));
		kfree_skb(skb);
		break;
	case ST_LL_ASLEEP:
		skb_queue_tail(&st_gdata->tx_waitq, skb);
		st_ll_wakeup(st_gdata);
		break;
	default:
		pr_err("ST LL is illegal state(%ld),"
			   "purging received skb.", st_ll_getstate(st_gdata));
		kfree_skb(skb);
		break;
	}
451

P
Pavan Savoy 已提交
452
	spin_unlock_irqrestore(&st_gdata->lock, flags);
453
	pr_debug("done %s", __func__);
P
Pavan Savoy 已提交
454 455 456 457 458 459 460 461 462
	return;
}

/*
 * internal wakeup function
 * called from either
 * - TTY layer when write's finished
 * - st_write (in context of the protocol stack)
 */
463 464 465 466 467 468 469
static void work_fn_write_wakeup(struct work_struct *work)
{
	struct st_data_s *st_gdata = container_of(work, struct st_data_s,
			work_write_wakeup);

	st_tx_wakeup((void *)st_gdata);
}
P
Pavan Savoy 已提交
470 471 472 473
void st_tx_wakeup(struct st_data_s *st_data)
{
	struct sk_buff *skb;
	unsigned long flags;	/* for irq save flags */
474
	pr_debug("%s", __func__);
P
Pavan Savoy 已提交
475 476
	/* check for sending & set flag sending here */
	if (test_and_set_bit(ST_TX_SENDING, &st_data->tx_state)) {
477
		pr_debug("ST already sending");
P
Pavan Savoy 已提交
478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514
		/* keep sending */
		set_bit(ST_TX_WAKEUP, &st_data->tx_state);
		return;
		/* TX_WAKEUP will be checked in another
		 * context
		 */
	}
	do {			/* come back if st_tx_wakeup is set */
		/* woke-up to write */
		clear_bit(ST_TX_WAKEUP, &st_data->tx_state);
		while ((skb = st_int_dequeue(st_data))) {
			int len;
			spin_lock_irqsave(&st_data->lock, flags);
			/* enable wake-up from TTY */
			set_bit(TTY_DO_WRITE_WAKEUP, &st_data->tty->flags);
			len = st_int_write(st_data, skb->data, skb->len);
			skb_pull(skb, len);
			/* if skb->len = len as expected, skb->len=0 */
			if (skb->len) {
				/* would be the next skb to be sent */
				st_data->tx_skb = skb;
				spin_unlock_irqrestore(&st_data->lock, flags);
				break;
			}
			kfree_skb(skb);
			spin_unlock_irqrestore(&st_data->lock, flags);
		}
		/* if wake-up is set in another context- restart sending */
	} while (test_bit(ST_TX_WAKEUP, &st_data->tx_state));

	/* clear flag sending */
	clear_bit(ST_TX_SENDING, &st_data->tx_state);
}

/********************************************************************/
/* functions called from ST KIM
*/
515
void kim_st_list_protocols(struct st_data_s *st_gdata, void *buf)
P
Pavan Savoy 已提交
516
{
517
	seq_printf(buf, "[%d]\nBT=%c\nFM=%c\nGPS=%c\n",
518
			st_gdata->protos_registered,
519 520 521
			st_gdata->is_registered[0x04] == true ? 'R' : 'U',
			st_gdata->is_registered[0x08] == true ? 'R' : 'U',
			st_gdata->is_registered[0x09] == true ? 'R' : 'U');
P
Pavan Savoy 已提交
522 523 524 525 526 527 528 529 530 531
}

/********************************************************************/
/*
 * functions called from protocol stack drivers
 * to be EXPORT-ed
 */
long st_register(struct st_proto_s *new_proto)
{
	struct st_data_s	*st_gdata;
532
	long err = 0;
P
Pavan Savoy 已提交
533 534
	unsigned long flags = 0;

535
	st_kim_ref(&st_gdata, 0);
P
Pavan Savoy 已提交
536 537 538
	if (st_gdata == NULL || new_proto == NULL || new_proto->recv == NULL
	    || new_proto->reg_complete_cb == NULL) {
		pr_err("gdata/new_proto/recv or reg_complete_cb not ready");
539
		return -EINVAL;
P
Pavan Savoy 已提交
540 541
	}

542 543
	if (new_proto->chnl_id >= ST_MAX_CHANNELS) {
		pr_err("chnl_id %d not supported", new_proto->chnl_id);
544
		return -EPROTONOSUPPORT;
P
Pavan Savoy 已提交
545 546
	}

547
	if (st_gdata->is_registered[new_proto->chnl_id] == true) {
548
		pr_err("chnl_id %d already registered", new_proto->chnl_id);
549
		return -EALREADY;
P
Pavan Savoy 已提交
550 551 552 553 554 555
	}

	/* can be from process context only */
	spin_lock_irqsave(&st_gdata->lock, flags);

	if (test_bit(ST_REG_IN_PROGRESS, &st_gdata->st_state)) {
556
		pr_info(" ST_REG_IN_PROGRESS:%d ", new_proto->chnl_id);
P
Pavan Savoy 已提交
557 558
		/* fw download in progress */

559
		add_channel_to_table(st_gdata, new_proto);
560
		st_gdata->protos_registered++;
P
Pavan Savoy 已提交
561 562 563 564
		new_proto->write = st_write;

		set_bit(ST_REG_PENDING, &st_gdata->st_state);
		spin_unlock_irqrestore(&st_gdata->lock, flags);
565
		return -EINPROGRESS;
P
Pavan Savoy 已提交
566
	} else if (st_gdata->protos_registered == ST_EMPTY) {
567
		pr_info(" chnl_id list empty :%d ", new_proto->chnl_id);
P
Pavan Savoy 已提交
568 569 570
		set_bit(ST_REG_IN_PROGRESS, &st_gdata->st_state);
		st_recv = st_kim_recv;

571 572 573
		/* enable the ST LL - to set default chip state */
		st_ll_enable(st_gdata);

P
Pavan Savoy 已提交
574 575 576 577 578 579
		/* release lock previously held - re-locked below */
		spin_unlock_irqrestore(&st_gdata->lock, flags);

		/* this may take a while to complete
		 * since it involves BT fw download
		 */
580
		err = st_kim_start(st_gdata->kim_data);
581
		if (err != 0) {
P
Pavan Savoy 已提交
582 583 584 585
			clear_bit(ST_REG_IN_PROGRESS, &st_gdata->st_state);
			if ((st_gdata->protos_registered != ST_EMPTY) &&
			    (test_bit(ST_REG_PENDING, &st_gdata->st_state))) {
				pr_err(" KIM failure complete callback ");
586
				spin_lock_irqsave(&st_gdata->lock, flags);
587
				st_reg_complete(st_gdata, err);
588
				spin_unlock_irqrestore(&st_gdata->lock, flags);
589
				clear_bit(ST_REG_PENDING, &st_gdata->st_state);
P
Pavan Savoy 已提交
590
			}
591
			return -EINVAL;
P
Pavan Savoy 已提交
592 593
		}

594 595
		spin_lock_irqsave(&st_gdata->lock, flags);

P
Pavan Savoy 已提交
596 597 598 599 600 601 602 603
		clear_bit(ST_REG_IN_PROGRESS, &st_gdata->st_state);
		st_recv = st_int_recv;

		/* this is where all pending registration
		 * are signalled to be complete by calling callback functions
		 */
		if ((st_gdata->protos_registered != ST_EMPTY) &&
		    (test_bit(ST_REG_PENDING, &st_gdata->st_state))) {
604
			pr_debug(" call reg complete callback ");
605
			st_reg_complete(st_gdata, 0);
P
Pavan Savoy 已提交
606 607 608 609 610 611
		}
		clear_bit(ST_REG_PENDING, &st_gdata->st_state);

		/* check for already registered once more,
		 * since the above check is old
		 */
612
		if (st_gdata->is_registered[new_proto->chnl_id] == true) {
P
Pavan Savoy 已提交
613
			pr_err(" proto %d already registered ",
614
				   new_proto->chnl_id);
615
			spin_unlock_irqrestore(&st_gdata->lock, flags);
616
			return -EALREADY;
P
Pavan Savoy 已提交
617 618
		}

619
		add_channel_to_table(st_gdata, new_proto);
620
		st_gdata->protos_registered++;
P
Pavan Savoy 已提交
621 622 623 624 625 626
		new_proto->write = st_write;
		spin_unlock_irqrestore(&st_gdata->lock, flags);
		return err;
	}
	/* if fw is already downloaded & new stack registers protocol */
	else {
627
		add_channel_to_table(st_gdata, new_proto);
628
		st_gdata->protos_registered++;
P
Pavan Savoy 已提交
629 630 631 632 633 634 635 636 637 638 639 640
		new_proto->write = st_write;

		/* lock already held before entering else */
		spin_unlock_irqrestore(&st_gdata->lock, flags);
		return err;
	}
}
EXPORT_SYMBOL_GPL(st_register);

/* to unregister a protocol -
 * to be called from protocol stack driver
 */
641
long st_unregister(struct st_proto_s *proto)
P
Pavan Savoy 已提交
642
{
643
	long err = 0;
P
Pavan Savoy 已提交
644 645 646
	unsigned long flags = 0;
	struct st_data_s	*st_gdata;

647
	pr_debug("%s: %d ", __func__, proto->chnl_id);
P
Pavan Savoy 已提交
648

649
	st_kim_ref(&st_gdata, 0);
650
	if (!st_gdata || proto->chnl_id >= ST_MAX_CHANNELS) {
651
		pr_err(" chnl_id %d not supported", proto->chnl_id);
652
		return -EPROTONOSUPPORT;
P
Pavan Savoy 已提交
653 654 655 656
	}

	spin_lock_irqsave(&st_gdata->lock, flags);

657
	if (st_gdata->is_registered[proto->chnl_id] == false) {
658
		pr_err(" chnl_id %d not registered", proto->chnl_id);
P
Pavan Savoy 已提交
659
		spin_unlock_irqrestore(&st_gdata->lock, flags);
660
		return -EPROTONOSUPPORT;
P
Pavan Savoy 已提交
661 662
	}

663 664 665
	if (st_gdata->protos_registered)
		st_gdata->protos_registered--;

666
	remove_channel_from_table(st_gdata, proto);
P
Pavan Savoy 已提交
667 668 669 670
	spin_unlock_irqrestore(&st_gdata->lock, flags);

	if ((st_gdata->protos_registered == ST_EMPTY) &&
	    (!test_bit(ST_REG_PENDING, &st_gdata->st_state))) {
671
		pr_info(" all chnl_ids unregistered ");
P
Pavan Savoy 已提交
672 673 674 675 676 677 678

		/* stop traffic on tty */
		if (st_gdata->tty) {
			tty_ldisc_flush(st_gdata->tty);
			stop_tty(st_gdata->tty);
		}

679
		/* all chnl_ids now unregistered */
680
		st_kim_stop(st_gdata->kim_data);
P
Pavan Savoy 已提交
681 682 683 684 685 686 687 688 689 690 691 692 693 694 695
		/* disable ST LL */
		st_ll_disable(st_gdata);
	}
	return err;
}

/*
 * called in protocol stack drivers
 * via the write function pointer
 */
long st_write(struct sk_buff *skb)
{
	struct st_data_s *st_gdata;
	long len;

696
	st_kim_ref(&st_gdata, 0);
P
Pavan Savoy 已提交
697 698 699
	if (unlikely(skb == NULL || st_gdata == NULL
		|| st_gdata->tty == NULL)) {
		pr_err("data/tty unavailable to perform write");
700
		return -EINVAL;
P
Pavan Savoy 已提交
701
	}
702

703
	pr_debug("%d to be written", skb->len);
P
Pavan Savoy 已提交
704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723
	len = skb->len;

	/* st_ll to decide where to enqueue the skb */
	st_int_enqueue(st_gdata, skb);
	/* wake up */
	st_tx_wakeup(st_gdata);

	/* return number of bytes written */
	return len;
}

/* for protocols making use of shared transport */
EXPORT_SYMBOL_GPL(st_unregister);

/********************************************************************/
/*
 * functions called from TTY layer
 */
static int st_tty_open(struct tty_struct *tty)
{
724
	int err = 0;
P
Pavan Savoy 已提交
725 726 727
	struct st_data_s *st_gdata;
	pr_info("%s ", __func__);

728
	st_kim_ref(&st_gdata, 0);
P
Pavan Savoy 已提交
729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744
	st_gdata->tty = tty;
	tty->disc_data = st_gdata;

	/* don't do an wakeup for now */
	clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);

	/* mem already allocated
	 */
	tty->receive_room = 65536;
	/* Flush any pending characters in the driver and discipline. */
	tty_ldisc_flush(tty);
	tty_driver_flush_buffer(tty);
	/*
	 * signal to UIM via KIM that -
	 * installation of N_TI_WL ldisc is complete
	 */
745
	st_kim_complete(st_gdata->kim_data);
746
	pr_debug("done %s", __func__);
P
Pavan Savoy 已提交
747 748 749 750 751
	return err;
}

static void st_tty_close(struct tty_struct *tty)
{
752
	unsigned char i = ST_MAX_CHANNELS;
P
Pavan Savoy 已提交
753 754 755 756 757 758 759 760 761 762
	unsigned long flags = 0;
	struct	st_data_s *st_gdata = tty->disc_data;

	pr_info("%s ", __func__);

	/* TODO:
	 * if a protocol has been registered & line discipline
	 * un-installed for some reason - what should be done ?
	 */
	spin_lock_irqsave(&st_gdata->lock, flags);
763
	for (i = ST_BT; i < ST_MAX_CHANNELS; i++) {
764
		if (st_gdata->is_registered[i] == true)
P
Pavan Savoy 已提交
765 766
			pr_err("%d not un-registered", i);
		st_gdata->list[i] = NULL;
767
		st_gdata->is_registered[i] = false;
P
Pavan Savoy 已提交
768
	}
769
	st_gdata->protos_registered = 0;
P
Pavan Savoy 已提交
770 771 772 773 774
	spin_unlock_irqrestore(&st_gdata->lock, flags);
	/*
	 * signal to UIM via KIM that -
	 * N_TI_WL ldisc is un-installed
	 */
775
	st_kim_complete(st_gdata->kim_data);
P
Pavan Savoy 已提交
776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791
	st_gdata->tty = NULL;
	/* Flush any pending characters in the driver and discipline. */
	tty_ldisc_flush(tty);
	tty_driver_flush_buffer(tty);

	spin_lock_irqsave(&st_gdata->lock, flags);
	/* empty out txq and tx_waitq */
	skb_queue_purge(&st_gdata->txq);
	skb_queue_purge(&st_gdata->tx_waitq);
	/* reset the TTY Rx states of ST */
	st_gdata->rx_count = 0;
	st_gdata->rx_state = ST_W4_PACKET_TYPE;
	kfree_skb(st_gdata->rx_skb);
	st_gdata->rx_skb = NULL;
	spin_unlock_irqrestore(&st_gdata->lock, flags);

792
	pr_debug("%s: done ", __func__);
P
Pavan Savoy 已提交
793 794
}

795 796
static void st_tty_receive(struct tty_struct *tty, const unsigned char *data,
			   char *tty_flags, int count)
P
Pavan Savoy 已提交
797 798
{
#ifdef VERBOSE
799 800
	print_hex_dump(KERN_DEBUG, ">in>", DUMP_PREFIX_NONE,
		16, 1, data, count, 0);
P
Pavan Savoy 已提交
801 802 803 804 805 806 807
#endif

	/*
	 * if fw download is in progress then route incoming data
	 * to KIM for validation
	 */
	st_recv(tty->disc_data, data, count);
808
	pr_debug("done %s", __func__);
P
Pavan Savoy 已提交
809 810 811 812 813 814 815 816
}

/* wake-up function called in from the TTY layer
 * inside the internal wakeup function will be called
 */
static void st_tty_wakeup(struct tty_struct *tty)
{
	struct	st_data_s *st_gdata = tty->disc_data;
817
	pr_debug("%s ", __func__);
P
Pavan Savoy 已提交
818 819 820
	/* don't do an wakeup for now */
	clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);

821 822 823 824 825 826
	/*
	 * schedule the internal wakeup instead of calling directly to
	 * avoid lockup (port->lock needed in tty->ops->write is
	 * already taken here
	 */
	schedule_work(&st_gdata->work_write_wakeup);
P
Pavan Savoy 已提交
827 828 829 830 831
}

static void st_tty_flush_buffer(struct tty_struct *tty)
{
	struct	st_data_s *st_gdata = tty->disc_data;
832
	pr_debug("%s ", __func__);
P
Pavan Savoy 已提交
833 834 835 836

	kfree_skb(st_gdata->tx_skb);
	st_gdata->tx_skb = NULL;

837
	tty_driver_flush_buffer(tty);
P
Pavan Savoy 已提交
838 839 840
	return;
}

841 842 843 844 845 846 847 848 849 850 851
static struct tty_ldisc_ops st_ldisc_ops = {
	.magic = TTY_LDISC_MAGIC,
	.name = "n_st",
	.open = st_tty_open,
	.close = st_tty_close,
	.receive_buf = st_tty_receive,
	.write_wakeup = st_tty_wakeup,
	.flush_buffer = st_tty_flush_buffer,
	.owner = THIS_MODULE
};

P
Pavan Savoy 已提交
852 853 854 855 856 857
/********************************************************************/
int st_core_init(struct st_data_s **core_data)
{
	struct st_data_s *st_gdata;
	long err;

858
	err = tty_register_ldisc(N_TI_WL, &st_ldisc_ops);
P
Pavan Savoy 已提交
859 860 861 862 863
	if (err) {
		pr_err("error registering %d line discipline %ld",
			   N_TI_WL, err);
		return err;
	}
864
	pr_debug("registered n_shared line discipline");
P
Pavan Savoy 已提交
865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891

	st_gdata = kzalloc(sizeof(struct st_data_s), GFP_KERNEL);
	if (!st_gdata) {
		pr_err("memory allocation failed");
		err = tty_unregister_ldisc(N_TI_WL);
		if (err)
			pr_err("unable to un-register ldisc %ld", err);
		err = -ENOMEM;
		return err;
	}

	/* Initialize ST TxQ and Tx waitQ queue head. All BT/FM/GPS module skb's
	 * will be pushed in this queue for actual transmission.
	 */
	skb_queue_head_init(&st_gdata->txq);
	skb_queue_head_init(&st_gdata->tx_waitq);

	/* Locking used in st_int_enqueue() to avoid multiple execution */
	spin_lock_init(&st_gdata->lock);

	err = st_ll_init(st_gdata);
	if (err) {
		pr_err("error during st_ll initialization(%ld)", err);
		kfree(st_gdata);
		err = tty_unregister_ldisc(N_TI_WL);
		if (err)
			pr_err("unable to un-register ldisc");
892
		return err;
P
Pavan Savoy 已提交
893
	}
894 895 896

	INIT_WORK(&st_gdata->work_write_wakeup, work_fn_write_wakeup);

P
Pavan Savoy 已提交
897 898 899 900 901 902 903 904 905 906 907
	*core_data = st_gdata;
	return 0;
}

void st_core_exit(struct st_data_s *st_gdata)
{
	long err;
	/* internal module cleanup */
	err = st_ll_deinit(st_gdata);
	if (err)
		pr_err("error during deinit of ST LL %ld", err);
908

P
Pavan Savoy 已提交
909 910 911 912 913 914 915 916 917 918 919 920 921 922
	if (st_gdata != NULL) {
		/* Free ST Tx Qs and skbs */
		skb_queue_purge(&st_gdata->txq);
		skb_queue_purge(&st_gdata->tx_waitq);
		kfree_skb(st_gdata->rx_skb);
		kfree_skb(st_gdata->tx_skb);
		/* TTY ldisc cleanup */
		err = tty_unregister_ldisc(N_TI_WL);
		if (err)
			pr_err("unable to un-register ldisc %ld", err);
		/* free the global data pointer */
		kfree(st_gdata);
	}
}