1  /**********************************************************************
2   * Author: Cavium, Inc.
3   *
4   * Contact: support@cavium.com
5   *          Please include "LiquidIO" in the subject.
6   *
7   * Copyright (c) 2003-2016 Cavium, Inc.
8   *
9   * This file is free software; you can redistribute it and/or modify
10   * it under the terms of the GNU General Public License, Version 2, as
11   * published by the Free Software Foundation.
12   *
13   * This file is distributed in the hope that it will be useful, but
14   * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
15   * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
16   * NONINFRINGEMENT.  See the GNU General Public License for more details.
17   ***********************************************************************/
18  #include <linux/pci.h>
19  #include <linux/netdevice.h>
20  #include "liquidio_common.h"
21  #include "octeon_droq.h"
22  #include "octeon_iq.h"
23  #include "response_manager.h"
24  #include "octeon_device.h"
25  #include "octeon_main.h"
26  #include "octeon_mailbox.h"
27  #include "cn23xx_pf_device.h"
28  
29  /**
30   * octeon_mbox_read:
31   * @mbox: Pointer mailbox
32   *
33   * Reads the 8-bytes of data from the mbox register
34   * Writes back the acknowldgement inidcating completion of read
35   */
octeon_mbox_read(struct octeon_mbox * mbox)36  int octeon_mbox_read(struct octeon_mbox *mbox)
37  {
38  	union octeon_mbox_message msg;
39  	int ret = 0;
40  
41  	spin_lock(&mbox->lock);
42  
43  	msg.u64 = readq(mbox->mbox_read_reg);
44  
45  	if ((msg.u64 == OCTEON_PFVFACK) || (msg.u64 == OCTEON_PFVFSIG)) {
46  		spin_unlock(&mbox->lock);
47  		return 0;
48  	}
49  
50  	if (mbox->state & OCTEON_MBOX_STATE_REQUEST_RECEIVING) {
51  		mbox->mbox_req.data[mbox->mbox_req.recv_len - 1] = msg.u64;
52  		mbox->mbox_req.recv_len++;
53  	} else {
54  		if (mbox->state & OCTEON_MBOX_STATE_RESPONSE_RECEIVING) {
55  			mbox->mbox_resp.data[mbox->mbox_resp.recv_len - 1] =
56  				msg.u64;
57  			mbox->mbox_resp.recv_len++;
58  		} else {
59  			if ((mbox->state & OCTEON_MBOX_STATE_IDLE) &&
60  			    (msg.s.type == OCTEON_MBOX_REQUEST)) {
61  				mbox->state &= ~OCTEON_MBOX_STATE_IDLE;
62  				mbox->state |=
63  				    OCTEON_MBOX_STATE_REQUEST_RECEIVING;
64  				mbox->mbox_req.msg.u64 = msg.u64;
65  				mbox->mbox_req.q_no = mbox->q_no;
66  				mbox->mbox_req.recv_len = 1;
67  			} else {
68  				if ((mbox->state &
69  				     OCTEON_MBOX_STATE_RESPONSE_PENDING) &&
70  				    (msg.s.type == OCTEON_MBOX_RESPONSE)) {
71  					mbox->state &=
72  					    ~OCTEON_MBOX_STATE_RESPONSE_PENDING;
73  					mbox->state |=
74  					    OCTEON_MBOX_STATE_RESPONSE_RECEIVING
75  					    ;
76  					mbox->mbox_resp.msg.u64 = msg.u64;
77  					mbox->mbox_resp.q_no = mbox->q_no;
78  					mbox->mbox_resp.recv_len = 1;
79  				} else {
80  					writeq(OCTEON_PFVFERR,
81  					       mbox->mbox_read_reg);
82  					mbox->state |= OCTEON_MBOX_STATE_ERROR;
83  					spin_unlock(&mbox->lock);
84  					return 1;
85  				}
86  			}
87  		}
88  	}
89  
90  	if (mbox->state & OCTEON_MBOX_STATE_REQUEST_RECEIVING) {
91  		if (mbox->mbox_req.recv_len < mbox->mbox_req.msg.s.len) {
92  			ret = 0;
93  		} else {
94  			mbox->state &= ~OCTEON_MBOX_STATE_REQUEST_RECEIVING;
95  			mbox->state |= OCTEON_MBOX_STATE_REQUEST_RECEIVED;
96  			ret = 1;
97  		}
98  	} else {
99  		if (mbox->state & OCTEON_MBOX_STATE_RESPONSE_RECEIVING) {
100  			if (mbox->mbox_resp.recv_len <
101  			    mbox->mbox_resp.msg.s.len) {
102  				ret = 0;
103  			} else {
104  				mbox->state &=
105  				    ~OCTEON_MBOX_STATE_RESPONSE_RECEIVING;
106  				mbox->state |=
107  				    OCTEON_MBOX_STATE_RESPONSE_RECEIVED;
108  				ret = 1;
109  			}
110  		} else {
111  			WARN_ON(1);
112  		}
113  	}
114  
115  	writeq(OCTEON_PFVFACK, mbox->mbox_read_reg);
116  
117  	spin_unlock(&mbox->lock);
118  
119  	return ret;
120  }
121  
122  /**
123   * octeon_mbox_write:
124   * @oct: Pointer Octeon Device
125   * @mbox_cmd: Cmd to send to mailbox.
126   *
127   * Populates the queue specific mbox structure
128   * with cmd information.
129   * Write the cmd to mbox register
130   */
octeon_mbox_write(struct octeon_device * oct,struct octeon_mbox_cmd * mbox_cmd)131  int octeon_mbox_write(struct octeon_device *oct,
132  		      struct octeon_mbox_cmd *mbox_cmd)
133  {
134  	struct octeon_mbox *mbox = oct->mbox[mbox_cmd->q_no];
135  	u32 count, i, ret = OCTEON_MBOX_STATUS_SUCCESS;
136  	long timeout = LIO_MBOX_WRITE_WAIT_TIME;
137  	unsigned long flags;
138  
139  	spin_lock_irqsave(&mbox->lock, flags);
140  
141  	if ((mbox_cmd->msg.s.type == OCTEON_MBOX_RESPONSE) &&
142  	    !(mbox->state & OCTEON_MBOX_STATE_REQUEST_RECEIVED)) {
143  		spin_unlock_irqrestore(&mbox->lock, flags);
144  		return OCTEON_MBOX_STATUS_FAILED;
145  	}
146  
147  	if ((mbox_cmd->msg.s.type == OCTEON_MBOX_REQUEST) &&
148  	    !(mbox->state & OCTEON_MBOX_STATE_IDLE)) {
149  		spin_unlock_irqrestore(&mbox->lock, flags);
150  		return OCTEON_MBOX_STATUS_BUSY;
151  	}
152  
153  	if (mbox_cmd->msg.s.type == OCTEON_MBOX_REQUEST) {
154  		memcpy(&mbox->mbox_resp, mbox_cmd,
155  		       sizeof(struct octeon_mbox_cmd));
156  		mbox->state = OCTEON_MBOX_STATE_RESPONSE_PENDING;
157  	}
158  
159  	spin_unlock_irqrestore(&mbox->lock, flags);
160  
161  	count = 0;
162  
163  	while (readq(mbox->mbox_write_reg) != OCTEON_PFVFSIG) {
164  		schedule_timeout_uninterruptible(timeout);
165  		if (count++ == LIO_MBOX_WRITE_WAIT_CNT) {
166  			ret = OCTEON_MBOX_STATUS_FAILED;
167  			break;
168  		}
169  	}
170  
171  	if (ret == OCTEON_MBOX_STATUS_SUCCESS) {
172  		writeq(mbox_cmd->msg.u64, mbox->mbox_write_reg);
173  		for (i = 0; i < (u32)(mbox_cmd->msg.s.len - 1); i++) {
174  			count = 0;
175  			while (readq(mbox->mbox_write_reg) !=
176  			       OCTEON_PFVFACK) {
177  				schedule_timeout_uninterruptible(timeout);
178  				if (count++ == LIO_MBOX_WRITE_WAIT_CNT) {
179  					ret = OCTEON_MBOX_STATUS_FAILED;
180  					break;
181  				}
182  			}
183  			if (ret == OCTEON_MBOX_STATUS_SUCCESS)
184  				writeq(mbox_cmd->data[i], mbox->mbox_write_reg);
185  			else
186  				break;
187  		}
188  	}
189  
190  	spin_lock_irqsave(&mbox->lock, flags);
191  	if (mbox_cmd->msg.s.type == OCTEON_MBOX_RESPONSE) {
192  		mbox->state = OCTEON_MBOX_STATE_IDLE;
193  		writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
194  	} else {
195  		if ((!mbox_cmd->msg.s.resp_needed) ||
196  		    (ret == OCTEON_MBOX_STATUS_FAILED)) {
197  			mbox->state &= ~OCTEON_MBOX_STATE_RESPONSE_PENDING;
198  			if (!(mbox->state &
199  			      (OCTEON_MBOX_STATE_REQUEST_RECEIVING |
200  			       OCTEON_MBOX_STATE_REQUEST_RECEIVED)))
201  				mbox->state = OCTEON_MBOX_STATE_IDLE;
202  		}
203  	}
204  	spin_unlock_irqrestore(&mbox->lock, flags);
205  
206  	return ret;
207  }
208  
get_vf_stats(struct octeon_device * oct,struct oct_vf_stats * stats)209  static void get_vf_stats(struct octeon_device *oct,
210  			 struct oct_vf_stats *stats)
211  {
212  	int i;
213  
214  	for (i = 0; i < oct->num_iqs; i++) {
215  		if (!oct->instr_queue[i])
216  			continue;
217  		stats->tx_packets += oct->instr_queue[i]->stats.tx_done;
218  		stats->tx_bytes += oct->instr_queue[i]->stats.tx_tot_bytes;
219  	}
220  
221  	for (i = 0; i < oct->num_oqs; i++) {
222  		if (!oct->droq[i])
223  			continue;
224  		stats->rx_packets += oct->droq[i]->stats.rx_pkts_received;
225  		stats->rx_bytes += oct->droq[i]->stats.rx_bytes_received;
226  	}
227  }
228  
229  /**
230   * octeon_mbox_process_cmd:
231   * @mbox: Pointer mailbox
232   * @mbox_cmd: Pointer to command received
233   *
234   * Process the cmd received in mbox
235   */
octeon_mbox_process_cmd(struct octeon_mbox * mbox,struct octeon_mbox_cmd * mbox_cmd)236  static int octeon_mbox_process_cmd(struct octeon_mbox *mbox,
237  				   struct octeon_mbox_cmd *mbox_cmd)
238  {
239  	struct octeon_device *oct = mbox->oct_dev;
240  
241  	switch (mbox_cmd->msg.s.cmd) {
242  	case OCTEON_VF_ACTIVE:
243  		dev_dbg(&oct->pci_dev->dev, "got vfactive sending data back\n");
244  		mbox_cmd->msg.s.type = OCTEON_MBOX_RESPONSE;
245  		mbox_cmd->msg.s.resp_needed = 1;
246  		mbox_cmd->msg.s.len = 2;
247  		mbox_cmd->data[0] = 0; /* VF version is in mbox_cmd->data[0] */
248  		((struct lio_version *)&mbox_cmd->data[0])->major =
249  			LIQUIDIO_BASE_MAJOR_VERSION;
250  		((struct lio_version *)&mbox_cmd->data[0])->minor =
251  			LIQUIDIO_BASE_MINOR_VERSION;
252  		((struct lio_version *)&mbox_cmd->data[0])->micro =
253  			LIQUIDIO_BASE_MICRO_VERSION;
254  		memcpy(mbox_cmd->msg.s.params, (uint8_t *)&oct->pfvf_hsword, 6);
255  		/* Sending core cofig info to the corresponding active VF.*/
256  		octeon_mbox_write(oct, mbox_cmd);
257  		break;
258  
259  	case OCTEON_VF_FLR_REQUEST:
260  		dev_info(&oct->pci_dev->dev,
261  			 "got a request for FLR from VF that owns DPI ring %u\n",
262  			 mbox->q_no);
263  		pcie_flr(oct->sriov_info.dpiring_to_vfpcidev_lut[mbox->q_no]);
264  		break;
265  
266  	case OCTEON_PF_CHANGED_VF_MACADDR:
267  		if (OCTEON_CN23XX_VF(oct))
268  			octeon_pf_changed_vf_macaddr(oct,
269  						     mbox_cmd->msg.s.params);
270  		break;
271  
272  	case OCTEON_GET_VF_STATS:
273  		dev_dbg(&oct->pci_dev->dev, "Got VF stats request. Sending data back\n");
274  		mbox_cmd->msg.s.type = OCTEON_MBOX_RESPONSE;
275  		mbox_cmd->msg.s.resp_needed = 1;
276  		mbox_cmd->msg.s.len = 1 +
277  			sizeof(struct oct_vf_stats) / sizeof(u64);
278  		get_vf_stats(oct, (struct oct_vf_stats *)mbox_cmd->data);
279  		octeon_mbox_write(oct, mbox_cmd);
280  		break;
281  	default:
282  		break;
283  	}
284  	return 0;
285  }
286  
287  /**
288   * octeon_mbox_process_message
289   * @mbox: mailbox
290   *
291   * Process the received mbox message.
292   */
octeon_mbox_process_message(struct octeon_mbox * mbox)293  int octeon_mbox_process_message(struct octeon_mbox *mbox)
294  {
295  	struct octeon_mbox_cmd mbox_cmd;
296  	unsigned long flags;
297  
298  	spin_lock_irqsave(&mbox->lock, flags);
299  
300  	if (mbox->state & OCTEON_MBOX_STATE_ERROR) {
301  		if (mbox->state & (OCTEON_MBOX_STATE_RESPONSE_PENDING |
302  				   OCTEON_MBOX_STATE_RESPONSE_RECEIVING)) {
303  			memcpy(&mbox_cmd, &mbox->mbox_resp,
304  			       sizeof(struct octeon_mbox_cmd));
305  			mbox->state = OCTEON_MBOX_STATE_IDLE;
306  			writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
307  			spin_unlock_irqrestore(&mbox->lock, flags);
308  			mbox_cmd.recv_status = 1;
309  			if (mbox_cmd.fn)
310  				mbox_cmd.fn(mbox->oct_dev, &mbox_cmd,
311  					    mbox_cmd.fn_arg);
312  			return 0;
313  		}
314  
315  		mbox->state = OCTEON_MBOX_STATE_IDLE;
316  		writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
317  		spin_unlock_irqrestore(&mbox->lock, flags);
318  		return 0;
319  	}
320  
321  	if (mbox->state & OCTEON_MBOX_STATE_RESPONSE_RECEIVED) {
322  		memcpy(&mbox_cmd, &mbox->mbox_resp,
323  		       sizeof(struct octeon_mbox_cmd));
324  		mbox->state = OCTEON_MBOX_STATE_IDLE;
325  		writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
326  		spin_unlock_irqrestore(&mbox->lock, flags);
327  		mbox_cmd.recv_status = 0;
328  		if (mbox_cmd.fn)
329  			mbox_cmd.fn(mbox->oct_dev, &mbox_cmd, mbox_cmd.fn_arg);
330  		return 0;
331  	}
332  
333  	if (mbox->state & OCTEON_MBOX_STATE_REQUEST_RECEIVED) {
334  		memcpy(&mbox_cmd, &mbox->mbox_req,
335  		       sizeof(struct octeon_mbox_cmd));
336  		if (!mbox_cmd.msg.s.resp_needed) {
337  			mbox->state &= ~OCTEON_MBOX_STATE_REQUEST_RECEIVED;
338  			if (!(mbox->state &
339  			      OCTEON_MBOX_STATE_RESPONSE_PENDING))
340  				mbox->state = OCTEON_MBOX_STATE_IDLE;
341  			writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
342  		}
343  
344  		spin_unlock_irqrestore(&mbox->lock, flags);
345  		octeon_mbox_process_cmd(mbox, &mbox_cmd);
346  		return 0;
347  	}
348  
349  	spin_unlock_irqrestore(&mbox->lock, flags);
350  	WARN_ON(1);
351  
352  	return 0;
353  }
354  
octeon_mbox_cancel(struct octeon_device * oct,int q_no)355  int octeon_mbox_cancel(struct octeon_device *oct, int q_no)
356  {
357  	struct octeon_mbox *mbox = oct->mbox[q_no];
358  	struct octeon_mbox_cmd *mbox_cmd;
359  	unsigned long flags = 0;
360  
361  	spin_lock_irqsave(&mbox->lock, flags);
362  	mbox_cmd = &mbox->mbox_resp;
363  
364  	if (!(mbox->state & OCTEON_MBOX_STATE_RESPONSE_PENDING)) {
365  		spin_unlock_irqrestore(&mbox->lock, flags);
366  		return 1;
367  	}
368  
369  	mbox->state = OCTEON_MBOX_STATE_IDLE;
370  	memset(mbox_cmd, 0, sizeof(*mbox_cmd));
371  	writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
372  	spin_unlock_irqrestore(&mbox->lock, flags);
373  
374  	return 0;
375  }
376