Commit c9aec052 authored by Felix Manlunas's avatar Felix Manlunas Committed by David S. Miller
Browse files

liquidio: improve soft command handling



1. Set LIO_SC_MAX_TMO_MS as the maximum timeout value for a soft command
   (sc).  All sc's use this value as a hard timeout value. Add expiry_time
   in struct octeon_soft_command to keep the hard timeout value. The field
   wait_time and timeout in struct octeon_soft_command will be obsoleted in
   the last patch of this patch series.
2. Add processing a synchronous sc in sc response thread
   lio_process_ordered_list. The memory allocated for a synchronous sc will
   be freed by lio_process_ordered_list() to the sc pool.
3. Add two response lists for lio_process_ordered_list to process the
   storage allocated for sc's:
   OCTEON_DONE_SC_LIST response list keeps all sc's which will be freed to
   the pool after their requestors have finished processing the responses.
   OCTEON_ZOMBIE_SC_LIST response list keeps all sc's which have got
   LIO_SC_MAX_TMO_MS timeout.
   When an sc gets a hard timeout, lio_process_order_list() will recheck
   its status 1 ms later. If the status has not updated by the firmware at
   that time, the sc will be removed from OCTEON_DONE_SC_LIST response list
   to OCTEON_ZOMBIE_SC_LIST response list. The sc's in the
   OCTEON_ZOMBIE_SC_LIST response list will be freed when the driver is
   unloaded.

Signed-off-by: default avatarWeilin Chang <weilin.chang@cavium.com>
Signed-off-by: default avatarFelix Manlunas <felix.manlunas@cavium.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 0927f71d
Loading
Loading
Loading
Loading
+28 −3
Original line number Diff line number Diff line
@@ -1037,12 +1037,12 @@ static void octeon_destroy_resources(struct octeon_device *oct)

		/* fallthrough */
	case OCT_DEV_IO_QUEUES_DONE:
		if (wait_for_pending_requests(oct))
			dev_err(&oct->pci_dev->dev, "There were pending requests\n");

		if (lio_wait_for_instr_fetch(oct))
			dev_err(&oct->pci_dev->dev, "IQ had pending instructions\n");

		if (wait_for_pending_requests(oct))
			dev_err(&oct->pci_dev->dev, "There were pending requests\n");

		/* Disable the input and output queues now. No more packets will
		 * arrive from Octeon, but we should wait for all packet
		 * processing to finish.
@@ -1052,6 +1052,31 @@ static void octeon_destroy_resources(struct octeon_device *oct)
		if (lio_wait_for_oq_pkts(oct))
			dev_err(&oct->pci_dev->dev, "OQ had pending packets\n");

		/* Force all requests waiting to be fetched by OCTEON to
		 * complete.
		 */
		for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct); i++) {
			struct octeon_instr_queue *iq;

			if (!(oct->io_qmask.iq & BIT_ULL(i)))
				continue;
			iq = oct->instr_queue[i];

			if (atomic_read(&iq->instr_pending)) {
				spin_lock_bh(&iq->lock);
				iq->fill_cnt = 0;
				iq->octeon_read_index = iq->host_write_index;
				iq->stats.instr_processed +=
					atomic_read(&iq->instr_pending);
				lio_process_iq_request_list(oct, iq, 0);
				spin_unlock_bh(&iq->lock);
			}
		}

		lio_process_ordered_list(oct, 1);
		octeon_free_sc_done_list(oct);
		octeon_free_sc_zombie_list(oct);

	/* fallthrough */
	case OCT_DEV_INTR_SET_DONE:
		/* Disable interrupts  */
+30 −4
Original line number Diff line number Diff line
@@ -471,12 +471,12 @@ static void octeon_destroy_resources(struct octeon_device *oct)
	case OCT_DEV_HOST_OK:
		/* fallthrough */
	case OCT_DEV_IO_QUEUES_DONE:
		if (wait_for_pending_requests(oct))
			dev_err(&oct->pci_dev->dev, "There were pending requests\n");

		if (lio_wait_for_instr_fetch(oct))
			dev_err(&oct->pci_dev->dev, "IQ had pending instructions\n");

		if (wait_for_pending_requests(oct))
			dev_err(&oct->pci_dev->dev, "There were pending requests\n");

		/* Disable the input and output queues now. No more packets will
		 * arrive from Octeon, but we should wait for all packet
		 * processing to finish.
@@ -485,6 +485,32 @@ static void octeon_destroy_resources(struct octeon_device *oct)

		if (lio_wait_for_oq_pkts(oct))
			dev_err(&oct->pci_dev->dev, "OQ had pending packets\n");

		/* Force all requests waiting to be fetched by OCTEON to
		 * complete.
		 */
		for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct); i++) {
			struct octeon_instr_queue *iq;

			if (!(oct->io_qmask.iq & BIT_ULL(i)))
				continue;
			iq = oct->instr_queue[i];

			if (atomic_read(&iq->instr_pending)) {
				spin_lock_bh(&iq->lock);
				iq->fill_cnt = 0;
				iq->octeon_read_index = iq->host_write_index;
				iq->stats.instr_processed +=
					atomic_read(&iq->instr_pending);
				lio_process_iq_request_list(oct, iq, 0);
				spin_unlock_bh(&iq->lock);
			}
		}

		lio_process_ordered_list(oct, 1);
		octeon_free_sc_done_list(oct);
		octeon_free_sc_zombie_list(oct);

	/* fall through */
	case OCT_DEV_INTR_SET_DONE:
		/* Disable interrupts  */
+1 −1
Original line number Diff line number Diff line
@@ -440,7 +440,7 @@ struct octeon_config {
/* Response lists - 1 ordered, 1 unordered-blocking, 1 unordered-nonblocking
 * NoResponse Lists are now maintained with each IQ. (Dec' 2007).
 */
#define MAX_RESPONSE_LISTS           4
#define MAX_RESPONSE_LISTS           6

/* Opcode hash bits. The opcode is hashed on the lower 6-bits to lookup the
 * dispatch table.
+11 −0
Original line number Diff line number Diff line
@@ -294,11 +294,20 @@ struct octeon_soft_command {
	/** Time out and callback */
	size_t wait_time;
	size_t timeout;
	size_t expiry_time;

	u32 iq_no;
	void (*callback)(struct octeon_device *, u32, void *);
	void *callback_arg;

	int caller_is_done;
	u32 sc_status;
	struct completion complete;
};

/* max timeout (in milli sec) for soft request */
#define LIO_SC_MAX_TMO_MS       60000

/** Maximum number of buffers to allocate into soft command buffer pool
 */
#define  MAX_SOFT_COMMAND_BUFFERS	256
@@ -319,6 +328,8 @@ struct octeon_sc_buffer_pool {
		(((octeon_dev_ptr)->instr_queue[iq_no]->stats.field) += count)

int octeon_setup_sc_buffer_pool(struct octeon_device *oct);
int octeon_free_sc_done_list(struct octeon_device *oct);
int octeon_free_sc_zombie_list(struct octeon_device *oct);
int octeon_free_sc_buffer_pool(struct octeon_device *oct);
struct octeon_soft_command *
	octeon_alloc_soft_command(struct octeon_device *oct,
+1 −2
Original line number Diff line number Diff line
@@ -75,8 +75,7 @@ octeon_alloc_soft_command_resp(struct octeon_device *oct,
	else
		sc->cmd.cmd2.rptr =  sc->dmarptr;

	sc->wait_time = 1000;
	sc->timeout = jiffies + sc->wait_time;
	sc->expiry_time = jiffies + msecs_to_jiffies(LIO_SC_MAX_TMO_MS);

	return sc;
}
Loading