diff options
Diffstat (limited to 'drivers/hid/intel-ish-hid/ishtp')
-rw-r--r-- | drivers/hid/intel-ish-hid/ishtp/bus.c | 52 | ||||
-rw-r--r-- | drivers/hid/intel-ish-hid/ishtp/bus.h | 5 | ||||
-rw-r--r-- | drivers/hid/intel-ish-hid/ishtp/client-buffers.c | 49 | ||||
-rw-r--r-- | drivers/hid/intel-ish-hid/ishtp/client.c | 24 | ||||
-rw-r--r-- | drivers/hid/intel-ish-hid/ishtp/client.h | 5 | ||||
-rw-r--r-- | drivers/hid/intel-ish-hid/ishtp/ishtp-dev.h | 2 |
6 files changed, 136 insertions, 1 deletions
diff --git a/drivers/hid/intel-ish-hid/ishtp/bus.c b/drivers/hid/intel-ish-hid/ishtp/bus.c index 2623a567ffba..728dc6d4561a 100644 --- a/drivers/hid/intel-ish-hid/ishtp/bus.c +++ b/drivers/hid/intel-ish-hid/ishtp/bus.c @@ -149,6 +149,31 @@ int ishtp_fw_cl_by_uuid(struct ishtp_device *dev, const uuid_le *uuid) EXPORT_SYMBOL(ishtp_fw_cl_by_uuid); /** + * ishtp_fw_cl_get_client() - return client information to client + * @dev: the ishtp device structure + * @uuid: uuid of the client to search + * + * Search firmware client using UUID and reture related client information. + * + * Return: pointer of client information on success, NULL on failure. + */ +struct ishtp_fw_client *ishtp_fw_cl_get_client(struct ishtp_device *dev, + const uuid_le *uuid) +{ + int i; + unsigned long flags; + + spin_lock_irqsave(&dev->fw_clients_lock, flags); + i = ishtp_fw_cl_by_uuid(dev, uuid); + spin_unlock_irqrestore(&dev->fw_clients_lock, flags); + if (i < 0 || dev->fw_clients[i].props.fixed_address) + return NULL; + + return &dev->fw_clients[i]; +} +EXPORT_SYMBOL(ishtp_fw_cl_get_client); + +/** * ishtp_fw_cl_by_id() - return index to fw_clients for client_id * @dev: the ishtp device structure * @client_id: fw client id to search @@ -564,6 +589,33 @@ void ishtp_put_device(struct ishtp_cl_device *cl_device) EXPORT_SYMBOL(ishtp_put_device); /** + * ishtp_set_drvdata() - set client driver data + * @cl_device: client device instance + * @data: driver data need to be set + * + * Set client driver data to cl_device->driver_data. + */ +void ishtp_set_drvdata(struct ishtp_cl_device *cl_device, void *data) +{ + cl_device->driver_data = data; +} +EXPORT_SYMBOL(ishtp_set_drvdata); + +/** + * ishtp_get_drvdata() - get client driver data + * @cl_device: client device instance + * + * Get client driver data from cl_device->driver_data. + * + * Return: pointer of driver data + */ +void *ishtp_get_drvdata(struct ishtp_cl_device *cl_device) +{ + return cl_device->driver_data; +} +EXPORT_SYMBOL(ishtp_get_drvdata); + +/** * ishtp_bus_new_client() - Create a new client * @dev: ISHTP device instance * diff --git a/drivers/hid/intel-ish-hid/ishtp/bus.h b/drivers/hid/intel-ish-hid/ishtp/bus.h index a1ffae7f26ad..b8a5bcc82536 100644 --- a/drivers/hid/intel-ish-hid/ishtp/bus.h +++ b/drivers/hid/intel-ish-hid/ishtp/bus.h @@ -101,6 +101,9 @@ void ishtp_reset_compl_handler(struct ishtp_device *dev); void ishtp_put_device(struct ishtp_cl_device *); void ishtp_get_device(struct ishtp_cl_device *); +void ishtp_set_drvdata(struct ishtp_cl_device *cl_device, void *data); +void *ishtp_get_drvdata(struct ishtp_cl_device *cl_device); + int __ishtp_cl_driver_register(struct ishtp_cl_driver *driver, struct module *owner); #define ishtp_cl_driver_register(driver) \ @@ -110,5 +113,7 @@ void ishtp_cl_driver_unregister(struct ishtp_cl_driver *driver); int ishtp_register_event_cb(struct ishtp_cl_device *device, void (*read_cb)(struct ishtp_cl_device *)); int ishtp_fw_cl_by_uuid(struct ishtp_device *dev, const uuid_le *cuuid); +struct ishtp_fw_client *ishtp_fw_cl_get_client(struct ishtp_device *dev, + const uuid_le *uuid); #endif /* _LINUX_ISHTP_CL_BUS_H */ diff --git a/drivers/hid/intel-ish-hid/ishtp/client-buffers.c b/drivers/hid/intel-ish-hid/ishtp/client-buffers.c index b9b917d2d50d..248651c35497 100644 --- a/drivers/hid/intel-ish-hid/ishtp/client-buffers.c +++ b/drivers/hid/intel-ish-hid/ishtp/client-buffers.c @@ -69,6 +69,8 @@ int ishtp_cl_alloc_tx_ring(struct ishtp_cl *cl) int j; unsigned long flags; + cl->tx_ring_free_size = 0; + /* Allocate pool to free Tx bufs */ for (j = 0; j < cl->tx_ring_size; ++j) { struct ishtp_cl_tx_ring *tx_buf; @@ -85,6 +87,7 @@ int ishtp_cl_alloc_tx_ring(struct ishtp_cl *cl) spin_lock_irqsave(&cl->tx_free_list_spinlock, flags); list_add_tail(&tx_buf->list, &cl->tx_free_list.list); + ++cl->tx_ring_free_size; spin_unlock_irqrestore(&cl->tx_free_list_spinlock, flags); } return 0; @@ -144,6 +147,7 @@ void ishtp_cl_free_tx_ring(struct ishtp_cl *cl) tx_buf = list_entry(cl->tx_free_list.list.next, struct ishtp_cl_tx_ring, list); list_del(&tx_buf->list); + --cl->tx_ring_free_size; kfree(tx_buf->send_buf.data); kfree(tx_buf); } @@ -255,3 +259,48 @@ int ishtp_cl_io_rb_recycle(struct ishtp_cl_rb *rb) return rets; } EXPORT_SYMBOL(ishtp_cl_io_rb_recycle); + +/** + * ishtp_cl_tx_empty() -test whether client device tx buffer is empty + * @cl: Pointer to client device instance + * + * Look client device tx buffer list, and check whether this list is empty + * + * Return: true if client tx buffer list is empty else false + */ +bool ishtp_cl_tx_empty(struct ishtp_cl *cl) +{ + int tx_list_empty; + unsigned long tx_flags; + + spin_lock_irqsave(&cl->tx_list_spinlock, tx_flags); + tx_list_empty = list_empty(&cl->tx_list.list); + spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags); + + return !!tx_list_empty; +} +EXPORT_SYMBOL(ishtp_cl_tx_empty); + +/** + * ishtp_cl_rx_get_rb() -Get a rb from client device rx buffer list + * @cl: Pointer to client device instance + * + * Check client device in-processing buffer list and get a rb from it. + * + * Return: rb pointer if buffer list isn't empty else NULL + */ +struct ishtp_cl_rb *ishtp_cl_rx_get_rb(struct ishtp_cl *cl) +{ + unsigned long rx_flags; + struct ishtp_cl_rb *rb; + + spin_lock_irqsave(&cl->in_process_spinlock, rx_flags); + rb = list_first_entry_or_null(&cl->in_process_list.list, + struct ishtp_cl_rb, list); + if (rb) + list_del_init(&rb->list); + spin_unlock_irqrestore(&cl->in_process_spinlock, rx_flags); + + return rb; +} +EXPORT_SYMBOL(ishtp_cl_rx_get_rb); diff --git a/drivers/hid/intel-ish-hid/ishtp/client.c b/drivers/hid/intel-ish-hid/ishtp/client.c index 007443ef5fca..faeccdb1475b 100644 --- a/drivers/hid/intel-ish-hid/ishtp/client.c +++ b/drivers/hid/intel-ish-hid/ishtp/client.c @@ -22,6 +22,25 @@ #include "hbm.h" #include "client.h" +int ishtp_cl_get_tx_free_buffer_size(struct ishtp_cl *cl) +{ + unsigned long tx_free_flags; + int size; + + spin_lock_irqsave(&cl->tx_free_list_spinlock, tx_free_flags); + size = cl->tx_ring_free_size * cl->device->fw_client->props.max_msg_length; + spin_unlock_irqrestore(&cl->tx_free_list_spinlock, tx_free_flags); + + return size; +} +EXPORT_SYMBOL(ishtp_cl_get_tx_free_buffer_size); + +int ishtp_cl_get_tx_free_rings(struct ishtp_cl *cl) +{ + return cl->tx_ring_free_size; +} +EXPORT_SYMBOL(ishtp_cl_get_tx_free_rings); + /** * ishtp_read_list_flush() - Flush read queue * @cl: ishtp client instance @@ -90,6 +109,7 @@ static void ishtp_cl_init(struct ishtp_cl *cl, struct ishtp_device *dev) cl->rx_ring_size = CL_DEF_RX_RING_SIZE; cl->tx_ring_size = CL_DEF_TX_RING_SIZE; + cl->tx_ring_free_size = cl->tx_ring_size; /* dma */ cl->last_tx_path = CL_TX_PATH_IPC; @@ -577,6 +597,8 @@ int ishtp_cl_send(struct ishtp_cl *cl, uint8_t *buf, size_t length) * max ISHTP message size per client */ list_del_init(&cl_msg->list); + --cl->tx_ring_free_size; + spin_unlock_irqrestore(&cl->tx_free_list_spinlock, tx_free_flags); memcpy(cl_msg->send_buf.data, buf, length); cl_msg->send_buf.size = length; @@ -685,6 +707,7 @@ static void ipc_tx_callback(void *prm) ishtp_write_message(dev, &ishtp_hdr, pmsg); spin_lock_irqsave(&cl->tx_free_list_spinlock, tx_free_flags); list_add_tail(&cl_msg->list, &cl->tx_free_list.list); + ++cl->tx_ring_free_size; spin_unlock_irqrestore(&cl->tx_free_list_spinlock, tx_free_flags); } else { @@ -778,6 +801,7 @@ static void ishtp_cl_send_msg_dma(struct ishtp_device *dev, ishtp_write_message(dev, &hdr, (unsigned char *)&dma_xfer); spin_lock_irqsave(&cl->tx_free_list_spinlock, tx_free_flags); list_add_tail(&cl_msg->list, &cl->tx_free_list.list); + ++cl->tx_ring_free_size; spin_unlock_irqrestore(&cl->tx_free_list_spinlock, tx_free_flags); ++cl->send_msg_cnt_dma; } diff --git a/drivers/hid/intel-ish-hid/ishtp/client.h b/drivers/hid/intel-ish-hid/ishtp/client.h index 79eade547f5d..042f4c4853b1 100644 --- a/drivers/hid/intel-ish-hid/ishtp/client.h +++ b/drivers/hid/intel-ish-hid/ishtp/client.h @@ -84,6 +84,7 @@ struct ishtp_cl { /* Client Tx buffers list */ unsigned int tx_ring_size; struct ishtp_cl_tx_ring tx_list, tx_free_list; + int tx_ring_free_size; spinlock_t tx_list_spinlock; spinlock_t tx_free_list_spinlock; size_t tx_offs; /* Offset in buffer at head of 'tx_list' */ @@ -137,6 +138,8 @@ int ishtp_cl_alloc_rx_ring(struct ishtp_cl *cl); int ishtp_cl_alloc_tx_ring(struct ishtp_cl *cl); void ishtp_cl_free_rx_ring(struct ishtp_cl *cl); void ishtp_cl_free_tx_ring(struct ishtp_cl *cl); +int ishtp_cl_get_tx_free_buffer_size(struct ishtp_cl *cl); +int ishtp_cl_get_tx_free_rings(struct ishtp_cl *cl); /* DMA I/F functions */ void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg, @@ -178,5 +181,7 @@ int ishtp_cl_flush_queues(struct ishtp_cl *cl); /* exported functions from ISHTP client buffer management scope */ int ishtp_cl_io_rb_recycle(struct ishtp_cl_rb *rb); +bool ishtp_cl_tx_empty(struct ishtp_cl *cl); +struct ishtp_cl_rb *ishtp_cl_rx_get_rb(struct ishtp_cl *cl); #endif /* _ISHTP_CLIENT_H_ */ diff --git a/drivers/hid/intel-ish-hid/ishtp/ishtp-dev.h b/drivers/hid/intel-ish-hid/ishtp/ishtp-dev.h index 6a6d927b78b0..e7c6bfefaf9e 100644 --- a/drivers/hid/intel-ish-hid/ishtp/ishtp-dev.h +++ b/drivers/hid/intel-ish-hid/ishtp/ishtp-dev.h @@ -207,7 +207,7 @@ struct ishtp_device { struct work_struct bh_hbm_work; /* IPC write queue */ - struct wr_msg_ctl_info wr_processing_list_head, wr_free_list_head; + struct list_head wr_processing_list, wr_free_list; /* For both processing list and free list */ spinlock_t wr_processing_spinlock; |