Skip to content

Commit a3a44d2

Browse files
EvenxfJiri Kosina
authored andcommitted
HID: Intel-ish-hid: Ishtp: Add helper functions for client connection
For every ishtp client driver during initialization state, the flow is: 1 - Allocate an ISHTP client instance 2 - Reserve a host id and link the client instance 3 - Search a firmware client using UUID and get related client information 4 - Bind firmware client id to the ISHTP client instance 5 - Set the state the ISHTP client instance to CONNECTING 6 - Send connect request to firmware 7 - Register event callback for messages from the firmware During deinitizalization state, the flow is: 9 - Set the state the ISHTP client instance to ISHTP_CL_DISCONNECTING 10 - Issue disconnect request to firmware 11 - Unlike the client instance 12 - Flush message queue 13 - Free ISHTP client instance Step 2-7 are identical to the steps of client driver initialization and driver reset flow, but reallocation of the RX/TX ring buffers can be avoided in reset flow. Also for step 9-12, they are identical to the steps of client driver failure handling after connect request, driver reset flow and driver removing. So, add two helper functions to simplify client driver code. ishtp_cl_establish_connection() ishtp_cl_destroy_connection() No functional changes are expected. Signed-off-by: Even Xu <[email protected]> Acked-by: Srinivas Pandruvada <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent 1f34279 commit a3a44d2

File tree

2 files changed

+177
-11
lines changed

2 files changed

+177
-11
lines changed

drivers/hid/intel-ish-hid/ishtp/client.c

Lines changed: 174 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -339,16 +339,17 @@ static bool ishtp_cl_is_other_connecting(struct ishtp_cl *cl)
339339
}
340340

341341
/**
342-
* ishtp_cl_connect() - Send connect request to firmware
342+
* ishtp_cl_connect_to_fw() - Send connect request to firmware
343343
* @cl: client device instance
344344
*
345-
* Send a connect request for a client to firmware. If successful it will
346-
* RX and TX ring buffers
345+
* Send a connect request to the firmware and wait for firmware response.
346+
* If there is successful connection response from the firmware, change
347+
* client state to ISHTP_CL_CONNECTED, and bind client to related
348+
* firmware client_id.
347349
*
348-
* Return: 0 if successful connect response from the firmware and able
349-
* to bind and allocate ring buffers or error code on failure
350+
* Return: 0 for success and error code on failure
350351
*/
351-
int ishtp_cl_connect(struct ishtp_cl *cl)
352+
static int ishtp_cl_connect_to_fw(struct ishtp_cl *cl)
352353
{
353354
struct ishtp_device *dev;
354355
int rets;
@@ -358,8 +359,6 @@ int ishtp_cl_connect(struct ishtp_cl *cl)
358359

359360
dev = cl->dev;
360361

361-
dev->print_log(dev, "%s() current_state = %d\n", __func__, cl->state);
362-
363362
if (ishtp_cl_is_other_connecting(cl)) {
364363
dev->print_log(dev, "%s() Busy\n", __func__);
365364
return -EBUSY;
@@ -405,6 +404,38 @@ int ishtp_cl_connect(struct ishtp_cl *cl)
405404
return rets;
406405
}
407406

407+
return rets;
408+
}
409+
410+
/**
411+
* ishtp_cl_connect() - Build connection with firmware
412+
* @cl: client device instance
413+
*
414+
* Call ishtp_cl_connect_to_fw() to connect and bind to firmware. If successful,
415+
* allocate RX and TX ring buffers, and start flow control with firmware to
416+
* start communication.
417+
*
418+
* Return: 0 if there is successful connection to the firmware, allocate
419+
* ring buffers.
420+
*/
421+
int ishtp_cl_connect(struct ishtp_cl *cl)
422+
{
423+
struct ishtp_device *dev;
424+
int rets;
425+
426+
if (!cl || !cl->dev)
427+
return -ENODEV;
428+
429+
dev = cl->dev;
430+
431+
dev->print_log(dev, "%s() current_state = %d\n", __func__, cl->state);
432+
433+
rets = ishtp_cl_connect_to_fw(cl);
434+
if (rets) {
435+
dev->print_log(dev, "%s() Connect to fw failed\n", __func__);
436+
return rets;
437+
}
438+
408439
rets = ishtp_cl_alloc_rx_ring(cl);
409440
if (rets) {
410441
dev->print_log(dev, "%s() Alloc RX ring failed\n", __func__);
@@ -422,15 +453,147 @@ int ishtp_cl_connect(struct ishtp_cl *cl)
422453
return rets;
423454
}
424455

425-
/* Upon successful connection and allocation, emit flow-control */
456+
/*
457+
* Upon successful connection and allocation, start flow-control.
458+
*/
426459
rets = ishtp_cl_read_start(cl);
427460

428-
dev->print_log(dev, "%s() successful\n", __func__);
429-
430461
return rets;
431462
}
432463
EXPORT_SYMBOL(ishtp_cl_connect);
433464

465+
/**
466+
* ishtp_cl_establish_connection() - Establish connection with the firmware
467+
* @cl: client device instance
468+
* @uuid: uuid of the client to search
469+
* @tx_size: TX ring buffer size
470+
* @rx_size: RX ring buffer size
471+
* @reset: true if called for reset connection, otherwise for first connection
472+
*
473+
* This is a helper function for client driver to build connection with firmware.
474+
* If it's first time connecting to the firmware, set reset to false, this
475+
* function will link client to bus, find client id and send connect request to
476+
* the firmware.
477+
*
478+
* If it's called for reset handler where client lost connection after
479+
* firmware reset, set reset to true, this function will reinit client state and
480+
* establish connection again. In this case, this function reuses current client
481+
* structure and ring buffers to avoid allocation failure and memory fragments.
482+
*
483+
* Return: 0 for successful connection with the firmware,
484+
* or error code on failure
485+
*/
486+
int ishtp_cl_establish_connection(struct ishtp_cl *cl, const guid_t *uuid,
487+
int tx_size, int rx_size, bool reset)
488+
{
489+
struct ishtp_device *dev;
490+
struct ishtp_fw_client *fw_client;
491+
int rets;
492+
493+
if (!cl || !cl->dev)
494+
return -ENODEV;
495+
496+
dev = cl->dev;
497+
498+
ishtp_set_connection_state(cl, ISHTP_CL_INITIALIZING);
499+
500+
/* reinit ishtp_cl structure if call for reset */
501+
if (reset) {
502+
cl->host_client_id = 0;
503+
cl->fw_client_id = 0;
504+
cl->ishtp_flow_ctrl_creds = 0;
505+
cl->out_flow_ctrl_creds = 0;
506+
507+
cl->last_tx_path = CL_TX_PATH_IPC;
508+
cl->last_dma_acked = 1;
509+
cl->last_dma_addr = NULL;
510+
cl->last_ipc_acked = 1;
511+
512+
cl->sending = 0;
513+
cl->err_send_msg = 0;
514+
cl->err_send_fc = 0;
515+
516+
cl->send_msg_cnt_ipc = 0;
517+
cl->send_msg_cnt_dma = 0;
518+
cl->recv_msg_cnt_ipc = 0;
519+
cl->recv_msg_cnt_dma = 0;
520+
cl->recv_msg_num_frags = 0;
521+
cl->ishtp_flow_ctrl_cnt = 0;
522+
cl->out_flow_ctrl_cnt = 0;
523+
}
524+
525+
/* link to bus */
526+
rets = ishtp_cl_link(cl);
527+
if (rets) {
528+
dev->print_log(dev, "%s() ishtp_cl_link failed\n", __func__);
529+
return rets;
530+
}
531+
532+
/* find firmware client */
533+
fw_client = ishtp_fw_cl_get_client(dev, uuid);
534+
if (!fw_client) {
535+
dev->print_log(dev,
536+
"%s() ish client uuid not found\n", __func__);
537+
return -ENOENT;
538+
}
539+
540+
ishtp_set_tx_ring_size(cl, tx_size);
541+
ishtp_set_rx_ring_size(cl, rx_size);
542+
543+
ishtp_cl_set_fw_client_id(cl, ishtp_get_fw_client_id(fw_client));
544+
545+
ishtp_set_connection_state(cl, ISHTP_CL_CONNECTING);
546+
547+
/*
548+
* For reset case, not allocate tx/rx ring buffer which are already
549+
* done in ishtp_cl_connect() during first connection.
550+
*/
551+
if (reset) {
552+
rets = ishtp_cl_connect_to_fw(cl);
553+
if (!rets)
554+
rets = ishtp_cl_read_start(cl);
555+
else
556+
dev->print_log(dev,
557+
"%s() connect to fw failed\n", __func__);
558+
} else {
559+
rets = ishtp_cl_connect(cl);
560+
}
561+
562+
return rets;
563+
}
564+
EXPORT_SYMBOL(ishtp_cl_establish_connection);
565+
566+
/**
567+
* ishtp_cl_destroy_connection() - Disconnect with the firmware
568+
* @cl: client device instance
569+
* @reset: true if called for firmware reset, false for normal disconnection
570+
*
571+
* This is a helper function for client driver to disconnect with firmware,
572+
* unlink to bus and flush message queue.
573+
*/
574+
void ishtp_cl_destroy_connection(struct ishtp_cl *cl, bool reset)
575+
{
576+
if (!cl)
577+
return;
578+
579+
if (reset) {
580+
/*
581+
* For reset case, connection is already lost during fw reset.
582+
* Just set state to DISCONNECTED is enough.
583+
*/
584+
ishtp_set_connection_state(cl, ISHTP_CL_DISCONNECTED);
585+
} else {
586+
if (cl->state != ISHTP_CL_DISCONNECTED) {
587+
ishtp_set_connection_state(cl, ISHTP_CL_DISCONNECTING);
588+
ishtp_cl_disconnect(cl);
589+
}
590+
}
591+
592+
ishtp_cl_unlink(cl);
593+
ishtp_cl_flush_queues(cl);
594+
}
595+
EXPORT_SYMBOL(ishtp_cl_destroy_connection);
596+
434597
/**
435598
* ishtp_cl_read_start() - Prepare to read client message
436599
* @cl: client device instance

include/linux/intel-ish-client-if.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ int ishtp_cl_link(struct ishtp_cl *cl);
9494
void ishtp_cl_unlink(struct ishtp_cl *cl);
9595
int ishtp_cl_disconnect(struct ishtp_cl *cl);
9696
int ishtp_cl_connect(struct ishtp_cl *cl);
97+
int ishtp_cl_establish_connection(struct ishtp_cl *cl, const guid_t *uuid,
98+
int tx_size, int rx_size, bool reset);
99+
void ishtp_cl_destroy_connection(struct ishtp_cl *cl, bool reset);
97100
int ishtp_cl_send(struct ishtp_cl *cl, uint8_t *buf, size_t length);
98101
int ishtp_cl_flush_queues(struct ishtp_cl *cl);
99102
int ishtp_cl_io_rb_recycle(struct ishtp_cl_rb *rb);

0 commit comments

Comments
 (0)