st_core.c 23.2 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 27
 *
 *  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/init.h>
#include <linux/tty.h>

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

31
#include <linux/ti_wilink_st.h>
P
Pavan Savoy 已提交
32 33 34 35 36 37 38 39

/* 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
 */
void (*st_recv) (void*, const unsigned char*, long);

/********************************************************************/
40 41
static void add_channel_to_table(struct st_data_s *st_gdata,
		struct st_proto_s *new_proto)
P
Pavan Savoy 已提交
42
{
43 44 45
	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;
46
	st_gdata->is_registered[new_proto->chnl_id] = true;
47 48 49 50 51 52
}

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);
53 54
/*	st_gdata->list[proto->chnl_id] = NULL; */
	st_gdata->is_registered[proto->chnl_id] = false;
P
Pavan Savoy 已提交
55
}
56

57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
/*
 * 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 已提交
75 76 77 78 79 80 81 82 83 84 85 86 87
/* 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");
88
		return -EINVAL;
P
Pavan Savoy 已提交
89 90 91
	}
	tty = st_gdata->tty;
#ifdef VERBOSE
92 93
	print_hex_dump(KERN_DEBUG, "<out<", DUMP_PREFIX_NONE,
		16, 1, data, count, 0);
P
Pavan Savoy 已提交
94 95 96 97 98 99 100 101 102
#endif
	return tty->ops->write(tty, data, count);

}

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

	if (unlikely
	    (st_gdata == NULL || st_gdata->rx_skb == NULL
109
	     || st_gdata->is_registered[chnl_id] == false)) {
110 111
		pr_err("chnl_id %d not registered, no data to send?",
			   chnl_id);
P
Pavan Savoy 已提交
112 113 114 115 116 117 118 119
		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
	 */
120
	if (likely(st_gdata->list[chnl_id]->recv != NULL)) {
121
		if (unlikely
122 123
			(st_gdata->list[chnl_id]->recv
			(st_gdata->list[chnl_id]->priv_data, st_gdata->rx_skb)
124
			     != 0)) {
125
			pr_err(" proto stack %d's ->recv failed", chnl_id);
P
Pavan Savoy 已提交
126 127 128 129
			kfree_skb(st_gdata->rx_skb);
			return;
		}
	} else {
130
		pr_err(" proto stack %d's ->recv null", chnl_id);
P
Pavan Savoy 已提交
131 132 133 134 135
		kfree_skb(st_gdata->rx_skb);
	}
	return;
}

136 137
/**
 * st_reg_complete -
P
Pavan Savoy 已提交
138 139 140 141 142 143 144
 * to call registration complete callbacks
 * of all protocol stack drivers
 */
void st_reg_complete(struct st_data_s *st_gdata, char err)
{
	unsigned char i = 0;
	pr_info(" %s ", __func__);
145
	for (i = 0; i < ST_MAX_CHANNELS; i++) {
146 147 148
		if (likely(st_gdata != NULL &&
			st_gdata->is_registered[i] == true &&
				st_gdata->list[i]->reg_complete_cb != NULL)) {
149 150
			st_gdata->list[i]->reg_complete_cb
				(st_gdata->list[i]->priv_data, err);
151 152 153
			pr_info("protocol %d's cb sent %d\n", i, err);
			if (err) { /* cleanup registered protocol */
				st_gdata->protos_registered--;
154
				st_gdata->is_registered[i] = false;
155 156
			}
		}
P
Pavan Savoy 已提交
157 158 159 160
	}
}

static inline int st_check_data_len(struct st_data_s *st_gdata,
161
	unsigned char chnl_id, int len)
P
Pavan Savoy 已提交
162
{
163
	int room = skb_tailroom(st_gdata->rx_skb);
P
Pavan Savoy 已提交
164

165
	pr_debug("len %d room %d", len, room);
P
Pavan Savoy 已提交
166 167 168 169 170 171

	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)
		 */
172
		st_send_frame(chnl_id, st_gdata);
P
Pavan Savoy 已提交
173 174 175 176 177 178 179 180 181 182 183 184

	} 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 */
185
		st_gdata->rx_state = ST_W4_DATA;
P
Pavan Savoy 已提交
186 187 188 189 190 191 192 193 194
		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;
195
	st_gdata->rx_chnl = 0;
P
Pavan Savoy 已提交
196 197 198 199

	return 0;
}

200 201 202
/**
 * st_wakeup_ack - internal function for action when wake-up ack
 *	received
P
Pavan Savoy 已提交
203 204 205 206
 */
static inline void st_wakeup_ack(struct st_data_s *st_gdata,
	unsigned char cmd)
{
207
	struct sk_buff *waiting_skb;
P
Pavan Savoy 已提交
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
	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);
}

225 226 227 228 229 230 231
/**
 * 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 已提交
232 233 234 235
 */
void st_int_recv(void *disc_data,
	const unsigned char *data, long count)
{
236
	char *ptr;
237 238 239 240
	struct st_proto_s *proto;
	unsigned short payload_len = 0;
	int len = 0, type = 0;
	unsigned char *plen;
P
Pavan Savoy 已提交
241
	struct st_data_s *st_gdata = (struct st_data_s *)disc_data;
242
	unsigned long flags;
P
Pavan Savoy 已提交
243 244 245 246 247 248 249 250

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

251
	pr_debug("count %ld rx_state %ld"
P
Pavan Savoy 已提交
252 253 254
		   "rx_count %ld", count, st_gdata->rx_state,
		   st_gdata->rx_count);

255
	spin_lock_irqsave(&st_gdata->lock, flags);
P
Pavan Savoy 已提交
256 257 258 259 260 261 262 263 264 265 266 267 268 269
	/* 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) {
270 271
			/* Waiting for complete packet ? */
			case ST_W4_DATA:
272
				pr_debug("Complete pkt received");
P
Pavan Savoy 已提交
273 274
				/* Ask ST CORE to forward
				 * the packet to protocol driver */
275
				st_send_frame(st_gdata->rx_chnl, st_gdata);
P
Pavan Savoy 已提交
276 277 278 279

				st_gdata->rx_state = ST_W4_PACKET_TYPE;
				st_gdata->rx_skb = NULL;
				continue;
280 281 282 283 284 285
			/* 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];
286
				pr_debug("plen pointing to %x\n", *plen);
287 288 289 290 291 292 293 294 295 296 297
				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);
298
				pr_debug("off %d, pay len %d\n",
299
					proto->offset_len_in_hdr, payload_len);
P
Pavan Savoy 已提交
300 301 302 303 304 305 306 307 308 309 310
				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:
311
			pr_debug("PM packet");
P
Pavan Savoy 已提交
312 313 314 315
			/* this takes appropriate action based on
			 * sleep state received --
			 */
			st_ll_sleep_state(st_gdata, *ptr);
316 317 318 319 320 321 322 323
			/* 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 已提交
324 325 326 327
			ptr++;
			count--;
			continue;
		case LL_WAKE_UP_ACK:
328
			pr_debug("PM packet");
329 330

			spin_unlock_irqrestore(&st_gdata->lock, flags);
P
Pavan Savoy 已提交
331 332
			/* wake up ack received */
			st_wakeup_ack(st_gdata, *ptr);
333 334
			spin_lock_irqsave(&st_gdata->lock, flags);

P
Pavan Savoy 已提交
335 336 337 338 339
			ptr++;
			count--;
			continue;
			/* Unknow packet? */
		default:
340 341 342 343 344 345 346 347 348 349 350 351
			type = *ptr;
			st_gdata->rx_skb = alloc_skb(
					st_gdata->list[type]->max_frame_size,
					GFP_ATOMIC);
			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;
352
			pr_debug("rx_count %ld\n", st_gdata->rx_count);
P
Pavan Savoy 已提交
353 354 355 356
		};
		ptr++;
		count--;
	}
357
	spin_unlock_irqrestore(&st_gdata->lock, flags);
358
	pr_debug("done %s", __func__);
P
Pavan Savoy 已提交
359 360 361
	return;
}

362 363 364 365 366
/**
 * 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 已提交
367 368 369 370 371
 */
struct sk_buff *st_int_dequeue(struct st_data_s *st_gdata)
{
	struct sk_buff *returning_skb;

372
	pr_debug("%s", __func__);
P
Pavan Savoy 已提交
373 374 375 376 377 378 379 380
	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);
}

381 382 383 384 385 386 387 388
/**
 * 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 已提交
389 390 391 392 393
 */
void st_int_enqueue(struct st_data_s *st_gdata, struct sk_buff *skb)
{
	unsigned long flags = 0;

394
	pr_debug("%s", __func__);
P
Pavan Savoy 已提交
395 396 397 398
	spin_lock_irqsave(&st_gdata->lock, flags);

	switch (st_ll_getstate(st_gdata)) {
	case ST_LL_AWAKE:
399
		pr_debug("ST LL is AWAKE, sending normally");
P
Pavan Savoy 已提交
400 401 402 403 404
		skb_queue_tail(&st_gdata->txq, skb);
		break;
	case ST_LL_ASLEEP_TO_AWAKE:
		skb_queue_tail(&st_gdata->tx_waitq, skb);
		break;
405
	case ST_LL_AWAKE_TO_ASLEEP:
P
Pavan Savoy 已提交
406 407 408 409 410 411 412 413 414 415 416 417 418 419
		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;
	}
420

P
Pavan Savoy 已提交
421
	spin_unlock_irqrestore(&st_gdata->lock, flags);
422
	pr_debug("done %s", __func__);
P
Pavan Savoy 已提交
423 424 425 426 427 428 429 430 431 432 433 434 435
	return;
}

/*
 * internal wakeup function
 * called from either
 * - TTY layer when write's finished
 * - st_write (in context of the protocol stack)
 */
void st_tx_wakeup(struct st_data_s *st_data)
{
	struct sk_buff *skb;
	unsigned long flags;	/* for irq save flags */
436
	pr_debug("%s", __func__);
P
Pavan Savoy 已提交
437 438
	/* check for sending & set flag sending here */
	if (test_and_set_bit(ST_TX_SENDING, &st_data->tx_state)) {
439
		pr_debug("ST already sending");
P
Pavan Savoy 已提交
440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476
		/* 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
*/
477
void kim_st_list_protocols(struct st_data_s *st_gdata, void *buf)
P
Pavan Savoy 已提交
478
{
479
	seq_printf(buf, "[%d]\nBT=%c\nFM=%c\nGPS=%c\n",
480
			st_gdata->protos_registered,
481 482 483
			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 已提交
484 485 486 487 488 489 490 491 492 493
}

/********************************************************************/
/*
 * 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;
494
	long err = 0;
P
Pavan Savoy 已提交
495 496
	unsigned long flags = 0;

497
	st_kim_ref(&st_gdata, 0);
498
	pr_info("%s(%d) ", __func__, new_proto->chnl_id);
P
Pavan Savoy 已提交
499 500 501
	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");
502
		return -EINVAL;
P
Pavan Savoy 已提交
503 504
	}

505 506
	if (new_proto->chnl_id >= ST_MAX_CHANNELS) {
		pr_err("chnl_id %d not supported", new_proto->chnl_id);
507
		return -EPROTONOSUPPORT;
P
Pavan Savoy 已提交
508 509
	}

510
	if (st_gdata->is_registered[new_proto->chnl_id] == true) {
511
		pr_err("chnl_id %d already registered", new_proto->chnl_id);
512
		return -EALREADY;
P
Pavan Savoy 已提交
513 514 515 516 517 518
	}

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

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

522
		add_channel_to_table(st_gdata, new_proto);
523
		st_gdata->protos_registered++;
P
Pavan Savoy 已提交
524 525 526 527
		new_proto->write = st_write;

		set_bit(ST_REG_PENDING, &st_gdata->st_state);
		spin_unlock_irqrestore(&st_gdata->lock, flags);
528
		return -EINPROGRESS;
P
Pavan Savoy 已提交
529
	} else if (st_gdata->protos_registered == ST_EMPTY) {
530
		pr_info(" chnl_id list empty :%d ", new_proto->chnl_id);
P
Pavan Savoy 已提交
531 532 533 534 535 536 537 538 539 540 541
		set_bit(ST_REG_IN_PROGRESS, &st_gdata->st_state);
		st_recv = st_kim_recv;

		/* release lock previously held - re-locked below */
		spin_unlock_irqrestore(&st_gdata->lock, flags);

		/* enable the ST LL - to set default chip state */
		st_ll_enable(st_gdata);
		/* this may take a while to complete
		 * since it involves BT fw download
		 */
542
		err = st_kim_start(st_gdata->kim_data);
543
		if (err != 0) {
P
Pavan Savoy 已提交
544 545 546 547
			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 ");
548
				st_reg_complete(st_gdata, err);
P
Pavan Savoy 已提交
549
			}
550
			return -EINVAL;
P
Pavan Savoy 已提交
551 552 553 554 555 556 557 558 559 560
		}

		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))) {
561
			pr_debug(" call reg complete callback ");
562
			st_reg_complete(st_gdata, 0);
P
Pavan Savoy 已提交
563 564 565 566 567 568
		}
		clear_bit(ST_REG_PENDING, &st_gdata->st_state);

		/* check for already registered once more,
		 * since the above check is old
		 */
569
		if (st_gdata->is_registered[new_proto->chnl_id] == true) {
P
Pavan Savoy 已提交
570
			pr_err(" proto %d already registered ",
571
				   new_proto->chnl_id);
572
			return -EALREADY;
P
Pavan Savoy 已提交
573 574 575
		}

		spin_lock_irqsave(&st_gdata->lock, flags);
576
		add_channel_to_table(st_gdata, new_proto);
577
		st_gdata->protos_registered++;
P
Pavan Savoy 已提交
578 579 580 581 582 583
		new_proto->write = st_write;
		spin_unlock_irqrestore(&st_gdata->lock, flags);
		return err;
	}
	/* if fw is already downloaded & new stack registers protocol */
	else {
584
		add_channel_to_table(st_gdata, new_proto);
585
		st_gdata->protos_registered++;
P
Pavan Savoy 已提交
586 587 588 589 590 591
		new_proto->write = st_write;

		/* lock already held before entering else */
		spin_unlock_irqrestore(&st_gdata->lock, flags);
		return err;
	}
592
	pr_debug("done %s(%d) ", __func__, new_proto->chnl_id);
P
Pavan Savoy 已提交
593 594 595 596 597 598
}
EXPORT_SYMBOL_GPL(st_register);

/* to unregister a protocol -
 * to be called from protocol stack driver
 */
599
long st_unregister(struct st_proto_s *proto)
P
Pavan Savoy 已提交
600
{
601
	long err = 0;
P
Pavan Savoy 已提交
602 603 604
	unsigned long flags = 0;
	struct st_data_s	*st_gdata;

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

607
	st_kim_ref(&st_gdata, 0);
608 609
	if (proto->chnl_id >= ST_MAX_CHANNELS) {
		pr_err(" chnl_id %d not supported", proto->chnl_id);
610
		return -EPROTONOSUPPORT;
P
Pavan Savoy 已提交
611 612 613 614
	}

	spin_lock_irqsave(&st_gdata->lock, flags);

615 616
	if (st_gdata->list[proto->chnl_id] == NULL) {
		pr_err(" chnl_id %d not registered", proto->chnl_id);
P
Pavan Savoy 已提交
617
		spin_unlock_irqrestore(&st_gdata->lock, flags);
618
		return -EPROTONOSUPPORT;
P
Pavan Savoy 已提交
619 620 621
	}

	st_gdata->protos_registered--;
622
	remove_channel_from_table(st_gdata, proto);
P
Pavan Savoy 已提交
623 624 625 626
	spin_unlock_irqrestore(&st_gdata->lock, flags);

	if ((st_gdata->protos_registered == ST_EMPTY) &&
	    (!test_bit(ST_REG_PENDING, &st_gdata->st_state))) {
627
		pr_info(" all chnl_ids unregistered ");
P
Pavan Savoy 已提交
628 629 630 631 632 633 634

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

635
		/* all chnl_ids now unregistered */
636
		st_kim_stop(st_gdata->kim_data);
P
Pavan Savoy 已提交
637 638 639 640 641 642 643 644 645 646 647 648 649 650 651
		/* 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;

652
	st_kim_ref(&st_gdata, 0);
P
Pavan Savoy 已提交
653 654 655
	if (unlikely(skb == NULL || st_gdata == NULL
		|| st_gdata->tty == NULL)) {
		pr_err("data/tty unavailable to perform write");
656
		return -EINVAL;
P
Pavan Savoy 已提交
657
	}
658

659
	pr_debug("%d to be written", skb->len);
P
Pavan Savoy 已提交
660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679
	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)
{
680
	int err = 0;
P
Pavan Savoy 已提交
681 682 683
	struct st_data_s *st_gdata;
	pr_info("%s ", __func__);

684
	st_kim_ref(&st_gdata, 0);
P
Pavan Savoy 已提交
685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700
	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
	 */
701
	st_kim_complete(st_gdata->kim_data);
702
	pr_debug("done %s", __func__);
P
Pavan Savoy 已提交
703 704 705 706 707
	return err;
}

static void st_tty_close(struct tty_struct *tty)
{
708
	unsigned char i = ST_MAX_CHANNELS;
P
Pavan Savoy 已提交
709 710 711 712 713 714 715 716 717 718
	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);
719
	for (i = ST_BT; i < ST_MAX_CHANNELS; i++) {
P
Pavan Savoy 已提交
720 721 722 723
		if (st_gdata->list[i] != NULL)
			pr_err("%d not un-registered", i);
		st_gdata->list[i] = NULL;
	}
724
	st_gdata->protos_registered = 0;
P
Pavan Savoy 已提交
725 726 727 728 729
	spin_unlock_irqrestore(&st_gdata->lock, flags);
	/*
	 * signal to UIM via KIM that -
	 * N_TI_WL ldisc is un-installed
	 */
730
	st_kim_complete(st_gdata->kim_data);
P
Pavan Savoy 已提交
731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746
	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);

747
	pr_debug("%s: done ", __func__);
P
Pavan Savoy 已提交
748 749
}

750 751
static void st_tty_receive(struct tty_struct *tty, const unsigned char *data,
			   char *tty_flags, int count)
P
Pavan Savoy 已提交
752 753
{
#ifdef VERBOSE
754 755
	print_hex_dump(KERN_DEBUG, ">in>", DUMP_PREFIX_NONE,
		16, 1, data, count, 0);
P
Pavan Savoy 已提交
756 757 758 759 760 761 762
#endif

	/*
	 * if fw download is in progress then route incoming data
	 * to KIM for validation
	 */
	st_recv(tty->disc_data, data, count);
763
	pr_debug("done %s", __func__);
P
Pavan Savoy 已提交
764 765 766 767 768 769 770 771
}

/* 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;
772
	pr_debug("%s ", __func__);
P
Pavan Savoy 已提交
773 774 775 776 777 778 779 780 781 782
	/* don't do an wakeup for now */
	clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);

	/* call our internal wakeup */
	st_tx_wakeup((void *)st_gdata);
}

static void st_tty_flush_buffer(struct tty_struct *tty)
{
	struct	st_data_s *st_gdata = tty->disc_data;
783
	pr_debug("%s ", __func__);
P
Pavan Savoy 已提交
784 785 786 787 788 789 790 791

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

	tty->ops->flush_buffer(tty);
	return;
}

792 793 794 795 796 797 798 799 800 801 802
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 已提交
803 804 805 806 807 808
/********************************************************************/
int st_core_init(struct st_data_s **core_data)
{
	struct st_data_s *st_gdata;
	long err;

809
	err = tty_register_ldisc(N_TI_WL, &st_ldisc_ops);
P
Pavan Savoy 已提交
810 811 812 813 814
	if (err) {
		pr_err("error registering %d line discipline %ld",
			   N_TI_WL, err);
		return err;
	}
815
	pr_debug("registered n_shared line discipline");
P
Pavan Savoy 已提交
816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842

	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");
843
		return err;
P
Pavan Savoy 已提交
844 845 846 847 848 849 850 851 852 853 854 855
	}
	*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);
856

P
Pavan Savoy 已提交
857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872
	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);
	}
}