diff --git a/drivers/char/diag/diagfwd_peripheral.c b/drivers/char/diag/diagfwd_peripheral.c index 9c9d000c94db..c1f954cdb080 100644 --- a/drivers/char/diag/diagfwd_peripheral.c +++ b/drivers/char/diag/diagfwd_peripheral.c @@ -437,9 +437,9 @@ int diagfwd_peripheral_init(void) fwd_info->inited = 1; fwd_info->read_bytes = 0; fwd_info->write_bytes = 0; - spin_lock_init(&fwd_info->buf_lock); - spin_lock_init(&fwd_info->write_buf_lock); + mutex_init(&fwd_info->buf_mutex); mutex_init(&fwd_info->data_mutex); + spin_lock_init(&fwd_info->write_buf_lock); } } @@ -453,8 +453,8 @@ int diagfwd_peripheral_init(void) fwd_info->ch_open = 0; fwd_info->read_bytes = 0; fwd_info->write_bytes = 0; - spin_lock_init(&fwd_info->buf_lock); spin_lock_init(&fwd_info->write_buf_lock); + mutex_init(&fwd_info->buf_mutex); mutex_init(&fwd_info->data_mutex); /* * This state shouldn't be set for Control channels @@ -1072,7 +1072,6 @@ static void diagfwd_queue_read(struct diagfwd_info *fwd_info) void diagfwd_buffers_init(struct diagfwd_info *fwd_info) { - unsigned long flags; if (!fwd_info) return; @@ -1083,10 +1082,10 @@ void diagfwd_buffers_init(struct diagfwd_info *fwd_info) return; } - spin_lock_irqsave(&fwd_info->buf_lock, flags); + mutex_lock(&fwd_info->buf_mutex); if (!fwd_info->buf_1) { fwd_info->buf_1 = kzalloc(sizeof(struct diagfwd_buf_t), - GFP_ATOMIC); + GFP_KERNEL); if (!fwd_info->buf_1) goto err; kmemleak_not_leak(fwd_info->buf_1); @@ -1094,7 +1093,7 @@ void diagfwd_buffers_init(struct diagfwd_info *fwd_info) if (!fwd_info->buf_1->data) { fwd_info->buf_1->data = kzalloc(PERIPHERAL_BUF_SZ + APF_DIAG_PADDING, - GFP_ATOMIC); + GFP_KERNEL); if (!fwd_info->buf_1->data) goto err; fwd_info->buf_1->len = PERIPHERAL_BUF_SZ; @@ -1106,7 +1105,7 @@ void diagfwd_buffers_init(struct diagfwd_info *fwd_info) if (fwd_info->type == TYPE_DATA) { if (!fwd_info->buf_2) { fwd_info->buf_2 = kzalloc(sizeof(struct diagfwd_buf_t), - GFP_ATOMIC); + GFP_KERNEL); if (!fwd_info->buf_2) goto err; kmemleak_not_leak(fwd_info->buf_2); @@ -1115,7 +1114,7 @@ void diagfwd_buffers_init(struct diagfwd_info *fwd_info) if (!fwd_info->buf_2->data) { fwd_info->buf_2->data = kzalloc(PERIPHERAL_BUF_SZ + APF_DIAG_PADDING, - GFP_ATOMIC); + GFP_KERNEL); if (!fwd_info->buf_2->data) goto err; fwd_info->buf_2->len = PERIPHERAL_BUF_SZ; @@ -1131,7 +1130,7 @@ void diagfwd_buffers_init(struct diagfwd_info *fwd_info) fwd_info->buf_1->data_raw = kzalloc(PERIPHERAL_BUF_SZ + APF_DIAG_PADDING, - GFP_ATOMIC); + GFP_KERNEL); if (!fwd_info->buf_1->data_raw) goto err; fwd_info->buf_1->len_raw = PERIPHERAL_BUF_SZ; @@ -1141,7 +1140,7 @@ void diagfwd_buffers_init(struct diagfwd_info *fwd_info) fwd_info->buf_2->data_raw = kzalloc(PERIPHERAL_BUF_SZ + APF_DIAG_PADDING, - GFP_ATOMIC); + GFP_KERNEL); if (!fwd_info->buf_2->data_raw) goto err; fwd_info->buf_2->len_raw = PERIPHERAL_BUF_SZ; @@ -1155,7 +1154,7 @@ void diagfwd_buffers_init(struct diagfwd_info *fwd_info) if (!fwd_info->buf_1->data_raw) { fwd_info->buf_1->data_raw = kzalloc(PERIPHERAL_BUF_SZ + APF_DIAG_PADDING, - GFP_ATOMIC); + GFP_KERNEL); if (!fwd_info->buf_1->data_raw) goto err; fwd_info->buf_1->len_raw = PERIPHERAL_BUF_SZ; @@ -1163,11 +1162,11 @@ void diagfwd_buffers_init(struct diagfwd_info *fwd_info) } } - spin_unlock_irqrestore(&fwd_info->buf_lock, flags); + mutex_unlock(&fwd_info->buf_mutex); return; err: - spin_unlock_irqrestore(&fwd_info->buf_lock, flags); + mutex_unlock(&fwd_info->buf_mutex); diagfwd_buffers_exit(fwd_info); return; @@ -1175,12 +1174,11 @@ err: static void diagfwd_buffers_exit(struct diagfwd_info *fwd_info) { - unsigned long flags; if (!fwd_info) return; - spin_lock_irqsave(&fwd_info->buf_lock, flags); + mutex_lock(&fwd_info->buf_mutex); if (fwd_info->buf_1) { kfree(fwd_info->buf_1->data); fwd_info->buf_1->data = NULL; @@ -1197,7 +1195,7 @@ static void diagfwd_buffers_exit(struct diagfwd_info *fwd_info) kfree(fwd_info->buf_2); fwd_info->buf_2 = NULL; } - spin_unlock_irqrestore(&fwd_info->buf_lock, flags); + mutex_unlock(&fwd_info->buf_mutex); } void diagfwd_write_buffers_init(struct diagfwd_info *fwd_info) diff --git a/drivers/char/diag/diagfwd_peripheral.h b/drivers/char/diag/diagfwd_peripheral.h index cbbab86a9425..7337a9f70eef 100644 --- a/drivers/char/diag/diagfwd_peripheral.h +++ b/drivers/char/diag/diagfwd_peripheral.h @@ -70,8 +70,8 @@ struct diagfwd_info { atomic_t opened; unsigned long read_bytes; unsigned long write_bytes; - spinlock_t buf_lock; spinlock_t write_buf_lock; + struct mutex buf_mutex; struct mutex data_mutex; void *ctxt; struct diagfwd_buf_t *buf_1; diff --git a/drivers/char/diag/diagfwd_socket.c b/drivers/char/diag/diagfwd_socket.c index 2f9ec51a17ba..955f239b4ffa 100644 --- a/drivers/char/diag/diagfwd_socket.c +++ b/drivers/char/diag/diagfwd_socket.c @@ -261,13 +261,6 @@ static void socket_data_ready(struct sock *sk_ptr) spin_unlock_irqrestore(&info->lock, flags); diag_ws_on_notify(); - /* - * Initialize read buffers for the servers. The servers must read data - * first to get the address of its clients. - */ - if (!atomic_read(&info->opened) && info->port_type == PORT_TYPE_SERVER) - diagfwd_buffers_init(info->fwd_ctxt); - queue_work(info->wq, &(info->read_work)); wake_up_interruptible(&info->read_wait_q); return; @@ -656,6 +649,9 @@ static void socket_read_work_fn(struct work_struct *work) if (!info) return; + if (!atomic_read(&info->opened) && info->port_type == PORT_TYPE_SERVER) + diagfwd_buffers_init(info->fwd_ctxt); + diagfwd_channel_read(info->fwd_ctxt); }