• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2017 - 2019 Pensando Systems, Inc */
3 
4 #include <linux/kernel.h>
5 #include <linux/types.h>
6 #include <linux/errno.h>
7 #include <linux/io.h>
8 #include <linux/slab.h>
9 #include <linux/etherdevice.h>
10 #include "ionic.h"
11 #include "ionic_dev.h"
12 #include "ionic_lif.h"
13 
ionic_watchdog_cb(struct timer_list * t)14 static void ionic_watchdog_cb(struct timer_list *t)
15 {
16 	struct ionic *ionic = from_timer(ionic, t, watchdog_timer);
17 	struct ionic_lif *lif = ionic->lif;
18 	struct ionic_deferred_work *work;
19 	int hb;
20 
21 	mod_timer(&ionic->watchdog_timer,
22 		  round_jiffies(jiffies + ionic->watchdog_period));
23 
24 	if (!lif)
25 		return;
26 
27 	hb = ionic_heartbeat_check(ionic);
28 	dev_dbg(ionic->dev, "%s: hb %d running %d UP %d\n",
29 		__func__, hb, netif_running(lif->netdev),
30 		test_bit(IONIC_LIF_F_UP, lif->state));
31 
32 	if (hb >= 0 &&
33 	    !test_bit(IONIC_LIF_F_FW_RESET, lif->state))
34 		ionic_link_status_check_request(lif, CAN_NOT_SLEEP);
35 
36 	if (test_bit(IONIC_LIF_F_FILTER_SYNC_NEEDED, lif->state)) {
37 		work = kzalloc(sizeof(*work), GFP_ATOMIC);
38 		if (!work) {
39 			netdev_err(lif->netdev, "rxmode change dropped\n");
40 			return;
41 		}
42 
43 		work->type = IONIC_DW_TYPE_RX_MODE;
44 		netdev_dbg(lif->netdev, "deferred: rx_mode\n");
45 		ionic_lif_deferred_enqueue(&lif->deferred, work);
46 	}
47 }
48 
ionic_init_devinfo(struct ionic * ionic)49 void ionic_init_devinfo(struct ionic *ionic)
50 {
51 	struct ionic_dev *idev = &ionic->idev;
52 
53 	idev->dev_info.asic_type = ioread8(&idev->dev_info_regs->asic_type);
54 	idev->dev_info.asic_rev = ioread8(&idev->dev_info_regs->asic_rev);
55 
56 	memcpy_fromio(idev->dev_info.fw_version,
57 		      idev->dev_info_regs->fw_version,
58 		      IONIC_DEVINFO_FWVERS_BUFLEN);
59 
60 	memcpy_fromio(idev->dev_info.serial_num,
61 		      idev->dev_info_regs->serial_num,
62 		      IONIC_DEVINFO_SERIAL_BUFLEN);
63 
64 	idev->dev_info.fw_version[IONIC_DEVINFO_FWVERS_BUFLEN] = 0;
65 	idev->dev_info.serial_num[IONIC_DEVINFO_SERIAL_BUFLEN] = 0;
66 
67 	dev_dbg(ionic->dev, "fw_version %s\n", idev->dev_info.fw_version);
68 }
69 
ionic_dev_setup(struct ionic * ionic)70 int ionic_dev_setup(struct ionic *ionic)
71 {
72 	struct ionic_dev_bar *bar = ionic->bars;
73 	unsigned int num_bars = ionic->num_bars;
74 	struct ionic_dev *idev = &ionic->idev;
75 	struct device *dev = ionic->dev;
76 	u32 sig;
77 
78 	/* BAR0: dev_cmd and interrupts */
79 	if (num_bars < 1) {
80 		dev_err(dev, "No bars found, aborting\n");
81 		return -EFAULT;
82 	}
83 
84 	if (bar->len < IONIC_BAR0_SIZE) {
85 		dev_err(dev, "Resource bar size %lu too small, aborting\n",
86 			bar->len);
87 		return -EFAULT;
88 	}
89 
90 	idev->dev_info_regs = bar->vaddr + IONIC_BAR0_DEV_INFO_REGS_OFFSET;
91 	idev->dev_cmd_regs = bar->vaddr + IONIC_BAR0_DEV_CMD_REGS_OFFSET;
92 	idev->intr_status = bar->vaddr + IONIC_BAR0_INTR_STATUS_OFFSET;
93 	idev->intr_ctrl = bar->vaddr + IONIC_BAR0_INTR_CTRL_OFFSET;
94 
95 	idev->hwstamp_regs = &idev->dev_info_regs->hwstamp;
96 
97 	sig = ioread32(&idev->dev_info_regs->signature);
98 	if (sig != IONIC_DEV_INFO_SIGNATURE) {
99 		dev_err(dev, "Incompatible firmware signature %x", sig);
100 		return -EFAULT;
101 	}
102 
103 	ionic_init_devinfo(ionic);
104 
105 	/* BAR1: doorbells */
106 	bar++;
107 	if (num_bars < 2) {
108 		dev_err(dev, "Doorbell bar missing, aborting\n");
109 		return -EFAULT;
110 	}
111 
112 	timer_setup(&ionic->watchdog_timer, ionic_watchdog_cb, 0);
113 	ionic->watchdog_period = IONIC_WATCHDOG_SECS * HZ;
114 
115 	/* set times to ensure the first check will proceed */
116 	atomic_long_set(&idev->last_check_time, jiffies - 2 * HZ);
117 	idev->last_hb_time = jiffies - 2 * ionic->watchdog_period;
118 	/* init as ready, so no transition if the first check succeeds */
119 	idev->last_fw_hb = 0;
120 	idev->fw_hb_ready = true;
121 	idev->fw_status_ready = true;
122 	idev->fw_generation = IONIC_FW_STS_F_GENERATION &
123 			      ioread8(&idev->dev_info_regs->fw_status);
124 
125 	idev->db_pages = bar->vaddr;
126 	idev->phy_db_pages = bar->bus_addr;
127 
128 	return 0;
129 }
130 
131 /* Devcmd Interface */
ionic_is_fw_running(struct ionic_dev * idev)132 bool ionic_is_fw_running(struct ionic_dev *idev)
133 {
134 	u8 fw_status = ioread8(&idev->dev_info_regs->fw_status);
135 
136 	/* firmware is useful only if the running bit is set and
137 	 * fw_status != 0xff (bad PCI read)
138 	 */
139 	return (fw_status != 0xff) && (fw_status & IONIC_FW_STS_F_RUNNING);
140 }
141 
ionic_heartbeat_check(struct ionic * ionic)142 int ionic_heartbeat_check(struct ionic *ionic)
143 {
144 	struct ionic_dev *idev = &ionic->idev;
145 	unsigned long check_time, last_check_time;
146 	bool fw_status_ready = true;
147 	bool fw_hb_ready;
148 	u8 fw_generation;
149 	u8 fw_status;
150 	u32 fw_hb;
151 
152 	/* wait a least one second before testing again */
153 	check_time = jiffies;
154 	last_check_time = atomic_long_read(&idev->last_check_time);
155 do_check_time:
156 	if (time_before(check_time, last_check_time + HZ))
157 		return 0;
158 	if (!atomic_long_try_cmpxchg_relaxed(&idev->last_check_time,
159 					     &last_check_time, check_time)) {
160 		/* if called concurrently, only the first should proceed. */
161 		dev_dbg(ionic->dev, "%s: do_check_time again\n", __func__);
162 		goto do_check_time;
163 	}
164 
165 	fw_status = ioread8(&idev->dev_info_regs->fw_status);
166 
167 	/* If fw_status is not ready don't bother with the generation */
168 	if (!ionic_is_fw_running(idev)) {
169 		fw_status_ready = false;
170 	} else {
171 		fw_generation = fw_status & IONIC_FW_STS_F_GENERATION;
172 		if (idev->fw_generation != fw_generation) {
173 			dev_info(ionic->dev, "FW generation 0x%02x -> 0x%02x\n",
174 				 idev->fw_generation, fw_generation);
175 
176 			idev->fw_generation = fw_generation;
177 
178 			/* If the generation changed, the fw status is not
179 			 * ready so we need to trigger a fw-down cycle.  After
180 			 * the down, the next watchdog will see the fw is up
181 			 * and the generation value stable, so will trigger
182 			 * the fw-up activity.
183 			 */
184 			fw_status_ready = false;
185 		}
186 	}
187 
188 	/* is this a transition? */
189 	if (fw_status_ready != idev->fw_status_ready) {
190 		struct ionic_lif *lif = ionic->lif;
191 		bool trigger = false;
192 
193 		idev->fw_status_ready = fw_status_ready;
194 
195 		if (!fw_status_ready) {
196 			dev_info(ionic->dev, "FW stopped %u\n", fw_status);
197 			if (lif && !test_bit(IONIC_LIF_F_FW_RESET, lif->state))
198 				trigger = true;
199 		} else {
200 			dev_info(ionic->dev, "FW running %u\n", fw_status);
201 			if (lif && test_bit(IONIC_LIF_F_FW_RESET, lif->state))
202 				trigger = true;
203 		}
204 
205 		if (trigger) {
206 			struct ionic_deferred_work *work;
207 
208 			work = kzalloc(sizeof(*work), GFP_ATOMIC);
209 			if (work) {
210 				work->type = IONIC_DW_TYPE_LIF_RESET;
211 				work->fw_status = fw_status_ready;
212 				ionic_lif_deferred_enqueue(&lif->deferred, work);
213 			}
214 		}
215 	}
216 
217 	if (!fw_status_ready)
218 		return -ENXIO;
219 
220 	/* wait at least one watchdog period since the last heartbeat */
221 	last_check_time = idev->last_hb_time;
222 	if (time_before(check_time, last_check_time + ionic->watchdog_period))
223 		return 0;
224 
225 	fw_hb = ioread32(&idev->dev_info_regs->fw_heartbeat);
226 	fw_hb_ready = fw_hb != idev->last_fw_hb;
227 
228 	/* early FW version had no heartbeat, so fake it */
229 	if (!fw_hb_ready && !fw_hb)
230 		fw_hb_ready = true;
231 
232 	dev_dbg(ionic->dev, "%s: fw_hb %u last_fw_hb %u ready %u\n",
233 		__func__, fw_hb, idev->last_fw_hb, fw_hb_ready);
234 
235 	idev->last_fw_hb = fw_hb;
236 
237 	/* log a transition */
238 	if (fw_hb_ready != idev->fw_hb_ready) {
239 		idev->fw_hb_ready = fw_hb_ready;
240 		if (!fw_hb_ready)
241 			dev_info(ionic->dev, "FW heartbeat stalled at %d\n", fw_hb);
242 		else
243 			dev_info(ionic->dev, "FW heartbeat restored at %d\n", fw_hb);
244 	}
245 
246 	if (!fw_hb_ready)
247 		return -ENXIO;
248 
249 	idev->last_hb_time = check_time;
250 
251 	return 0;
252 }
253 
ionic_dev_cmd_status(struct ionic_dev * idev)254 u8 ionic_dev_cmd_status(struct ionic_dev *idev)
255 {
256 	return ioread8(&idev->dev_cmd_regs->comp.comp.status);
257 }
258 
ionic_dev_cmd_done(struct ionic_dev * idev)259 bool ionic_dev_cmd_done(struct ionic_dev *idev)
260 {
261 	return ioread32(&idev->dev_cmd_regs->done) & IONIC_DEV_CMD_DONE;
262 }
263 
ionic_dev_cmd_comp(struct ionic_dev * idev,union ionic_dev_cmd_comp * comp)264 void ionic_dev_cmd_comp(struct ionic_dev *idev, union ionic_dev_cmd_comp *comp)
265 {
266 	memcpy_fromio(comp, &idev->dev_cmd_regs->comp, sizeof(*comp));
267 }
268 
ionic_dev_cmd_go(struct ionic_dev * idev,union ionic_dev_cmd * cmd)269 void ionic_dev_cmd_go(struct ionic_dev *idev, union ionic_dev_cmd *cmd)
270 {
271 	idev->opcode = cmd->cmd.opcode;
272 	memcpy_toio(&idev->dev_cmd_regs->cmd, cmd, sizeof(*cmd));
273 	iowrite32(0, &idev->dev_cmd_regs->done);
274 	iowrite32(1, &idev->dev_cmd_regs->doorbell);
275 }
276 
277 /* Device commands */
ionic_dev_cmd_identify(struct ionic_dev * idev,u8 ver)278 void ionic_dev_cmd_identify(struct ionic_dev *idev, u8 ver)
279 {
280 	union ionic_dev_cmd cmd = {
281 		.identify.opcode = IONIC_CMD_IDENTIFY,
282 		.identify.ver = ver,
283 	};
284 
285 	ionic_dev_cmd_go(idev, &cmd);
286 }
287 
ionic_dev_cmd_init(struct ionic_dev * idev)288 void ionic_dev_cmd_init(struct ionic_dev *idev)
289 {
290 	union ionic_dev_cmd cmd = {
291 		.init.opcode = IONIC_CMD_INIT,
292 		.init.type = 0,
293 	};
294 
295 	ionic_dev_cmd_go(idev, &cmd);
296 }
297 
ionic_dev_cmd_reset(struct ionic_dev * idev)298 void ionic_dev_cmd_reset(struct ionic_dev *idev)
299 {
300 	union ionic_dev_cmd cmd = {
301 		.reset.opcode = IONIC_CMD_RESET,
302 	};
303 
304 	ionic_dev_cmd_go(idev, &cmd);
305 }
306 
307 /* Port commands */
ionic_dev_cmd_port_identify(struct ionic_dev * idev)308 void ionic_dev_cmd_port_identify(struct ionic_dev *idev)
309 {
310 	union ionic_dev_cmd cmd = {
311 		.port_init.opcode = IONIC_CMD_PORT_IDENTIFY,
312 		.port_init.index = 0,
313 	};
314 
315 	ionic_dev_cmd_go(idev, &cmd);
316 }
317 
ionic_dev_cmd_port_init(struct ionic_dev * idev)318 void ionic_dev_cmd_port_init(struct ionic_dev *idev)
319 {
320 	union ionic_dev_cmd cmd = {
321 		.port_init.opcode = IONIC_CMD_PORT_INIT,
322 		.port_init.index = 0,
323 		.port_init.info_pa = cpu_to_le64(idev->port_info_pa),
324 	};
325 
326 	ionic_dev_cmd_go(idev, &cmd);
327 }
328 
ionic_dev_cmd_port_reset(struct ionic_dev * idev)329 void ionic_dev_cmd_port_reset(struct ionic_dev *idev)
330 {
331 	union ionic_dev_cmd cmd = {
332 		.port_reset.opcode = IONIC_CMD_PORT_RESET,
333 		.port_reset.index = 0,
334 	};
335 
336 	ionic_dev_cmd_go(idev, &cmd);
337 }
338 
ionic_dev_cmd_port_state(struct ionic_dev * idev,u8 state)339 void ionic_dev_cmd_port_state(struct ionic_dev *idev, u8 state)
340 {
341 	union ionic_dev_cmd cmd = {
342 		.port_setattr.opcode = IONIC_CMD_PORT_SETATTR,
343 		.port_setattr.index = 0,
344 		.port_setattr.attr = IONIC_PORT_ATTR_STATE,
345 		.port_setattr.state = state,
346 	};
347 
348 	ionic_dev_cmd_go(idev, &cmd);
349 }
350 
ionic_dev_cmd_port_speed(struct ionic_dev * idev,u32 speed)351 void ionic_dev_cmd_port_speed(struct ionic_dev *idev, u32 speed)
352 {
353 	union ionic_dev_cmd cmd = {
354 		.port_setattr.opcode = IONIC_CMD_PORT_SETATTR,
355 		.port_setattr.index = 0,
356 		.port_setattr.attr = IONIC_PORT_ATTR_SPEED,
357 		.port_setattr.speed = cpu_to_le32(speed),
358 	};
359 
360 	ionic_dev_cmd_go(idev, &cmd);
361 }
362 
ionic_dev_cmd_port_autoneg(struct ionic_dev * idev,u8 an_enable)363 void ionic_dev_cmd_port_autoneg(struct ionic_dev *idev, u8 an_enable)
364 {
365 	union ionic_dev_cmd cmd = {
366 		.port_setattr.opcode = IONIC_CMD_PORT_SETATTR,
367 		.port_setattr.index = 0,
368 		.port_setattr.attr = IONIC_PORT_ATTR_AUTONEG,
369 		.port_setattr.an_enable = an_enable,
370 	};
371 
372 	ionic_dev_cmd_go(idev, &cmd);
373 }
374 
ionic_dev_cmd_port_fec(struct ionic_dev * idev,u8 fec_type)375 void ionic_dev_cmd_port_fec(struct ionic_dev *idev, u8 fec_type)
376 {
377 	union ionic_dev_cmd cmd = {
378 		.port_setattr.opcode = IONIC_CMD_PORT_SETATTR,
379 		.port_setattr.index = 0,
380 		.port_setattr.attr = IONIC_PORT_ATTR_FEC,
381 		.port_setattr.fec_type = fec_type,
382 	};
383 
384 	ionic_dev_cmd_go(idev, &cmd);
385 }
386 
ionic_dev_cmd_port_pause(struct ionic_dev * idev,u8 pause_type)387 void ionic_dev_cmd_port_pause(struct ionic_dev *idev, u8 pause_type)
388 {
389 	union ionic_dev_cmd cmd = {
390 		.port_setattr.opcode = IONIC_CMD_PORT_SETATTR,
391 		.port_setattr.index = 0,
392 		.port_setattr.attr = IONIC_PORT_ATTR_PAUSE,
393 		.port_setattr.pause_type = pause_type,
394 	};
395 
396 	ionic_dev_cmd_go(idev, &cmd);
397 }
398 
399 /* VF commands */
ionic_set_vf_config(struct ionic * ionic,int vf,u8 attr,u8 * data)400 int ionic_set_vf_config(struct ionic *ionic, int vf, u8 attr, u8 *data)
401 {
402 	union ionic_dev_cmd cmd = {
403 		.vf_setattr.opcode = IONIC_CMD_VF_SETATTR,
404 		.vf_setattr.attr = attr,
405 		.vf_setattr.vf_index = cpu_to_le16(vf),
406 	};
407 	int err;
408 
409 	switch (attr) {
410 	case IONIC_VF_ATTR_SPOOFCHK:
411 		cmd.vf_setattr.spoofchk = *data;
412 		dev_dbg(ionic->dev, "%s: vf %d spoof %d\n",
413 			__func__, vf, *data);
414 		break;
415 	case IONIC_VF_ATTR_TRUST:
416 		cmd.vf_setattr.trust = *data;
417 		dev_dbg(ionic->dev, "%s: vf %d trust %d\n",
418 			__func__, vf, *data);
419 		break;
420 	case IONIC_VF_ATTR_LINKSTATE:
421 		cmd.vf_setattr.linkstate = *data;
422 		dev_dbg(ionic->dev, "%s: vf %d linkstate %d\n",
423 			__func__, vf, *data);
424 		break;
425 	case IONIC_VF_ATTR_MAC:
426 		ether_addr_copy(cmd.vf_setattr.macaddr, data);
427 		dev_dbg(ionic->dev, "%s: vf %d macaddr %pM\n",
428 			__func__, vf, data);
429 		break;
430 	case IONIC_VF_ATTR_VLAN:
431 		cmd.vf_setattr.vlanid = cpu_to_le16(*(u16 *)data);
432 		dev_dbg(ionic->dev, "%s: vf %d vlan %d\n",
433 			__func__, vf, *(u16 *)data);
434 		break;
435 	case IONIC_VF_ATTR_RATE:
436 		cmd.vf_setattr.maxrate = cpu_to_le32(*(u32 *)data);
437 		dev_dbg(ionic->dev, "%s: vf %d maxrate %d\n",
438 			__func__, vf, *(u32 *)data);
439 		break;
440 	case IONIC_VF_ATTR_STATSADDR:
441 		cmd.vf_setattr.stats_pa = cpu_to_le64(*(u64 *)data);
442 		dev_dbg(ionic->dev, "%s: vf %d stats_pa 0x%08llx\n",
443 			__func__, vf, *(u64 *)data);
444 		break;
445 	default:
446 		return -EINVAL;
447 	}
448 
449 	mutex_lock(&ionic->dev_cmd_lock);
450 	ionic_dev_cmd_go(&ionic->idev, &cmd);
451 	err = ionic_dev_cmd_wait(ionic, DEVCMD_TIMEOUT);
452 	mutex_unlock(&ionic->dev_cmd_lock);
453 
454 	return err;
455 }
456 
457 /* LIF commands */
ionic_dev_cmd_queue_identify(struct ionic_dev * idev,u16 lif_type,u8 qtype,u8 qver)458 void ionic_dev_cmd_queue_identify(struct ionic_dev *idev,
459 				  u16 lif_type, u8 qtype, u8 qver)
460 {
461 	union ionic_dev_cmd cmd = {
462 		.q_identify.opcode = IONIC_CMD_Q_IDENTIFY,
463 		.q_identify.lif_type = cpu_to_le16(lif_type),
464 		.q_identify.type = qtype,
465 		.q_identify.ver = qver,
466 	};
467 
468 	ionic_dev_cmd_go(idev, &cmd);
469 }
470 
ionic_dev_cmd_lif_identify(struct ionic_dev * idev,u8 type,u8 ver)471 void ionic_dev_cmd_lif_identify(struct ionic_dev *idev, u8 type, u8 ver)
472 {
473 	union ionic_dev_cmd cmd = {
474 		.lif_identify.opcode = IONIC_CMD_LIF_IDENTIFY,
475 		.lif_identify.type = type,
476 		.lif_identify.ver = ver,
477 	};
478 
479 	ionic_dev_cmd_go(idev, &cmd);
480 }
481 
ionic_dev_cmd_lif_init(struct ionic_dev * idev,u16 lif_index,dma_addr_t info_pa)482 void ionic_dev_cmd_lif_init(struct ionic_dev *idev, u16 lif_index,
483 			    dma_addr_t info_pa)
484 {
485 	union ionic_dev_cmd cmd = {
486 		.lif_init.opcode = IONIC_CMD_LIF_INIT,
487 		.lif_init.index = cpu_to_le16(lif_index),
488 		.lif_init.info_pa = cpu_to_le64(info_pa),
489 	};
490 
491 	ionic_dev_cmd_go(idev, &cmd);
492 }
493 
ionic_dev_cmd_lif_reset(struct ionic_dev * idev,u16 lif_index)494 void ionic_dev_cmd_lif_reset(struct ionic_dev *idev, u16 lif_index)
495 {
496 	union ionic_dev_cmd cmd = {
497 		.lif_init.opcode = IONIC_CMD_LIF_RESET,
498 		.lif_init.index = cpu_to_le16(lif_index),
499 	};
500 
501 	ionic_dev_cmd_go(idev, &cmd);
502 }
503 
ionic_dev_cmd_adminq_init(struct ionic_dev * idev,struct ionic_qcq * qcq,u16 lif_index,u16 intr_index)504 void ionic_dev_cmd_adminq_init(struct ionic_dev *idev, struct ionic_qcq *qcq,
505 			       u16 lif_index, u16 intr_index)
506 {
507 	struct ionic_queue *q = &qcq->q;
508 	struct ionic_cq *cq = &qcq->cq;
509 
510 	union ionic_dev_cmd cmd = {
511 		.q_init.opcode = IONIC_CMD_Q_INIT,
512 		.q_init.lif_index = cpu_to_le16(lif_index),
513 		.q_init.type = q->type,
514 		.q_init.ver = qcq->q.lif->qtype_info[q->type].version,
515 		.q_init.index = cpu_to_le32(q->index),
516 		.q_init.flags = cpu_to_le16(IONIC_QINIT_F_IRQ |
517 					    IONIC_QINIT_F_ENA),
518 		.q_init.pid = cpu_to_le16(q->pid),
519 		.q_init.intr_index = cpu_to_le16(intr_index),
520 		.q_init.ring_size = ilog2(q->num_descs),
521 		.q_init.ring_base = cpu_to_le64(q->base_pa),
522 		.q_init.cq_ring_base = cpu_to_le64(cq->base_pa),
523 	};
524 
525 	ionic_dev_cmd_go(idev, &cmd);
526 }
527 
ionic_db_page_num(struct ionic_lif * lif,int pid)528 int ionic_db_page_num(struct ionic_lif *lif, int pid)
529 {
530 	return (lif->hw_index * lif->dbid_count) + pid;
531 }
532 
ionic_cq_init(struct ionic_lif * lif,struct ionic_cq * cq,struct ionic_intr_info * intr,unsigned int num_descs,size_t desc_size)533 int ionic_cq_init(struct ionic_lif *lif, struct ionic_cq *cq,
534 		  struct ionic_intr_info *intr,
535 		  unsigned int num_descs, size_t desc_size)
536 {
537 	unsigned int ring_size;
538 
539 	if (desc_size == 0 || !is_power_of_2(num_descs))
540 		return -EINVAL;
541 
542 	ring_size = ilog2(num_descs);
543 	if (ring_size < 2 || ring_size > 16)
544 		return -EINVAL;
545 
546 	cq->lif = lif;
547 	cq->bound_intr = intr;
548 	cq->num_descs = num_descs;
549 	cq->desc_size = desc_size;
550 	cq->tail_idx = 0;
551 	cq->done_color = 1;
552 
553 	return 0;
554 }
555 
ionic_cq_map(struct ionic_cq * cq,void * base,dma_addr_t base_pa)556 void ionic_cq_map(struct ionic_cq *cq, void *base, dma_addr_t base_pa)
557 {
558 	struct ionic_cq_info *cur;
559 	unsigned int i;
560 
561 	cq->base = base;
562 	cq->base_pa = base_pa;
563 
564 	for (i = 0, cur = cq->info; i < cq->num_descs; i++, cur++)
565 		cur->cq_desc = base + (i * cq->desc_size);
566 }
567 
ionic_cq_bind(struct ionic_cq * cq,struct ionic_queue * q)568 void ionic_cq_bind(struct ionic_cq *cq, struct ionic_queue *q)
569 {
570 	cq->bound_q = q;
571 }
572 
ionic_cq_service(struct ionic_cq * cq,unsigned int work_to_do,ionic_cq_cb cb,ionic_cq_done_cb done_cb,void * done_arg)573 unsigned int ionic_cq_service(struct ionic_cq *cq, unsigned int work_to_do,
574 			      ionic_cq_cb cb, ionic_cq_done_cb done_cb,
575 			      void *done_arg)
576 {
577 	struct ionic_cq_info *cq_info;
578 	unsigned int work_done = 0;
579 
580 	if (work_to_do == 0)
581 		return 0;
582 
583 	cq_info = &cq->info[cq->tail_idx];
584 	while (cb(cq, cq_info)) {
585 		if (cq->tail_idx == cq->num_descs - 1)
586 			cq->done_color = !cq->done_color;
587 		cq->tail_idx = (cq->tail_idx + 1) & (cq->num_descs - 1);
588 		cq_info = &cq->info[cq->tail_idx];
589 		DEBUG_STATS_CQE_CNT(cq);
590 
591 		if (++work_done >= work_to_do)
592 			break;
593 	}
594 
595 	if (work_done && done_cb)
596 		done_cb(done_arg);
597 
598 	return work_done;
599 }
600 
ionic_q_init(struct ionic_lif * lif,struct ionic_dev * idev,struct ionic_queue * q,unsigned int index,const char * name,unsigned int num_descs,size_t desc_size,size_t sg_desc_size,unsigned int pid)601 int ionic_q_init(struct ionic_lif *lif, struct ionic_dev *idev,
602 		 struct ionic_queue *q, unsigned int index, const char *name,
603 		 unsigned int num_descs, size_t desc_size,
604 		 size_t sg_desc_size, unsigned int pid)
605 {
606 	unsigned int ring_size;
607 
608 	if (desc_size == 0 || !is_power_of_2(num_descs))
609 		return -EINVAL;
610 
611 	ring_size = ilog2(num_descs);
612 	if (ring_size < 2 || ring_size > 16)
613 		return -EINVAL;
614 
615 	q->lif = lif;
616 	q->idev = idev;
617 	q->index = index;
618 	q->num_descs = num_descs;
619 	q->desc_size = desc_size;
620 	q->sg_desc_size = sg_desc_size;
621 	q->tail_idx = 0;
622 	q->head_idx = 0;
623 	q->pid = pid;
624 
625 	snprintf(q->name, sizeof(q->name), "L%d-%s%u", lif->index, name, index);
626 
627 	return 0;
628 }
629 
ionic_q_map(struct ionic_queue * q,void * base,dma_addr_t base_pa)630 void ionic_q_map(struct ionic_queue *q, void *base, dma_addr_t base_pa)
631 {
632 	struct ionic_desc_info *cur;
633 	unsigned int i;
634 
635 	q->base = base;
636 	q->base_pa = base_pa;
637 
638 	for (i = 0, cur = q->info; i < q->num_descs; i++, cur++)
639 		cur->desc = base + (i * q->desc_size);
640 }
641 
ionic_q_sg_map(struct ionic_queue * q,void * base,dma_addr_t base_pa)642 void ionic_q_sg_map(struct ionic_queue *q, void *base, dma_addr_t base_pa)
643 {
644 	struct ionic_desc_info *cur;
645 	unsigned int i;
646 
647 	q->sg_base = base;
648 	q->sg_base_pa = base_pa;
649 
650 	for (i = 0, cur = q->info; i < q->num_descs; i++, cur++)
651 		cur->sg_desc = base + (i * q->sg_desc_size);
652 }
653 
ionic_q_post(struct ionic_queue * q,bool ring_doorbell,ionic_desc_cb cb,void * cb_arg)654 void ionic_q_post(struct ionic_queue *q, bool ring_doorbell, ionic_desc_cb cb,
655 		  void *cb_arg)
656 {
657 	struct ionic_desc_info *desc_info;
658 	struct ionic_lif *lif = q->lif;
659 	struct device *dev = q->dev;
660 
661 	desc_info = &q->info[q->head_idx];
662 	desc_info->cb = cb;
663 	desc_info->cb_arg = cb_arg;
664 
665 	q->head_idx = (q->head_idx + 1) & (q->num_descs - 1);
666 
667 	dev_dbg(dev, "lif=%d qname=%s qid=%d qtype=%d p_index=%d ringdb=%d\n",
668 		q->lif->index, q->name, q->hw_type, q->hw_index,
669 		q->head_idx, ring_doorbell);
670 
671 	if (ring_doorbell)
672 		ionic_dbell_ring(lif->kern_dbpage, q->hw_type,
673 				 q->dbval | q->head_idx);
674 }
675 
ionic_q_is_posted(struct ionic_queue * q,unsigned int pos)676 static bool ionic_q_is_posted(struct ionic_queue *q, unsigned int pos)
677 {
678 	unsigned int mask, tail, head;
679 
680 	mask = q->num_descs - 1;
681 	tail = q->tail_idx;
682 	head = q->head_idx;
683 
684 	return ((pos - tail) & mask) < ((head - tail) & mask);
685 }
686 
ionic_q_service(struct ionic_queue * q,struct ionic_cq_info * cq_info,unsigned int stop_index)687 void ionic_q_service(struct ionic_queue *q, struct ionic_cq_info *cq_info,
688 		     unsigned int stop_index)
689 {
690 	struct ionic_desc_info *desc_info;
691 	ionic_desc_cb cb;
692 	void *cb_arg;
693 	u16 index;
694 
695 	/* check for empty queue */
696 	if (q->tail_idx == q->head_idx)
697 		return;
698 
699 	/* stop index must be for a descriptor that is not yet completed */
700 	if (unlikely(!ionic_q_is_posted(q, stop_index)))
701 		dev_err(q->dev,
702 			"ionic stop is not posted %s stop %u tail %u head %u\n",
703 			q->name, stop_index, q->tail_idx, q->head_idx);
704 
705 	do {
706 		desc_info = &q->info[q->tail_idx];
707 		index = q->tail_idx;
708 		q->tail_idx = (q->tail_idx + 1) & (q->num_descs - 1);
709 
710 		cb = desc_info->cb;
711 		cb_arg = desc_info->cb_arg;
712 
713 		desc_info->cb = NULL;
714 		desc_info->cb_arg = NULL;
715 
716 		if (cb)
717 			cb(q, desc_info, cq_info, cb_arg);
718 	} while (index != stop_index);
719 }
720