static void pch_spi_process_messages()

in spi-topcliff-pch.c [1125:1257]


static void pch_spi_process_messages(struct work_struct *pwork)
{
	struct spi_message *pmsg, *tmp;
	struct pch_spi_data *data;
	int bpw;

	data = container_of(pwork, struct pch_spi_data, work);
	dev_dbg(&data->master->dev, "%s data initialized\n", __func__);

	spin_lock(&data->lock);
	/* check if suspend has been initiated;if yes flush queue */
	if (data->board_dat->suspend_sts || (data->status == STATUS_EXITING)) {
		dev_dbg(&data->master->dev,
			"%s suspend/remove initiated, flushing queue\n", __func__);
		list_for_each_entry_safe(pmsg, tmp, data->queue.next, queue) {
			pmsg->status = -EIO;

			if (pmsg->complete) {
				spin_unlock(&data->lock);
				pmsg->complete(pmsg->context);
				spin_lock(&data->lock);
			}

			/* delete from queue */
			list_del_init(&pmsg->queue);
		}

		spin_unlock(&data->lock);
		return;
	}

	data->bcurrent_msg_processing = true;
	dev_dbg(&data->master->dev,
		"%s Set data->bcurrent_msg_processing= true\n", __func__);

	/* Get the message from the queue and delete it from there. */
	data->current_msg = list_entry(data->queue.next, struct spi_message,
					queue);

	list_del_init(&data->current_msg->queue);

	data->current_msg->status = 0;

	pch_spi_select_chip(data, data->current_msg->spi);

	spin_unlock(&data->lock);

	if (data->use_dma)
		pch_spi_request_dma(data,
				    data->current_msg->spi->bits_per_word);
	pch_spi_writereg(data->master, PCH_SSNXCR, SSN_NO_CONTROL);
	do {
		int cnt;
		/* If we are already processing a message get the next
		transfer structure from the message otherwise retrieve
		the 1st transfer request from the message. */
		spin_lock(&data->lock);
		if (data->cur_trans == NULL) {
			data->cur_trans =
				list_entry(data->current_msg->transfers.next,
					   struct spi_transfer, transfer_list);
			dev_dbg(&data->master->dev,
				"%s :Getting 1st transfer message\n",
				__func__);
		} else {
			data->cur_trans =
				list_entry(data->cur_trans->transfer_list.next,
					   struct spi_transfer, transfer_list);
			dev_dbg(&data->master->dev,
				"%s :Getting next transfer message\n",
				__func__);
		}
		spin_unlock(&data->lock);

		if (!data->cur_trans->len)
			goto out;
		cnt = (data->cur_trans->len - 1) / PCH_BUF_SIZE + 1;
		data->save_total_len = data->cur_trans->len;
		if (data->use_dma) {
			int i;
			char *save_rx_buf = data->cur_trans->rx_buf;

			for (i = 0; i < cnt; i++) {
				pch_spi_handle_dma(data, &bpw);
				if (!pch_spi_start_transfer(data)) {
					data->transfer_complete = true;
					data->current_msg->status = -EIO;
					data->current_msg->complete
						   (data->current_msg->context);
					data->bcurrent_msg_processing = false;
					data->current_msg = NULL;
					data->cur_trans = NULL;
					goto out;
				}
				pch_spi_copy_rx_data_for_dma(data, bpw);
			}
			data->cur_trans->rx_buf = save_rx_buf;
		} else {
			pch_spi_set_tx(data, &bpw);
			pch_spi_set_ir(data);
			pch_spi_copy_rx_data(data, bpw);
			kfree(data->pkt_rx_buff);
			data->pkt_rx_buff = NULL;
			kfree(data->pkt_tx_buff);
			data->pkt_tx_buff = NULL;
		}
		/* increment message count */
		data->cur_trans->len = data->save_total_len;
		data->current_msg->actual_length += data->cur_trans->len;

		dev_dbg(&data->master->dev,
			"%s:data->current_msg->actual_length=%d\n",
			__func__, data->current_msg->actual_length);

		spi_transfer_delay_exec(data->cur_trans);

		spin_lock(&data->lock);

		/* No more transfer in this message. */
		if ((data->cur_trans->transfer_list.next) ==
		    &(data->current_msg->transfers)) {
			pch_spi_nomore_transfer(data);
		}

		spin_unlock(&data->lock);

	} while (data->cur_trans != NULL);

out:
	pch_spi_writereg(data->master, PCH_SSNXCR, SSN_HIGH);
	if (data->use_dma)
		pch_spi_release_dma(data);
}