On 7 November 2014 20:22, Ashwin Chaugule ashwin.chaugule@linaro.org wrote:
+struct mbox_chan *pcc_mbox_request_channel(struct mbox_client *cl,
int index)+{
struct device *dev = pcc_mbox_ctrl.dev;struct mbox_chan *chan;unsigned long flags;/** Each PCC Subspace is a Mailbox Channel.* The PCC Clients get their PCC Subspace ID* from their own tables and pass it here.* This returns a pointer to the PCC subspace* for the Client to operate on.*/chan = &pcc_mbox_chan[index];
You are mapping 'Type' of a client directly onto SubSpace-ID of the channel allocated. If two clients need an instance of, say, Generic-Communications-Channel i.e, Type-0, this will not work. If no two clients can ask the same channel, MAX_PCC_SUBSPACES should be limited to max 'Type' value defined in ACPI specs (just 2 in ACPI-5.1).
if (!chan || chan->cl) {dev_err(dev, "%s: PCC mailbox not free\n", __func__);return ERR_PTR(-EBUSY);}spin_lock_irqsave(&chan->lock, flags);chan->msg_free = 0;chan->msg_count = 0;chan->active_req = NULL;chan->cl = cl;init_completion(&chan->tx_complete);if (chan->txdone_method == TXDONE_BY_POLL && cl->knows_txdone)chan->txdone_method |= TXDONE_BY_ACK;spin_unlock_irqrestore(&chan->lock, flags);return chan;+} +EXPORT_SYMBOL_GPL(pcc_mbox_request_channel);
Nothing PCC specific here. All you have done is define a new api just to pick an element from the array. You simply needed the mbox_request_channel() let you through to controller.
+void pcc_mbox_free_channel(struct mbox_chan *chan) +{
unsigned long flags;if (!chan || !chan->cl)return;spin_lock_irqsave(&chan->lock, flags);chan->cl = NULL;chan->active_req = NULL;if (chan->txdone_method == (TXDONE_BY_POLL | TXDONE_BY_ACK))chan->txdone_method = TXDONE_BY_POLL;spin_unlock_irqrestore(&chan->lock, flags);+} +EXPORT_SYMBOL_GPL(pcc_mbox_free_channel);
Ditto, nothing PCC in this new PCC specific api.
+/**
- pcc_send_data - Called from Mailbox Controller code to finally
transmit data over channel.
- @chan: Pointer to Mailbox channel over which to send data.
- @data: Actual data to be written over channel.
- Return: Err if something failed else 0 for success.
- */
+static int pcc_send_data(struct mbox_chan *chan, void *data) +{
struct acpi_pcct_hw_reduced *pcct_ss = chan->con_priv;struct acpi_pcct_shared_memory *generic_comm_base =(struct acpi_pcct_shared_memory *) pcct_ss->base_address;struct acpi_generic_address doorbell;u64 doorbell_preserve;u64 doorbell_val;u64 doorbell_write;u16 cmd = *(u16 *) data;u16 ss_idx = -1;ss_idx = get_subspace_id(chan);if (ss_idx < 0) {pr_err("Invalid Subspace ID from PCC client\n");return -EINVAL;}doorbell = pcct_ss->doorbell_register;doorbell_preserve = pcct_ss->preserve_mask;doorbell_write = pcct_ss->write_mask;/* Write to the shared comm region. */writew(cmd, &generic_comm_base->command);/* Write Subspace MAGIC value so platform can identify destination. */writel((PCCS_SS_SIG_MAGIC | ss_idx), &generic_comm_base->signature);/* Flip CMD COMPLETE bit */writew(0, &generic_comm_base->status);/* Sync notification from OSPM to Platform. */acpi_read(&doorbell_val, &doorbell);acpi_write((doorbell_val & doorbell_preserve) | doorbell_write,&doorbell);return 0;+}
+static struct mbox_chan_ops pcc_chan_ops = {
.send_data = pcc_send_data,.last_tx_done = pcc_tx_done,+};
+/**
- parse_pcc_subspace - Parse the PCC table and extract PCC subspace
entries. There should be one entry per PCC client.
- @header: Pointer to the ACPI subtable header under the PCCT.
- @end: End of subtable entry.
- Return: 0 for Success, else errno.
- This gets called for each entry in the PCC table.
- */
+static int parse_pcc_subspace(struct acpi_subtable_header *header,
const unsigned long end)+{
struct acpi_pcct_hw_reduced *pcct_ss;if (pcc_mbox_ctrl.num_chans <= MAX_PCC_SUBSPACES) {pcct_ss = (struct acpi_pcct_hw_reduced *) header;if (pcct_ss->header.type !=ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE) {pr_err("Incorrect PCC Subspace type detected\n");return -EINVAL;}
The driver supports only ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE client ?!
-Jassi