diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/mmc/card | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/mmc/card')
-rw-r--r-- | drivers/mmc/card/block.c | 9 | ||||
-rw-r--r-- | drivers/mmc/card/mmc_test.c | 10 | ||||
-rw-r--r-- | drivers/mmc/card/queue.c | 29 | ||||
-rw-r--r-- | drivers/mmc/card/sdio_uart.c | 432 |
4 files changed, 278 insertions, 202 deletions
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 85f0e8cd875b..cb9fbc83b090 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c | |||
@@ -23,6 +23,7 @@ | |||
23 | 23 | ||
24 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
25 | #include <linux/fs.h> | 25 | #include <linux/fs.h> |
26 | #include <linux/slab.h> | ||
26 | #include <linux/errno.h> | 27 | #include <linux/errno.h> |
27 | #include <linux/hdreg.h> | 28 | #include <linux/hdreg.h> |
28 | #include <linux/kdev_t.h> | 29 | #include <linux/kdev_t.h> |
@@ -85,7 +86,14 @@ static void mmc_blk_put(struct mmc_blk_data *md) | |||
85 | mutex_lock(&open_lock); | 86 | mutex_lock(&open_lock); |
86 | md->usage--; | 87 | md->usage--; |
87 | if (md->usage == 0) { | 88 | if (md->usage == 0) { |
89 | int devmaj = MAJOR(disk_devt(md->disk)); | ||
88 | int devidx = MINOR(disk_devt(md->disk)) >> MMC_SHIFT; | 90 | int devidx = MINOR(disk_devt(md->disk)) >> MMC_SHIFT; |
91 | |||
92 | if (!devmaj) | ||
93 | devidx = md->disk->first_minor >> MMC_SHIFT; | ||
94 | |||
95 | blk_cleanup_queue(md->queue.queue); | ||
96 | |||
89 | __clear_bit(devidx, dev_use); | 97 | __clear_bit(devidx, dev_use); |
90 | 98 | ||
91 | put_disk(md->disk); | 99 | put_disk(md->disk); |
@@ -613,6 +621,7 @@ static int mmc_blk_probe(struct mmc_card *card) | |||
613 | return 0; | 621 | return 0; |
614 | 622 | ||
615 | out: | 623 | out: |
624 | mmc_cleanup_queue(&md->queue); | ||
616 | mmc_blk_put(md); | 625 | mmc_blk_put(md); |
617 | 626 | ||
618 | return err; | 627 | return err; |
diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c index b9f1e84897cc..445d7db2277e 100644 --- a/drivers/mmc/card/mmc_test.c +++ b/drivers/mmc/card/mmc_test.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/mmc/card.h> | 13 | #include <linux/mmc/card.h> |
14 | #include <linux/mmc/host.h> | 14 | #include <linux/mmc/host.h> |
15 | #include <linux/mmc/mmc.h> | 15 | #include <linux/mmc/mmc.h> |
16 | #include <linux/slab.h> | ||
16 | 17 | ||
17 | #include <linux/scatterlist.h> | 18 | #include <linux/scatterlist.h> |
18 | 19 | ||
@@ -74,6 +75,9 @@ static void mmc_test_prepare_mrq(struct mmc_test_card *test, | |||
74 | } | 75 | } |
75 | 76 | ||
76 | mrq->cmd->arg = dev_addr; | 77 | mrq->cmd->arg = dev_addr; |
78 | if (!mmc_card_blockaddr(test->card)) | ||
79 | mrq->cmd->arg <<= 9; | ||
80 | |||
77 | mrq->cmd->flags = MMC_RSP_R1 | MMC_CMD_ADTC; | 81 | mrq->cmd->flags = MMC_RSP_R1 | MMC_CMD_ADTC; |
78 | 82 | ||
79 | if (blocks == 1) | 83 | if (blocks == 1) |
@@ -190,7 +194,7 @@ static int __mmc_test_prepare(struct mmc_test_card *test, int write) | |||
190 | } | 194 | } |
191 | 195 | ||
192 | for (i = 0;i < BUFFER_SIZE / 512;i++) { | 196 | for (i = 0;i < BUFFER_SIZE / 512;i++) { |
193 | ret = mmc_test_buffer_transfer(test, test->buffer, i * 512, 512, 1); | 197 | ret = mmc_test_buffer_transfer(test, test->buffer, i, 512, 1); |
194 | if (ret) | 198 | if (ret) |
195 | return ret; | 199 | return ret; |
196 | } | 200 | } |
@@ -219,7 +223,7 @@ static int mmc_test_cleanup(struct mmc_test_card *test) | |||
219 | memset(test->buffer, 0, 512); | 223 | memset(test->buffer, 0, 512); |
220 | 224 | ||
221 | for (i = 0;i < BUFFER_SIZE / 512;i++) { | 225 | for (i = 0;i < BUFFER_SIZE / 512;i++) { |
222 | ret = mmc_test_buffer_transfer(test, test->buffer, i * 512, 512, 1); | 226 | ret = mmc_test_buffer_transfer(test, test->buffer, i, 512, 1); |
223 | if (ret) | 227 | if (ret) |
224 | return ret; | 228 | return ret; |
225 | } | 229 | } |
@@ -426,7 +430,7 @@ static int mmc_test_transfer(struct mmc_test_card *test, | |||
426 | for (i = 0;i < sectors;i++) { | 430 | for (i = 0;i < sectors;i++) { |
427 | ret = mmc_test_buffer_transfer(test, | 431 | ret = mmc_test_buffer_transfer(test, |
428 | test->buffer + i * 512, | 432 | test->buffer + i * 512, |
429 | dev_addr + i * 512, 512, 0); | 433 | dev_addr + i, 512, 0); |
430 | if (ret) | 434 | if (ret) |
431 | return ret; | 435 | return ret; |
432 | } | 436 | } |
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index 49e582356c65..d6ded247d941 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c | |||
@@ -9,6 +9,7 @@ | |||
9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
10 | * | 10 | * |
11 | */ | 11 | */ |
12 | #include <linux/slab.h> | ||
12 | #include <linux/module.h> | 13 | #include <linux/module.h> |
13 | #include <linux/blkdev.h> | 14 | #include <linux/blkdev.h> |
14 | #include <linux/freezer.h> | 15 | #include <linux/freezer.h> |
@@ -90,9 +91,10 @@ static void mmc_request(struct request_queue *q) | |||
90 | struct request *req; | 91 | struct request *req; |
91 | 92 | ||
92 | if (!mq) { | 93 | if (!mq) { |
93 | printk(KERN_ERR "MMC: killing requests for dead queue\n"); | 94 | while ((req = blk_fetch_request(q)) != NULL) { |
94 | while ((req = blk_fetch_request(q)) != NULL) | 95 | req->cmd_flags |= REQ_QUIET; |
95 | __blk_end_request_all(req, -EIO); | 96 | __blk_end_request_all(req, -EIO); |
97 | } | ||
96 | return; | 98 | return; |
97 | } | 99 | } |
98 | 100 | ||
@@ -153,9 +155,8 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock | |||
153 | 155 | ||
154 | if (mq->bounce_buf) { | 156 | if (mq->bounce_buf) { |
155 | blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_ANY); | 157 | blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_ANY); |
156 | blk_queue_max_sectors(mq->queue, bouncesz / 512); | 158 | blk_queue_max_hw_sectors(mq->queue, bouncesz / 512); |
157 | blk_queue_max_phys_segments(mq->queue, bouncesz / 512); | 159 | blk_queue_max_segments(mq->queue, bouncesz / 512); |
158 | blk_queue_max_hw_segments(mq->queue, bouncesz / 512); | ||
159 | blk_queue_max_segment_size(mq->queue, bouncesz); | 160 | blk_queue_max_segment_size(mq->queue, bouncesz); |
160 | 161 | ||
161 | mq->sg = kmalloc(sizeof(struct scatterlist), | 162 | mq->sg = kmalloc(sizeof(struct scatterlist), |
@@ -179,10 +180,9 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock | |||
179 | 180 | ||
180 | if (!mq->bounce_buf) { | 181 | if (!mq->bounce_buf) { |
181 | blk_queue_bounce_limit(mq->queue, limit); | 182 | blk_queue_bounce_limit(mq->queue, limit); |
182 | blk_queue_max_sectors(mq->queue, | 183 | blk_queue_max_hw_sectors(mq->queue, |
183 | min(host->max_blk_count, host->max_req_size / 512)); | 184 | min(host->max_blk_count, host->max_req_size / 512)); |
184 | blk_queue_max_phys_segments(mq->queue, host->max_phys_segs); | 185 | blk_queue_max_segments(mq->queue, host->max_hw_segs); |
185 | blk_queue_max_hw_segments(mq->queue, host->max_hw_segs); | ||
186 | blk_queue_max_segment_size(mq->queue, host->max_seg_size); | 186 | blk_queue_max_segment_size(mq->queue, host->max_seg_size); |
187 | 187 | ||
188 | mq->sg = kmalloc(sizeof(struct scatterlist) * | 188 | mq->sg = kmalloc(sizeof(struct scatterlist) * |
@@ -223,17 +223,18 @@ void mmc_cleanup_queue(struct mmc_queue *mq) | |||
223 | struct request_queue *q = mq->queue; | 223 | struct request_queue *q = mq->queue; |
224 | unsigned long flags; | 224 | unsigned long flags; |
225 | 225 | ||
226 | /* Mark that we should start throwing out stragglers */ | ||
227 | spin_lock_irqsave(q->queue_lock, flags); | ||
228 | q->queuedata = NULL; | ||
229 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
230 | |||
231 | /* Make sure the queue isn't suspended, as that will deadlock */ | 226 | /* Make sure the queue isn't suspended, as that will deadlock */ |
232 | mmc_queue_resume(mq); | 227 | mmc_queue_resume(mq); |
233 | 228 | ||
234 | /* Then terminate our worker thread */ | 229 | /* Then terminate our worker thread */ |
235 | kthread_stop(mq->thread); | 230 | kthread_stop(mq->thread); |
236 | 231 | ||
232 | /* Empty the queue */ | ||
233 | spin_lock_irqsave(q->queue_lock, flags); | ||
234 | q->queuedata = NULL; | ||
235 | blk_start_queue(q); | ||
236 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
237 | |||
237 | if (mq->bounce_sg) | 238 | if (mq->bounce_sg) |
238 | kfree(mq->bounce_sg); | 239 | kfree(mq->bounce_sg); |
239 | mq->bounce_sg = NULL; | 240 | mq->bounce_sg = NULL; |
@@ -245,8 +246,6 @@ void mmc_cleanup_queue(struct mmc_queue *mq) | |||
245 | kfree(mq->bounce_buf); | 246 | kfree(mq->bounce_buf); |
246 | mq->bounce_buf = NULL; | 247 | mq->bounce_buf = NULL; |
247 | 248 | ||
248 | blk_cleanup_queue(mq->queue); | ||
249 | |||
250 | mq->card = NULL; | 249 | mq->card = NULL; |
251 | } | 250 | } |
252 | EXPORT_SYMBOL(mmc_cleanup_queue); | 251 | EXPORT_SYMBOL(mmc_cleanup_queue); |
diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c index 36a8d53ad2a2..a0716967b7c8 100644 --- a/drivers/mmc/card/sdio_uart.c +++ b/drivers/mmc/card/sdio_uart.c | |||
@@ -29,13 +29,15 @@ | |||
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
30 | #include <linux/init.h> | 30 | #include <linux/init.h> |
31 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
32 | #include <linux/sched.h> | ||
32 | #include <linux/mutex.h> | 33 | #include <linux/mutex.h> |
33 | #include <linux/seq_file.h> | 34 | #include <linux/seq_file.h> |
34 | #include <linux/serial_reg.h> | 35 | #include <linux/serial_reg.h> |
35 | #include <linux/circ_buf.h> | 36 | #include <linux/circ_buf.h> |
36 | #include <linux/gfp.h> | ||
37 | #include <linux/tty.h> | 37 | #include <linux/tty.h> |
38 | #include <linux/tty_flip.h> | 38 | #include <linux/tty_flip.h> |
39 | #include <linux/kfifo.h> | ||
40 | #include <linux/slab.h> | ||
39 | 41 | ||
40 | #include <linux/mmc/core.h> | 42 | #include <linux/mmc/core.h> |
41 | #include <linux/mmc/card.h> | 43 | #include <linux/mmc/card.h> |
@@ -46,19 +48,9 @@ | |||
46 | #define UART_NR 8 /* Number of UARTs this driver can handle */ | 48 | #define UART_NR 8 /* Number of UARTs this driver can handle */ |
47 | 49 | ||
48 | 50 | ||
49 | #define UART_XMIT_SIZE PAGE_SIZE | 51 | #define FIFO_SIZE PAGE_SIZE |
50 | #define WAKEUP_CHARS 256 | 52 | #define WAKEUP_CHARS 256 |
51 | 53 | ||
52 | #define circ_empty(circ) ((circ)->head == (circ)->tail) | ||
53 | #define circ_clear(circ) ((circ)->head = (circ)->tail = 0) | ||
54 | |||
55 | #define circ_chars_pending(circ) \ | ||
56 | (CIRC_CNT((circ)->head, (circ)->tail, UART_XMIT_SIZE)) | ||
57 | |||
58 | #define circ_chars_free(circ) \ | ||
59 | (CIRC_SPACE((circ)->head, (circ)->tail, UART_XMIT_SIZE)) | ||
60 | |||
61 | |||
62 | struct uart_icount { | 54 | struct uart_icount { |
63 | __u32 cts; | 55 | __u32 cts; |
64 | __u32 dsr; | 56 | __u32 dsr; |
@@ -73,20 +65,20 @@ struct uart_icount { | |||
73 | }; | 65 | }; |
74 | 66 | ||
75 | struct sdio_uart_port { | 67 | struct sdio_uart_port { |
68 | struct tty_port port; | ||
76 | struct kref kref; | 69 | struct kref kref; |
77 | struct tty_struct *tty; | 70 | struct tty_struct *tty; |
78 | unsigned int index; | 71 | unsigned int index; |
79 | unsigned int opened; | ||
80 | struct mutex open_lock; | ||
81 | struct sdio_func *func; | 72 | struct sdio_func *func; |
82 | struct mutex func_lock; | 73 | struct mutex func_lock; |
83 | struct task_struct *in_sdio_uart_irq; | 74 | struct task_struct *in_sdio_uart_irq; |
84 | unsigned int regs_offset; | 75 | unsigned int regs_offset; |
85 | struct circ_buf xmit; | 76 | struct kfifo xmit_fifo; |
86 | spinlock_t write_lock; | 77 | spinlock_t write_lock; |
87 | struct uart_icount icount; | 78 | struct uart_icount icount; |
88 | unsigned int uartclk; | 79 | unsigned int uartclk; |
89 | unsigned int mctrl; | 80 | unsigned int mctrl; |
81 | unsigned int rx_mctrl; | ||
90 | unsigned int read_status_mask; | 82 | unsigned int read_status_mask; |
91 | unsigned int ignore_status_mask; | 83 | unsigned int ignore_status_mask; |
92 | unsigned char x_char; | 84 | unsigned char x_char; |
@@ -102,9 +94,10 @@ static int sdio_uart_add_port(struct sdio_uart_port *port) | |||
102 | int index, ret = -EBUSY; | 94 | int index, ret = -EBUSY; |
103 | 95 | ||
104 | kref_init(&port->kref); | 96 | kref_init(&port->kref); |
105 | mutex_init(&port->open_lock); | ||
106 | mutex_init(&port->func_lock); | 97 | mutex_init(&port->func_lock); |
107 | spin_lock_init(&port->write_lock); | 98 | spin_lock_init(&port->write_lock); |
99 | if (kfifo_alloc(&port->xmit_fifo, FIFO_SIZE, GFP_KERNEL)) | ||
100 | return -ENOMEM; | ||
108 | 101 | ||
109 | spin_lock(&sdio_uart_table_lock); | 102 | spin_lock(&sdio_uart_table_lock); |
110 | for (index = 0; index < UART_NR; index++) { | 103 | for (index = 0; index < UART_NR; index++) { |
@@ -140,6 +133,7 @@ static void sdio_uart_port_destroy(struct kref *kref) | |||
140 | { | 133 | { |
141 | struct sdio_uart_port *port = | 134 | struct sdio_uart_port *port = |
142 | container_of(kref, struct sdio_uart_port, kref); | 135 | container_of(kref, struct sdio_uart_port, kref); |
136 | kfifo_free(&port->xmit_fifo); | ||
143 | kfree(port); | 137 | kfree(port); |
144 | } | 138 | } |
145 | 139 | ||
@@ -151,6 +145,7 @@ static void sdio_uart_port_put(struct sdio_uart_port *port) | |||
151 | static void sdio_uart_port_remove(struct sdio_uart_port *port) | 145 | static void sdio_uart_port_remove(struct sdio_uart_port *port) |
152 | { | 146 | { |
153 | struct sdio_func *func; | 147 | struct sdio_func *func; |
148 | struct tty_struct *tty; | ||
154 | 149 | ||
155 | BUG_ON(sdio_uart_table[port->index] != port); | 150 | BUG_ON(sdio_uart_table[port->index] != port); |
156 | 151 | ||
@@ -165,15 +160,19 @@ static void sdio_uart_port_remove(struct sdio_uart_port *port) | |||
165 | * give up on that port ASAP. | 160 | * give up on that port ASAP. |
166 | * Beware: the lock ordering is critical. | 161 | * Beware: the lock ordering is critical. |
167 | */ | 162 | */ |
168 | mutex_lock(&port->open_lock); | 163 | mutex_lock(&port->port.mutex); |
169 | mutex_lock(&port->func_lock); | 164 | mutex_lock(&port->func_lock); |
170 | func = port->func; | 165 | func = port->func; |
171 | sdio_claim_host(func); | 166 | sdio_claim_host(func); |
172 | port->func = NULL; | 167 | port->func = NULL; |
173 | mutex_unlock(&port->func_lock); | 168 | mutex_unlock(&port->func_lock); |
174 | if (port->opened) | 169 | tty = tty_port_tty_get(&port->port); |
175 | tty_hangup(port->tty); | 170 | /* tty_hangup is async so is this safe as is ?? */ |
176 | mutex_unlock(&port->open_lock); | 171 | if (tty) { |
172 | tty_hangup(tty); | ||
173 | tty_kref_put(tty); | ||
174 | } | ||
175 | mutex_unlock(&port->port.mutex); | ||
177 | sdio_release_irq(func); | 176 | sdio_release_irq(func); |
178 | sdio_disable_func(func); | 177 | sdio_disable_func(func); |
179 | sdio_release_host(func); | 178 | sdio_release_host(func); |
@@ -217,6 +216,8 @@ static unsigned int sdio_uart_get_mctrl(struct sdio_uart_port *port) | |||
217 | unsigned char status; | 216 | unsigned char status; |
218 | unsigned int ret; | 217 | unsigned int ret; |
219 | 218 | ||
219 | /* FIXME: What stops this losing the delta bits and breaking | ||
220 | sdio_uart_check_modem_status ? */ | ||
220 | status = sdio_in(port, UART_MSR); | 221 | status = sdio_in(port, UART_MSR); |
221 | 222 | ||
222 | ret = 0; | 223 | ret = 0; |
@@ -231,7 +232,8 @@ static unsigned int sdio_uart_get_mctrl(struct sdio_uart_port *port) | |||
231 | return ret; | 232 | return ret; |
232 | } | 233 | } |
233 | 234 | ||
234 | static void sdio_uart_write_mctrl(struct sdio_uart_port *port, unsigned int mctrl) | 235 | static void sdio_uart_write_mctrl(struct sdio_uart_port *port, |
236 | unsigned int mctrl) | ||
235 | { | 237 | { |
236 | unsigned char mcr = 0; | 238 | unsigned char mcr = 0; |
237 | 239 | ||
@@ -387,9 +389,10 @@ static void sdio_uart_stop_rx(struct sdio_uart_port *port) | |||
387 | sdio_out(port, UART_IER, port->ier); | 389 | sdio_out(port, UART_IER, port->ier); |
388 | } | 390 | } |
389 | 391 | ||
390 | static void sdio_uart_receive_chars(struct sdio_uart_port *port, unsigned int *status) | 392 | static void sdio_uart_receive_chars(struct sdio_uart_port *port, |
393 | unsigned int *status) | ||
391 | { | 394 | { |
392 | struct tty_struct *tty = port->tty; | 395 | struct tty_struct *tty = tty_port_tty_get(&port->port); |
393 | unsigned int ch, flag; | 396 | unsigned int ch, flag; |
394 | int max_count = 256; | 397 | int max_count = 256; |
395 | 398 | ||
@@ -399,7 +402,7 @@ static void sdio_uart_receive_chars(struct sdio_uart_port *port, unsigned int *s | |||
399 | port->icount.rx++; | 402 | port->icount.rx++; |
400 | 403 | ||
401 | if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE | | 404 | if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE | |
402 | UART_LSR_FE | UART_LSR_OE))) { | 405 | UART_LSR_FE | UART_LSR_OE))) { |
403 | /* | 406 | /* |
404 | * For statistics only | 407 | * For statistics only |
405 | */ | 408 | */ |
@@ -417,33 +420,41 @@ static void sdio_uart_receive_chars(struct sdio_uart_port *port, unsigned int *s | |||
417 | * Mask off conditions which should be ignored. | 420 | * Mask off conditions which should be ignored. |
418 | */ | 421 | */ |
419 | *status &= port->read_status_mask; | 422 | *status &= port->read_status_mask; |
420 | if (*status & UART_LSR_BI) { | 423 | if (*status & UART_LSR_BI) |
421 | flag = TTY_BREAK; | 424 | flag = TTY_BREAK; |
422 | } else if (*status & UART_LSR_PE) | 425 | else if (*status & UART_LSR_PE) |
423 | flag = TTY_PARITY; | 426 | flag = TTY_PARITY; |
424 | else if (*status & UART_LSR_FE) | 427 | else if (*status & UART_LSR_FE) |
425 | flag = TTY_FRAME; | 428 | flag = TTY_FRAME; |
426 | } | 429 | } |
427 | 430 | ||
428 | if ((*status & port->ignore_status_mask & ~UART_LSR_OE) == 0) | 431 | if ((*status & port->ignore_status_mask & ~UART_LSR_OE) == 0) |
429 | tty_insert_flip_char(tty, ch, flag); | 432 | if (tty) |
433 | tty_insert_flip_char(tty, ch, flag); | ||
430 | 434 | ||
431 | /* | 435 | /* |
432 | * Overrun is special. Since it's reported immediately, | 436 | * Overrun is special. Since it's reported immediately, |
433 | * it doesn't affect the current character. | 437 | * it doesn't affect the current character. |
434 | */ | 438 | */ |
435 | if (*status & ~port->ignore_status_mask & UART_LSR_OE) | 439 | if (*status & ~port->ignore_status_mask & UART_LSR_OE) |
436 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); | 440 | if (tty) |
441 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); | ||
437 | 442 | ||
438 | *status = sdio_in(port, UART_LSR); | 443 | *status = sdio_in(port, UART_LSR); |
439 | } while ((*status & UART_LSR_DR) && (max_count-- > 0)); | 444 | } while ((*status & UART_LSR_DR) && (max_count-- > 0)); |
440 | tty_flip_buffer_push(tty); | 445 | if (tty) { |
446 | tty_flip_buffer_push(tty); | ||
447 | tty_kref_put(tty); | ||
448 | } | ||
441 | } | 449 | } |
442 | 450 | ||
443 | static void sdio_uart_transmit_chars(struct sdio_uart_port *port) | 451 | static void sdio_uart_transmit_chars(struct sdio_uart_port *port) |
444 | { | 452 | { |
445 | struct circ_buf *xmit = &port->xmit; | 453 | struct kfifo *xmit = &port->xmit_fifo; |
446 | int count; | 454 | int count; |
455 | struct tty_struct *tty; | ||
456 | u8 iobuf[16]; | ||
457 | int len; | ||
447 | 458 | ||
448 | if (port->x_char) { | 459 | if (port->x_char) { |
449 | sdio_out(port, UART_TX, port->x_char); | 460 | sdio_out(port, UART_TX, port->x_char); |
@@ -451,30 +462,35 @@ static void sdio_uart_transmit_chars(struct sdio_uart_port *port) | |||
451 | port->x_char = 0; | 462 | port->x_char = 0; |
452 | return; | 463 | return; |
453 | } | 464 | } |
454 | if (circ_empty(xmit) || port->tty->stopped || port->tty->hw_stopped) { | 465 | |
466 | tty = tty_port_tty_get(&port->port); | ||
467 | |||
468 | if (tty == NULL || !kfifo_len(xmit) || | ||
469 | tty->stopped || tty->hw_stopped) { | ||
455 | sdio_uart_stop_tx(port); | 470 | sdio_uart_stop_tx(port); |
471 | tty_kref_put(tty); | ||
456 | return; | 472 | return; |
457 | } | 473 | } |
458 | 474 | ||
459 | count = 16; | 475 | len = kfifo_out_locked(xmit, iobuf, 16, &port->write_lock); |
460 | do { | 476 | for (count = 0; count < len; count++) { |
461 | sdio_out(port, UART_TX, xmit->buf[xmit->tail]); | 477 | sdio_out(port, UART_TX, iobuf[count]); |
462 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | ||
463 | port->icount.tx++; | 478 | port->icount.tx++; |
464 | if (circ_empty(xmit)) | 479 | } |
465 | break; | ||
466 | } while (--count > 0); | ||
467 | |||
468 | if (circ_chars_pending(xmit) < WAKEUP_CHARS) | ||
469 | tty_wakeup(port->tty); | ||
470 | 480 | ||
471 | if (circ_empty(xmit)) | 481 | len = kfifo_len(xmit); |
472 | sdio_uart_stop_tx(port); | 482 | if (len < WAKEUP_CHARS) { |
483 | tty_wakeup(tty); | ||
484 | if (len == 0) | ||
485 | sdio_uart_stop_tx(port); | ||
486 | } | ||
487 | tty_kref_put(tty); | ||
473 | } | 488 | } |
474 | 489 | ||
475 | static void sdio_uart_check_modem_status(struct sdio_uart_port *port) | 490 | static void sdio_uart_check_modem_status(struct sdio_uart_port *port) |
476 | { | 491 | { |
477 | int status; | 492 | int status; |
493 | struct tty_struct *tty; | ||
478 | 494 | ||
479 | status = sdio_in(port, UART_MSR); | 495 | status = sdio_in(port, UART_MSR); |
480 | 496 | ||
@@ -485,25 +501,39 @@ static void sdio_uart_check_modem_status(struct sdio_uart_port *port) | |||
485 | port->icount.rng++; | 501 | port->icount.rng++; |
486 | if (status & UART_MSR_DDSR) | 502 | if (status & UART_MSR_DDSR) |
487 | port->icount.dsr++; | 503 | port->icount.dsr++; |
488 | if (status & UART_MSR_DDCD) | 504 | if (status & UART_MSR_DDCD) { |
489 | port->icount.dcd++; | 505 | port->icount.dcd++; |
506 | /* DCD raise - wake for open */ | ||
507 | if (status & UART_MSR_DCD) | ||
508 | wake_up_interruptible(&port->port.open_wait); | ||
509 | else { | ||
510 | /* DCD drop - hang up if tty attached */ | ||
511 | tty = tty_port_tty_get(&port->port); | ||
512 | if (tty) { | ||
513 | tty_hangup(tty); | ||
514 | tty_kref_put(tty); | ||
515 | } | ||
516 | } | ||
517 | } | ||
490 | if (status & UART_MSR_DCTS) { | 518 | if (status & UART_MSR_DCTS) { |
491 | port->icount.cts++; | 519 | port->icount.cts++; |
492 | if (port->tty->termios->c_cflag & CRTSCTS) { | 520 | tty = tty_port_tty_get(&port->port); |
521 | if (tty && (tty->termios->c_cflag & CRTSCTS)) { | ||
493 | int cts = (status & UART_MSR_CTS); | 522 | int cts = (status & UART_MSR_CTS); |
494 | if (port->tty->hw_stopped) { | 523 | if (tty->hw_stopped) { |
495 | if (cts) { | 524 | if (cts) { |
496 | port->tty->hw_stopped = 0; | 525 | tty->hw_stopped = 0; |
497 | sdio_uart_start_tx(port); | 526 | sdio_uart_start_tx(port); |
498 | tty_wakeup(port->tty); | 527 | tty_wakeup(tty); |
499 | } | 528 | } |
500 | } else { | 529 | } else { |
501 | if (!cts) { | 530 | if (!cts) { |
502 | port->tty->hw_stopped = 1; | 531 | tty->hw_stopped = 1; |
503 | sdio_uart_stop_tx(port); | 532 | sdio_uart_stop_tx(port); |
504 | } | 533 | } |
505 | } | 534 | } |
506 | } | 535 | } |
536 | tty_kref_put(tty); | ||
507 | } | 537 | } |
508 | } | 538 | } |
509 | 539 | ||
@@ -540,33 +570,81 @@ static void sdio_uart_irq(struct sdio_func *func) | |||
540 | port->in_sdio_uart_irq = NULL; | 570 | port->in_sdio_uart_irq = NULL; |
541 | } | 571 | } |
542 | 572 | ||
543 | static int sdio_uart_startup(struct sdio_uart_port *port) | 573 | static int uart_carrier_raised(struct tty_port *tport) |
574 | { | ||
575 | struct sdio_uart_port *port = | ||
576 | container_of(tport, struct sdio_uart_port, port); | ||
577 | unsigned int ret = sdio_uart_claim_func(port); | ||
578 | if (ret) /* Missing hardware shouldn't block for carrier */ | ||
579 | return 1; | ||
580 | ret = sdio_uart_get_mctrl(port); | ||
581 | sdio_uart_release_func(port); | ||
582 | if (ret & TIOCM_CAR) | ||
583 | return 1; | ||
584 | return 0; | ||
585 | } | ||
586 | |||
587 | /** | ||
588 | * uart_dtr_rts - port helper to set uart signals | ||
589 | * @tport: tty port to be updated | ||
590 | * @onoff: set to turn on DTR/RTS | ||
591 | * | ||
592 | * Called by the tty port helpers when the modem signals need to be | ||
593 | * adjusted during an open, close and hangup. | ||
594 | */ | ||
595 | |||
596 | static void uart_dtr_rts(struct tty_port *tport, int onoff) | ||
597 | { | ||
598 | struct sdio_uart_port *port = | ||
599 | container_of(tport, struct sdio_uart_port, port); | ||
600 | int ret = sdio_uart_claim_func(port); | ||
601 | if (ret) | ||
602 | return; | ||
603 | if (onoff == 0) | ||
604 | sdio_uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); | ||
605 | else | ||
606 | sdio_uart_set_mctrl(port, TIOCM_DTR | TIOCM_RTS); | ||
607 | sdio_uart_release_func(port); | ||
608 | } | ||
609 | |||
610 | /** | ||
611 | * sdio_uart_activate - start up hardware | ||
612 | * @tport: tty port to activate | ||
613 | * @tty: tty bound to this port | ||
614 | * | ||
615 | * Activate a tty port. The port locking guarantees us this will be | ||
616 | * run exactly once per set of opens, and if successful will see the | ||
617 | * shutdown method run exactly once to match. Start up and shutdown are | ||
618 | * protected from each other by the internal locking and will not run | ||
619 | * at the same time even during a hangup event. | ||
620 | * | ||
621 | * If we successfully start up the port we take an extra kref as we | ||
622 | * will keep it around until shutdown when the kref is dropped. | ||
623 | */ | ||
624 | |||
625 | static int sdio_uart_activate(struct tty_port *tport, struct tty_struct *tty) | ||
544 | { | 626 | { |
545 | unsigned long page; | 627 | struct sdio_uart_port *port = |
628 | container_of(tport, struct sdio_uart_port, port); | ||
546 | int ret; | 629 | int ret; |
547 | 630 | ||
548 | /* | 631 | /* |
549 | * Set the TTY IO error marker - we will only clear this | 632 | * Set the TTY IO error marker - we will only clear this |
550 | * once we have successfully opened the port. | 633 | * once we have successfully opened the port. |
551 | */ | 634 | */ |
552 | set_bit(TTY_IO_ERROR, &port->tty->flags); | 635 | set_bit(TTY_IO_ERROR, &tty->flags); |
553 | 636 | ||
554 | /* Initialise and allocate the transmit buffer. */ | 637 | kfifo_reset(&port->xmit_fifo); |
555 | page = __get_free_page(GFP_KERNEL); | ||
556 | if (!page) | ||
557 | return -ENOMEM; | ||
558 | port->xmit.buf = (unsigned char *)page; | ||
559 | circ_clear(&port->xmit); | ||
560 | 638 | ||
561 | ret = sdio_uart_claim_func(port); | 639 | ret = sdio_uart_claim_func(port); |
562 | if (ret) | 640 | if (ret) |
563 | goto err1; | 641 | return ret; |
564 | ret = sdio_enable_func(port->func); | 642 | ret = sdio_enable_func(port->func); |
565 | if (ret) | 643 | if (ret) |
566 | goto err2; | 644 | goto err1; |
567 | ret = sdio_claim_irq(port->func, sdio_uart_irq); | 645 | ret = sdio_claim_irq(port->func, sdio_uart_irq); |
568 | if (ret) | 646 | if (ret) |
569 | goto err3; | 647 | goto err2; |
570 | 648 | ||
571 | /* | 649 | /* |
572 | * Clear the FIFO buffers and disable them. | 650 | * Clear the FIFO buffers and disable them. |
@@ -574,7 +652,7 @@ static int sdio_uart_startup(struct sdio_uart_port *port) | |||
574 | */ | 652 | */ |
575 | sdio_out(port, UART_FCR, UART_FCR_ENABLE_FIFO); | 653 | sdio_out(port, UART_FCR, UART_FCR_ENABLE_FIFO); |
576 | sdio_out(port, UART_FCR, UART_FCR_ENABLE_FIFO | | 654 | sdio_out(port, UART_FCR, UART_FCR_ENABLE_FIFO | |
577 | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); | 655 | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); |
578 | sdio_out(port, UART_FCR, 0); | 656 | sdio_out(port, UART_FCR, 0); |
579 | 657 | ||
580 | /* | 658 | /* |
@@ -590,19 +668,19 @@ static int sdio_uart_startup(struct sdio_uart_port *port) | |||
590 | */ | 668 | */ |
591 | sdio_out(port, UART_LCR, UART_LCR_WLEN8); | 669 | sdio_out(port, UART_LCR, UART_LCR_WLEN8); |
592 | 670 | ||
593 | port->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE | UART_IER_UUE; | 671 | port->ier = UART_IER_RLSI|UART_IER_RDI|UART_IER_RTOIE|UART_IER_UUE; |
594 | port->mctrl = TIOCM_OUT2; | 672 | port->mctrl = TIOCM_OUT2; |
595 | 673 | ||
596 | sdio_uart_change_speed(port, port->tty->termios, NULL); | 674 | sdio_uart_change_speed(port, tty->termios, NULL); |
597 | 675 | ||
598 | if (port->tty->termios->c_cflag & CBAUD) | 676 | if (tty->termios->c_cflag & CBAUD) |
599 | sdio_uart_set_mctrl(port, TIOCM_RTS | TIOCM_DTR); | 677 | sdio_uart_set_mctrl(port, TIOCM_RTS | TIOCM_DTR); |
600 | 678 | ||
601 | if (port->tty->termios->c_cflag & CRTSCTS) | 679 | if (tty->termios->c_cflag & CRTSCTS) |
602 | if (!(sdio_uart_get_mctrl(port) & TIOCM_CTS)) | 680 | if (!(sdio_uart_get_mctrl(port) & TIOCM_CTS)) |
603 | port->tty->hw_stopped = 1; | 681 | tty->hw_stopped = 1; |
604 | 682 | ||
605 | clear_bit(TTY_IO_ERROR, &port->tty->flags); | 683 | clear_bit(TTY_IO_ERROR, &tty->flags); |
606 | 684 | ||
607 | /* Kick the IRQ handler once while we're still holding the host lock */ | 685 | /* Kick the IRQ handler once while we're still holding the host lock */ |
608 | sdio_uart_irq(port->func); | 686 | sdio_uart_irq(port->func); |
@@ -610,32 +688,36 @@ static int sdio_uart_startup(struct sdio_uart_port *port) | |||
610 | sdio_uart_release_func(port); | 688 | sdio_uart_release_func(port); |
611 | return 0; | 689 | return 0; |
612 | 690 | ||
613 | err3: | ||
614 | sdio_disable_func(port->func); | ||
615 | err2: | 691 | err2: |
616 | sdio_uart_release_func(port); | 692 | sdio_disable_func(port->func); |
617 | err1: | 693 | err1: |
618 | free_page((unsigned long)port->xmit.buf); | 694 | sdio_uart_release_func(port); |
619 | return ret; | 695 | return ret; |
620 | } | 696 | } |
621 | 697 | ||
622 | static void sdio_uart_shutdown(struct sdio_uart_port *port) | 698 | /** |
699 | * sdio_uart_shutdown - stop hardware | ||
700 | * @tport: tty port to shut down | ||
701 | * | ||
702 | * Deactivate a tty port. The port locking guarantees us this will be | ||
703 | * run only if a successful matching activate already ran. The two are | ||
704 | * protected from each other by the internal locking and will not run | ||
705 | * at the same time even during a hangup event. | ||
706 | */ | ||
707 | |||
708 | static void sdio_uart_shutdown(struct tty_port *tport) | ||
623 | { | 709 | { |
710 | struct sdio_uart_port *port = | ||
711 | container_of(tport, struct sdio_uart_port, port); | ||
624 | int ret; | 712 | int ret; |
625 | 713 | ||
626 | ret = sdio_uart_claim_func(port); | 714 | ret = sdio_uart_claim_func(port); |
627 | if (ret) | 715 | if (ret) |
628 | goto skip; | 716 | return; |
629 | 717 | ||
630 | sdio_uart_stop_rx(port); | 718 | sdio_uart_stop_rx(port); |
631 | 719 | ||
632 | /* TODO: wait here for TX FIFO to drain */ | 720 | /* Disable interrupts from this port */ |
633 | |||
634 | /* Turn off DTR and RTS early. */ | ||
635 | if (port->tty->termios->c_cflag & HUPCL) | ||
636 | sdio_uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); | ||
637 | |||
638 | /* Disable interrupts from this port */ | ||
639 | sdio_release_irq(port->func); | 721 | sdio_release_irq(port->func); |
640 | port->ier = 0; | 722 | port->ier = 0; |
641 | sdio_out(port, UART_IER, 0); | 723 | sdio_out(port, UART_IER, 0); |
@@ -653,108 +735,82 @@ static void sdio_uart_shutdown(struct sdio_uart_port *port) | |||
653 | sdio_disable_func(port->func); | 735 | sdio_disable_func(port->func); |
654 | 736 | ||
655 | sdio_uart_release_func(port); | 737 | sdio_uart_release_func(port); |
656 | |||
657 | skip: | ||
658 | /* Free the transmit buffer page. */ | ||
659 | free_page((unsigned long)port->xmit.buf); | ||
660 | } | 738 | } |
661 | 739 | ||
662 | static int sdio_uart_open (struct tty_struct *tty, struct file * filp) | 740 | /** |
741 | * sdio_uart_install - install method | ||
742 | * @driver: the driver in use (sdio_uart in our case) | ||
743 | * @tty: the tty being bound | ||
744 | * | ||
745 | * Look up and bind the tty and the driver together. Initialize | ||
746 | * any needed private data (in our case the termios) | ||
747 | */ | ||
748 | |||
749 | static int sdio_uart_install(struct tty_driver *driver, struct tty_struct *tty) | ||
663 | { | 750 | { |
664 | struct sdio_uart_port *port; | 751 | int idx = tty->index; |
665 | int ret; | 752 | struct sdio_uart_port *port = sdio_uart_port_get(idx); |
753 | int ret = tty_init_termios(tty); | ||
754 | |||
755 | if (ret == 0) { | ||
756 | tty_driver_kref_get(driver); | ||
757 | tty->count++; | ||
758 | /* This is the ref sdio_uart_port get provided */ | ||
759 | tty->driver_data = port; | ||
760 | driver->ttys[idx] = tty; | ||
761 | } else | ||
762 | sdio_uart_port_put(port); | ||
763 | return ret; | ||
764 | } | ||
666 | 765 | ||
667 | port = sdio_uart_port_get(tty->index); | 766 | /** |
668 | if (!port) | 767 | * sdio_uart_cleanup - called on the last tty kref drop |
669 | return -ENODEV; | 768 | * @tty: the tty being destroyed |
769 | * | ||
770 | * Called asynchronously when the last reference to the tty is dropped. | ||
771 | * We cannot destroy the tty->driver_data port kref until this point | ||
772 | */ | ||
670 | 773 | ||
671 | mutex_lock(&port->open_lock); | 774 | static void sdio_uart_cleanup(struct tty_struct *tty) |
775 | { | ||
776 | struct sdio_uart_port *port = tty->driver_data; | ||
777 | tty->driver_data = NULL; /* Bug trap */ | ||
778 | sdio_uart_port_put(port); | ||
779 | } | ||
672 | 780 | ||
673 | /* | 781 | /* |
674 | * Make sure not to mess up with a dead port | 782 | * Open/close/hangup is now entirely boilerplate |
675 | * which has not been closed yet. | 783 | */ |
676 | */ | ||
677 | if (tty->driver_data && tty->driver_data != port) { | ||
678 | mutex_unlock(&port->open_lock); | ||
679 | sdio_uart_port_put(port); | ||
680 | return -EBUSY; | ||
681 | } | ||
682 | 784 | ||
683 | if (!port->opened) { | 785 | static int sdio_uart_open(struct tty_struct *tty, struct file *filp) |
684 | tty->driver_data = port; | 786 | { |
685 | port->tty = tty; | 787 | struct sdio_uart_port *port = tty->driver_data; |
686 | ret = sdio_uart_startup(port); | 788 | return tty_port_open(&port->port, tty, filp); |
687 | if (ret) { | ||
688 | tty->driver_data = NULL; | ||
689 | port->tty = NULL; | ||
690 | mutex_unlock(&port->open_lock); | ||
691 | sdio_uart_port_put(port); | ||
692 | return ret; | ||
693 | } | ||
694 | } | ||
695 | port->opened++; | ||
696 | mutex_unlock(&port->open_lock); | ||
697 | return 0; | ||
698 | } | 789 | } |
699 | 790 | ||
700 | static void sdio_uart_close(struct tty_struct *tty, struct file * filp) | 791 | static void sdio_uart_close(struct tty_struct *tty, struct file * filp) |
701 | { | 792 | { |
702 | struct sdio_uart_port *port = tty->driver_data; | 793 | struct sdio_uart_port *port = tty->driver_data; |
794 | tty_port_close(&port->port, tty, filp); | ||
795 | } | ||
703 | 796 | ||
704 | if (!port) | 797 | static void sdio_uart_hangup(struct tty_struct *tty) |
705 | return; | 798 | { |
706 | 799 | struct sdio_uart_port *port = tty->driver_data; | |
707 | mutex_lock(&port->open_lock); | 800 | tty_port_hangup(&port->port); |
708 | BUG_ON(!port->opened); | ||
709 | |||
710 | /* | ||
711 | * This is messy. The tty layer calls us even when open() | ||
712 | * returned an error. Ignore this close request if tty->count | ||
713 | * is larger than port->count. | ||
714 | */ | ||
715 | if (tty->count > port->opened) { | ||
716 | mutex_unlock(&port->open_lock); | ||
717 | return; | ||
718 | } | ||
719 | |||
720 | if (--port->opened == 0) { | ||
721 | tty->closing = 1; | ||
722 | sdio_uart_shutdown(port); | ||
723 | tty_ldisc_flush(tty); | ||
724 | port->tty = NULL; | ||
725 | tty->driver_data = NULL; | ||
726 | tty->closing = 0; | ||
727 | } | ||
728 | mutex_unlock(&port->open_lock); | ||
729 | sdio_uart_port_put(port); | ||
730 | } | 801 | } |
731 | 802 | ||
732 | static int sdio_uart_write(struct tty_struct * tty, const unsigned char *buf, | 803 | static int sdio_uart_write(struct tty_struct *tty, const unsigned char *buf, |
733 | int count) | 804 | int count) |
734 | { | 805 | { |
735 | struct sdio_uart_port *port = tty->driver_data; | 806 | struct sdio_uart_port *port = tty->driver_data; |
736 | struct circ_buf *circ = &port->xmit; | 807 | int ret; |
737 | int c, ret = 0; | ||
738 | 808 | ||
739 | if (!port->func) | 809 | if (!port->func) |
740 | return -ENODEV; | 810 | return -ENODEV; |
741 | 811 | ||
742 | spin_lock(&port->write_lock); | 812 | ret = kfifo_in_locked(&port->xmit_fifo, buf, count, &port->write_lock); |
743 | while (1) { | 813 | if (!(port->ier & UART_IER_THRI)) { |
744 | c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE); | ||
745 | if (count < c) | ||
746 | c = count; | ||
747 | if (c <= 0) | ||
748 | break; | ||
749 | memcpy(circ->buf + circ->head, buf, c); | ||
750 | circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1); | ||
751 | buf += c; | ||
752 | count -= c; | ||
753 | ret += c; | ||
754 | } | ||
755 | spin_unlock(&port->write_lock); | ||
756 | |||
757 | if ( !(port->ier & UART_IER_THRI)) { | ||
758 | int err = sdio_uart_claim_func(port); | 814 | int err = sdio_uart_claim_func(port); |
759 | if (!err) { | 815 | if (!err) { |
760 | sdio_uart_start_tx(port); | 816 | sdio_uart_start_tx(port); |
@@ -770,13 +826,13 @@ static int sdio_uart_write(struct tty_struct * tty, const unsigned char *buf, | |||
770 | static int sdio_uart_write_room(struct tty_struct *tty) | 826 | static int sdio_uart_write_room(struct tty_struct *tty) |
771 | { | 827 | { |
772 | struct sdio_uart_port *port = tty->driver_data; | 828 | struct sdio_uart_port *port = tty->driver_data; |
773 | return port ? circ_chars_free(&port->xmit) : 0; | 829 | return FIFO_SIZE - kfifo_len(&port->xmit_fifo); |
774 | } | 830 | } |
775 | 831 | ||
776 | static int sdio_uart_chars_in_buffer(struct tty_struct *tty) | 832 | static int sdio_uart_chars_in_buffer(struct tty_struct *tty) |
777 | { | 833 | { |
778 | struct sdio_uart_port *port = tty->driver_data; | 834 | struct sdio_uart_port *port = tty->driver_data; |
779 | return port ? circ_chars_pending(&port->xmit) : 0; | 835 | return kfifo_len(&port->xmit_fifo); |
780 | } | 836 | } |
781 | 837 | ||
782 | static void sdio_uart_send_xchar(struct tty_struct *tty, char ch) | 838 | static void sdio_uart_send_xchar(struct tty_struct *tty, char ch) |
@@ -841,17 +897,12 @@ static void sdio_uart_unthrottle(struct tty_struct *tty) | |||
841 | sdio_uart_release_func(port); | 897 | sdio_uart_release_func(port); |
842 | } | 898 | } |
843 | 899 | ||
844 | static void sdio_uart_set_termios(struct tty_struct *tty, struct ktermios *old_termios) | 900 | static void sdio_uart_set_termios(struct tty_struct *tty, |
901 | struct ktermios *old_termios) | ||
845 | { | 902 | { |
846 | struct sdio_uart_port *port = tty->driver_data; | 903 | struct sdio_uart_port *port = tty->driver_data; |
847 | unsigned int cflag = tty->termios->c_cflag; | 904 | unsigned int cflag = tty->termios->c_cflag; |
848 | 905 | ||
849 | #define RELEVANT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) | ||
850 | |||
851 | if ((cflag ^ old_termios->c_cflag) == 0 && | ||
852 | RELEVANT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0) | ||
853 | return; | ||
854 | |||
855 | if (sdio_uart_claim_func(port) != 0) | 906 | if (sdio_uart_claim_func(port) != 0) |
856 | return; | 907 | return; |
857 | 908 | ||
@@ -925,8 +976,8 @@ static int sdio_uart_tiocmset(struct tty_struct *tty, struct file *file, | |||
925 | struct sdio_uart_port *port = tty->driver_data; | 976 | struct sdio_uart_port *port = tty->driver_data; |
926 | int result; | 977 | int result; |
927 | 978 | ||
928 | result =sdio_uart_claim_func(port); | 979 | result = sdio_uart_claim_func(port); |
929 | if(!result) { | 980 | if (!result) { |
930 | sdio_uart_update_mctrl(port, set, clear); | 981 | sdio_uart_update_mctrl(port, set, clear); |
931 | sdio_uart_release_func(port); | 982 | sdio_uart_release_func(port); |
932 | } | 983 | } |
@@ -944,33 +995,33 @@ static int sdio_uart_proc_show(struct seq_file *m, void *v) | |||
944 | struct sdio_uart_port *port = sdio_uart_port_get(i); | 995 | struct sdio_uart_port *port = sdio_uart_port_get(i); |
945 | if (port) { | 996 | if (port) { |
946 | seq_printf(m, "%d: uart:SDIO", i); | 997 | seq_printf(m, "%d: uart:SDIO", i); |
947 | if(capable(CAP_SYS_ADMIN)) { | 998 | if (capable(CAP_SYS_ADMIN)) { |
948 | seq_printf(m, " tx:%d rx:%d", | 999 | seq_printf(m, " tx:%d rx:%d", |
949 | port->icount.tx, port->icount.rx); | 1000 | port->icount.tx, port->icount.rx); |
950 | if (port->icount.frame) | 1001 | if (port->icount.frame) |
951 | seq_printf(m, " fe:%d", | 1002 | seq_printf(m, " fe:%d", |
952 | port->icount.frame); | 1003 | port->icount.frame); |
953 | if (port->icount.parity) | 1004 | if (port->icount.parity) |
954 | seq_printf(m, " pe:%d", | 1005 | seq_printf(m, " pe:%d", |
955 | port->icount.parity); | 1006 | port->icount.parity); |
956 | if (port->icount.brk) | 1007 | if (port->icount.brk) |
957 | seq_printf(m, " brk:%d", | 1008 | seq_printf(m, " brk:%d", |
958 | port->icount.brk); | 1009 | port->icount.brk); |
959 | if (port->icount.overrun) | 1010 | if (port->icount.overrun) |
960 | seq_printf(m, " oe:%d", | 1011 | seq_printf(m, " oe:%d", |
961 | port->icount.overrun); | 1012 | port->icount.overrun); |
962 | if (port->icount.cts) | 1013 | if (port->icount.cts) |
963 | seq_printf(m, " cts:%d", | 1014 | seq_printf(m, " cts:%d", |
964 | port->icount.cts); | 1015 | port->icount.cts); |
965 | if (port->icount.dsr) | 1016 | if (port->icount.dsr) |
966 | seq_printf(m, " dsr:%d", | 1017 | seq_printf(m, " dsr:%d", |
967 | port->icount.dsr); | 1018 | port->icount.dsr); |
968 | if (port->icount.rng) | 1019 | if (port->icount.rng) |
969 | seq_printf(m, " rng:%d", | 1020 | seq_printf(m, " rng:%d", |
970 | port->icount.rng); | 1021 | port->icount.rng); |
971 | if (port->icount.dcd) | 1022 | if (port->icount.dcd) |
972 | seq_printf(m, " dcd:%d", | 1023 | seq_printf(m, " dcd:%d", |
973 | port->icount.dcd); | 1024 | port->icount.dcd); |
974 | } | 1025 | } |
975 | sdio_uart_port_put(port); | 1026 | sdio_uart_port_put(port); |
976 | seq_putc(m, '\n'); | 1027 | seq_putc(m, '\n'); |
@@ -992,6 +1043,13 @@ static const struct file_operations sdio_uart_proc_fops = { | |||
992 | .release = single_release, | 1043 | .release = single_release, |
993 | }; | 1044 | }; |
994 | 1045 | ||
1046 | static const struct tty_port_operations sdio_uart_port_ops = { | ||
1047 | .dtr_rts = uart_dtr_rts, | ||
1048 | .carrier_raised = uart_carrier_raised, | ||
1049 | .shutdown = sdio_uart_shutdown, | ||
1050 | .activate = sdio_uart_activate, | ||
1051 | }; | ||
1052 | |||
995 | static const struct tty_operations sdio_uart_ops = { | 1053 | static const struct tty_operations sdio_uart_ops = { |
996 | .open = sdio_uart_open, | 1054 | .open = sdio_uart_open, |
997 | .close = sdio_uart_close, | 1055 | .close = sdio_uart_close, |
@@ -1002,9 +1060,12 @@ static const struct tty_operations sdio_uart_ops = { | |||
1002 | .throttle = sdio_uart_throttle, | 1060 | .throttle = sdio_uart_throttle, |
1003 | .unthrottle = sdio_uart_unthrottle, | 1061 | .unthrottle = sdio_uart_unthrottle, |
1004 | .set_termios = sdio_uart_set_termios, | 1062 | .set_termios = sdio_uart_set_termios, |
1063 | .hangup = sdio_uart_hangup, | ||
1005 | .break_ctl = sdio_uart_break_ctl, | 1064 | .break_ctl = sdio_uart_break_ctl, |
1006 | .tiocmget = sdio_uart_tiocmget, | 1065 | .tiocmget = sdio_uart_tiocmget, |
1007 | .tiocmset = sdio_uart_tiocmset, | 1066 | .tiocmset = sdio_uart_tiocmset, |
1067 | .install = sdio_uart_install, | ||
1068 | .cleanup = sdio_uart_cleanup, | ||
1008 | .proc_fops = &sdio_uart_proc_fops, | 1069 | .proc_fops = &sdio_uart_proc_fops, |
1009 | }; | 1070 | }; |
1010 | 1071 | ||
@@ -1041,7 +1102,7 @@ static int sdio_uart_probe(struct sdio_func *func, | |||
1041 | } | 1102 | } |
1042 | if (!tpl) { | 1103 | if (!tpl) { |
1043 | printk(KERN_WARNING | 1104 | printk(KERN_WARNING |
1044 | "%s: can't find tuple 0x91 subtuple 0 (SUBTPL_SIOREG) for GPS class\n", | 1105 | "%s: can't find tuple 0x91 subtuple 0 (SUBTPL_SIOREG) for GPS class\n", |
1045 | sdio_func_id(func)); | 1106 | sdio_func_id(func)); |
1046 | kfree(port); | 1107 | kfree(port); |
1047 | return -EINVAL; | 1108 | return -EINVAL; |
@@ -1066,13 +1127,16 @@ static int sdio_uart_probe(struct sdio_func *func, | |||
1066 | 1127 | ||
1067 | port->func = func; | 1128 | port->func = func; |
1068 | sdio_set_drvdata(func, port); | 1129 | sdio_set_drvdata(func, port); |
1130 | tty_port_init(&port->port); | ||
1131 | port->port.ops = &sdio_uart_port_ops; | ||
1069 | 1132 | ||
1070 | ret = sdio_uart_add_port(port); | 1133 | ret = sdio_uart_add_port(port); |
1071 | if (ret) { | 1134 | if (ret) { |
1072 | kfree(port); | 1135 | kfree(port); |
1073 | } else { | 1136 | } else { |
1074 | struct device *dev; | 1137 | struct device *dev; |
1075 | dev = tty_register_device(sdio_uart_tty_driver, port->index, &func->dev); | 1138 | dev = tty_register_device(sdio_uart_tty_driver, |
1139 | port->index, &func->dev); | ||
1076 | if (IS_ERR(dev)) { | 1140 | if (IS_ERR(dev)) { |
1077 | sdio_uart_port_remove(port); | 1141 | sdio_uart_port_remove(port); |
1078 | ret = PTR_ERR(dev); | 1142 | ret = PTR_ERR(dev); |