1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /* Copyright (c) 2018 Mellanox Technologies. All rights reserved */
3 
4 #include <linux/kernel.h>
5 #include <linux/err.h>
6 #include <linux/ethtool.h>
7 #include <linux/sfp.h>
8 #include <linux/mutex.h>
9 
10 #include "core.h"
11 #include "core_env.h"
12 #include "item.h"
13 #include "reg.h"
14 
15 struct mlxsw_env_module_info {
16 	u64 module_overheat_counter;
17 	bool is_overheat;
18 	int num_ports_mapped;
19 	int num_ports_up;
20 	enum ethtool_module_power_mode_policy power_mode_policy;
21 	enum mlxsw_reg_pmtm_module_type type;
22 };
23 
24 struct mlxsw_env {
25 	struct mlxsw_core *core;
26 	u8 module_count;
27 	struct mutex module_info_lock; /* Protects 'module_info'. */
28 	struct mlxsw_env_module_info module_info[];
29 };
30 
31 static int __mlxsw_env_validate_module_type(struct mlxsw_core *core, u8 module)
32 {
33 	struct mlxsw_env *mlxsw_env = mlxsw_core_env(core);
34 	int err;
35 
36 	switch (mlxsw_env->module_info[module].type) {
37 	case MLXSW_REG_PMTM_MODULE_TYPE_TWISTED_PAIR:
38 		err = -EINVAL;
39 		break;
40 	default:
41 		err = 0;
42 	}
43 
44 	return err;
45 }
46 
47 static int mlxsw_env_validate_module_type(struct mlxsw_core *core, u8 module)
48 {
49 	struct mlxsw_env *mlxsw_env = mlxsw_core_env(core);
50 	int err;
51 
52 	mutex_lock(&mlxsw_env->module_info_lock);
53 	err = __mlxsw_env_validate_module_type(core, module);
54 	mutex_unlock(&mlxsw_env->module_info_lock);
55 
56 	return err;
57 }
58 
59 static int
60 mlxsw_env_validate_cable_ident(struct mlxsw_core *core, int id, bool *qsfp,
61 			       bool *cmis)
62 {
63 	char mcia_pl[MLXSW_REG_MCIA_LEN];
64 	char *eeprom_tmp;
65 	u8 ident;
66 	int err;
67 
68 	err = mlxsw_env_validate_module_type(core, id);
69 	if (err)
70 		return err;
71 
72 	mlxsw_reg_mcia_pack(mcia_pl, id, 0, MLXSW_REG_MCIA_PAGE0_LO_OFF, 0, 1,
73 			    MLXSW_REG_MCIA_I2C_ADDR_LOW);
74 	err = mlxsw_reg_query(core, MLXSW_REG(mcia), mcia_pl);
75 	if (err)
76 		return err;
77 	eeprom_tmp = mlxsw_reg_mcia_eeprom_data(mcia_pl);
78 	ident = eeprom_tmp[0];
79 	*cmis = false;
80 	switch (ident) {
81 	case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_SFP:
82 		*qsfp = false;
83 		break;
84 	case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP:
85 	case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP_PLUS:
86 	case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP28:
87 		*qsfp = true;
88 		break;
89 	case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP_DD:
90 	case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_OSFP:
91 		*qsfp = true;
92 		*cmis = true;
93 		break;
94 	default:
95 		return -EINVAL;
96 	}
97 
98 	return 0;
99 }
100 
101 static int
102 mlxsw_env_query_module_eeprom(struct mlxsw_core *mlxsw_core, int module,
103 			      u16 offset, u16 size, void *data,
104 			      bool qsfp, unsigned int *p_read_size)
105 {
106 	char mcia_pl[MLXSW_REG_MCIA_LEN];
107 	char *eeprom_tmp;
108 	u16 i2c_addr;
109 	u8 page = 0;
110 	int status;
111 	int err;
112 
113 	/* MCIA register accepts buffer size <= 48. Page of size 128 should be
114 	 * read by chunks of size 48, 48, 32. Align the size of the last chunk
115 	 * to avoid reading after the end of the page.
116 	 */
117 	size = min_t(u16, size, MLXSW_REG_MCIA_EEPROM_SIZE);
118 
119 	if (offset < MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH &&
120 	    offset + size > MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH)
121 		/* Cross pages read, read until offset 256 in low page */
122 		size = MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH - offset;
123 
124 	i2c_addr = MLXSW_REG_MCIA_I2C_ADDR_LOW;
125 	if (offset >= MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH) {
126 		if (qsfp) {
127 			/* When reading upper pages 1, 2 and 3 the offset
128 			 * starts at 128. Please refer to "QSFP+ Memory Map"
129 			 * figure in SFF-8436 specification and to "CMIS Module
130 			 * Memory Map" figure in CMIS specification for
131 			 * graphical depiction.
132 			 */
133 			page = MLXSW_REG_MCIA_PAGE_GET(offset);
134 			offset -= MLXSW_REG_MCIA_EEPROM_UP_PAGE_LENGTH * page;
135 			if (offset + size > MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH)
136 				size = MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH - offset;
137 		} else {
138 			/* When reading upper pages 1, 2 and 3 the offset
139 			 * starts at 0 and I2C high address is used. Please refer
140 			 * refer to "Memory Organization" figure in SFF-8472
141 			 * specification for graphical depiction.
142 			 */
143 			i2c_addr = MLXSW_REG_MCIA_I2C_ADDR_HIGH;
144 			offset -= MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH;
145 		}
146 	}
147 
148 	mlxsw_reg_mcia_pack(mcia_pl, module, 0, page, offset, size, i2c_addr);
149 
150 	err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mcia), mcia_pl);
151 	if (err)
152 		return err;
153 
154 	status = mlxsw_reg_mcia_status_get(mcia_pl);
155 	if (status)
156 		return -EIO;
157 
158 	eeprom_tmp = mlxsw_reg_mcia_eeprom_data(mcia_pl);
159 	memcpy(data, eeprom_tmp, size);
160 	*p_read_size = size;
161 
162 	return 0;
163 }
164 
165 int mlxsw_env_module_temp_thresholds_get(struct mlxsw_core *core, int module,
166 					 int off, int *temp)
167 {
168 	unsigned int module_temp, module_crit, module_emerg;
169 	union {
170 		u8 buf[MLXSW_REG_MCIA_TH_ITEM_SIZE];
171 		u16 temp;
172 	} temp_thresh;
173 	char mcia_pl[MLXSW_REG_MCIA_LEN] = {0};
174 	char mtmp_pl[MLXSW_REG_MTMP_LEN];
175 	char *eeprom_tmp;
176 	bool qsfp, cmis;
177 	int page;
178 	int err;
179 
180 	mlxsw_reg_mtmp_pack(mtmp_pl, MLXSW_REG_MTMP_MODULE_INDEX_MIN + module,
181 			    false, false);
182 	err = mlxsw_reg_query(core, MLXSW_REG(mtmp), mtmp_pl);
183 	if (err)
184 		return err;
185 	mlxsw_reg_mtmp_unpack(mtmp_pl, &module_temp, NULL, &module_crit,
186 			      &module_emerg, NULL);
187 	if (!module_temp) {
188 		*temp = 0;
189 		return 0;
190 	}
191 
192 	/* Validate if threshold reading is available through MTMP register,
193 	 * otherwise fallback to read through MCIA.
194 	 */
195 	if (module_emerg) {
196 		*temp = off == SFP_TEMP_HIGH_WARN ? module_crit : module_emerg;
197 		return 0;
198 	}
199 
200 	/* Read Free Side Device Temperature Thresholds from page 03h
201 	 * (MSB at lower byte address).
202 	 * Bytes:
203 	 * 128-129 - Temp High Alarm (SFP_TEMP_HIGH_ALARM);
204 	 * 130-131 - Temp Low Alarm (SFP_TEMP_LOW_ALARM);
205 	 * 132-133 - Temp High Warning (SFP_TEMP_HIGH_WARN);
206 	 * 134-135 - Temp Low Warning (SFP_TEMP_LOW_WARN);
207 	 */
208 
209 	/* Validate module identifier value. */
210 	err = mlxsw_env_validate_cable_ident(core, module, &qsfp, &cmis);
211 	if (err)
212 		return err;
213 
214 	if (qsfp) {
215 		/* For QSFP/CMIS module-defined thresholds are located in page
216 		 * 02h, otherwise in page 03h.
217 		 */
218 		if (cmis)
219 			page = MLXSW_REG_MCIA_TH_PAGE_CMIS_NUM;
220 		else
221 			page = MLXSW_REG_MCIA_TH_PAGE_NUM;
222 		mlxsw_reg_mcia_pack(mcia_pl, module, 0, page,
223 				    MLXSW_REG_MCIA_TH_PAGE_OFF + off,
224 				    MLXSW_REG_MCIA_TH_ITEM_SIZE,
225 				    MLXSW_REG_MCIA_I2C_ADDR_LOW);
226 	} else {
227 		mlxsw_reg_mcia_pack(mcia_pl, module, 0,
228 				    MLXSW_REG_MCIA_PAGE0_LO,
229 				    off, MLXSW_REG_MCIA_TH_ITEM_SIZE,
230 				    MLXSW_REG_MCIA_I2C_ADDR_HIGH);
231 	}
232 
233 	err = mlxsw_reg_query(core, MLXSW_REG(mcia), mcia_pl);
234 	if (err)
235 		return err;
236 
237 	eeprom_tmp = mlxsw_reg_mcia_eeprom_data(mcia_pl);
238 	memcpy(temp_thresh.buf, eeprom_tmp, MLXSW_REG_MCIA_TH_ITEM_SIZE);
239 	*temp = temp_thresh.temp * 1000;
240 
241 	return 0;
242 }
243 
244 int mlxsw_env_get_module_info(struct net_device *netdev,
245 			      struct mlxsw_core *mlxsw_core, int module,
246 			      struct ethtool_modinfo *modinfo)
247 {
248 	u8 module_info[MLXSW_REG_MCIA_EEPROM_MODULE_INFO_SIZE];
249 	u16 offset = MLXSW_REG_MCIA_EEPROM_MODULE_INFO_SIZE;
250 	u8 module_rev_id, module_id, diag_mon;
251 	unsigned int read_size;
252 	int err;
253 
254 	err = mlxsw_env_validate_module_type(mlxsw_core, module);
255 	if (err) {
256 		netdev_err(netdev,
257 			   "EEPROM is not equipped on port module type");
258 		return err;
259 	}
260 
261 	err = mlxsw_env_query_module_eeprom(mlxsw_core, module, 0, offset,
262 					    module_info, false, &read_size);
263 	if (err)
264 		return err;
265 
266 	if (read_size < offset)
267 		return -EIO;
268 
269 	module_rev_id = module_info[MLXSW_REG_MCIA_EEPROM_MODULE_INFO_REV_ID];
270 	module_id = module_info[MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID];
271 
272 	switch (module_id) {
273 	case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP:
274 		modinfo->type       = ETH_MODULE_SFF_8436;
275 		modinfo->eeprom_len = ETH_MODULE_SFF_8436_MAX_LEN;
276 		break;
277 	case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP_PLUS:
278 	case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP28:
279 		if (module_id == MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP28 ||
280 		    module_rev_id >=
281 		    MLXSW_REG_MCIA_EEPROM_MODULE_INFO_REV_ID_8636) {
282 			modinfo->type       = ETH_MODULE_SFF_8636;
283 			modinfo->eeprom_len = ETH_MODULE_SFF_8636_MAX_LEN;
284 		} else {
285 			modinfo->type       = ETH_MODULE_SFF_8436;
286 			modinfo->eeprom_len = ETH_MODULE_SFF_8436_MAX_LEN;
287 		}
288 		break;
289 	case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_SFP:
290 		/* Verify if transceiver provides diagnostic monitoring page */
291 		err = mlxsw_env_query_module_eeprom(mlxsw_core, module,
292 						    SFP_DIAGMON, 1, &diag_mon,
293 						    false, &read_size);
294 		if (err)
295 			return err;
296 
297 		if (read_size < 1)
298 			return -EIO;
299 
300 		modinfo->type       = ETH_MODULE_SFF_8472;
301 		if (diag_mon)
302 			modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
303 		else
304 			modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN / 2;
305 		break;
306 	case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP_DD:
307 	case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_OSFP:
308 		/* Use SFF_8636 as base type. ethtool should recognize specific
309 		 * type through the identifier value.
310 		 */
311 		modinfo->type       = ETH_MODULE_SFF_8636;
312 		/* Verify if module EEPROM is a flat memory. In case of flat
313 		 * memory only page 00h (0-255 bytes) can be read. Otherwise
314 		 * upper pages 01h and 02h can also be read. Upper pages 10h
315 		 * and 11h are currently not supported by the driver.
316 		 */
317 		if (module_info[MLXSW_REG_MCIA_EEPROM_MODULE_INFO_TYPE_ID] &
318 		    MLXSW_REG_MCIA_EEPROM_CMIS_FLAT_MEMORY)
319 			modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN;
320 		else
321 			modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
322 		break;
323 	default:
324 		return -EINVAL;
325 	}
326 
327 	return 0;
328 }
329 EXPORT_SYMBOL(mlxsw_env_get_module_info);
330 
331 int mlxsw_env_get_module_eeprom(struct net_device *netdev,
332 				struct mlxsw_core *mlxsw_core, int module,
333 				struct ethtool_eeprom *ee, u8 *data)
334 {
335 	int offset = ee->offset;
336 	unsigned int read_size;
337 	bool qsfp, cmis;
338 	int i = 0;
339 	int err;
340 
341 	if (!ee->len)
342 		return -EINVAL;
343 
344 	memset(data, 0, ee->len);
345 	/* Validate module identifier value. */
346 	err = mlxsw_env_validate_cable_ident(mlxsw_core, module, &qsfp, &cmis);
347 	if (err)
348 		return err;
349 
350 	while (i < ee->len) {
351 		err = mlxsw_env_query_module_eeprom(mlxsw_core, module, offset,
352 						    ee->len - i, data + i,
353 						    qsfp, &read_size);
354 		if (err) {
355 			netdev_err(netdev, "Eeprom query failed\n");
356 			return err;
357 		}
358 
359 		i += read_size;
360 		offset += read_size;
361 	}
362 
363 	return 0;
364 }
365 EXPORT_SYMBOL(mlxsw_env_get_module_eeprom);
366 
367 static int mlxsw_env_mcia_status_process(const char *mcia_pl,
368 					 struct netlink_ext_ack *extack)
369 {
370 	u8 status = mlxsw_reg_mcia_status_get(mcia_pl);
371 
372 	switch (status) {
373 	case MLXSW_REG_MCIA_STATUS_GOOD:
374 		return 0;
375 	case MLXSW_REG_MCIA_STATUS_NO_EEPROM_MODULE:
376 		NL_SET_ERR_MSG_MOD(extack, "No response from module's EEPROM");
377 		return -EIO;
378 	case MLXSW_REG_MCIA_STATUS_MODULE_NOT_SUPPORTED:
379 		NL_SET_ERR_MSG_MOD(extack, "Module type not supported by the device");
380 		return -EOPNOTSUPP;
381 	case MLXSW_REG_MCIA_STATUS_MODULE_NOT_CONNECTED:
382 		NL_SET_ERR_MSG_MOD(extack, "No module present indication");
383 		return -EIO;
384 	case MLXSW_REG_MCIA_STATUS_I2C_ERROR:
385 		NL_SET_ERR_MSG_MOD(extack, "Error occurred while trying to access module's EEPROM using I2C");
386 		return -EIO;
387 	case MLXSW_REG_MCIA_STATUS_MODULE_DISABLED:
388 		NL_SET_ERR_MSG_MOD(extack, "Module is disabled");
389 		return -EIO;
390 	default:
391 		NL_SET_ERR_MSG_MOD(extack, "Unknown error");
392 		return -EIO;
393 	}
394 }
395 
396 int
397 mlxsw_env_get_module_eeprom_by_page(struct mlxsw_core *mlxsw_core, u8 module,
398 				    const struct ethtool_module_eeprom *page,
399 				    struct netlink_ext_ack *extack)
400 {
401 	u32 bytes_read = 0;
402 	u16 device_addr;
403 	int err;
404 
405 	err = mlxsw_env_validate_module_type(mlxsw_core, module);
406 	if (err) {
407 		NL_SET_ERR_MSG_MOD(extack, "EEPROM is not equipped on port module type");
408 		return err;
409 	}
410 
411 	/* Offset cannot be larger than 2 * ETH_MODULE_EEPROM_PAGE_LEN */
412 	device_addr = page->offset;
413 
414 	while (bytes_read < page->length) {
415 		char mcia_pl[MLXSW_REG_MCIA_LEN];
416 		char *eeprom_tmp;
417 		u8 size;
418 
419 		size = min_t(u8, page->length - bytes_read,
420 			     MLXSW_REG_MCIA_EEPROM_SIZE);
421 
422 		mlxsw_reg_mcia_pack(mcia_pl, module, 0, page->page,
423 				    device_addr + bytes_read, size,
424 				    page->i2c_address);
425 		mlxsw_reg_mcia_bank_number_set(mcia_pl, page->bank);
426 
427 		err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mcia), mcia_pl);
428 		if (err) {
429 			NL_SET_ERR_MSG_MOD(extack, "Failed to access module's EEPROM");
430 			return err;
431 		}
432 
433 		err = mlxsw_env_mcia_status_process(mcia_pl, extack);
434 		if (err)
435 			return err;
436 
437 		eeprom_tmp = mlxsw_reg_mcia_eeprom_data(mcia_pl);
438 		memcpy(page->data + bytes_read, eeprom_tmp, size);
439 		bytes_read += size;
440 	}
441 
442 	return bytes_read;
443 }
444 EXPORT_SYMBOL(mlxsw_env_get_module_eeprom_by_page);
445 
446 static int mlxsw_env_module_reset(struct mlxsw_core *mlxsw_core, u8 module)
447 {
448 	char pmaos_pl[MLXSW_REG_PMAOS_LEN];
449 
450 	mlxsw_reg_pmaos_pack(pmaos_pl, module);
451 	mlxsw_reg_pmaos_rst_set(pmaos_pl, true);
452 
453 	return mlxsw_reg_write(mlxsw_core, MLXSW_REG(pmaos), pmaos_pl);
454 }
455 
456 int mlxsw_env_reset_module(struct net_device *netdev,
457 			   struct mlxsw_core *mlxsw_core, u8 module, u32 *flags)
458 {
459 	struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core);
460 	u32 req = *flags;
461 	int err;
462 
463 	if (!(req & ETH_RESET_PHY) &&
464 	    !(req & (ETH_RESET_PHY << ETH_RESET_SHARED_SHIFT)))
465 		return 0;
466 
467 	mutex_lock(&mlxsw_env->module_info_lock);
468 
469 	err = __mlxsw_env_validate_module_type(mlxsw_core, module);
470 	if (err) {
471 		netdev_err(netdev, "Reset module is not supported on port module type\n");
472 		goto out;
473 	}
474 
475 	if (mlxsw_env->module_info[module].num_ports_up) {
476 		netdev_err(netdev, "Cannot reset module when ports using it are administratively up\n");
477 		err = -EINVAL;
478 		goto out;
479 	}
480 
481 	if (mlxsw_env->module_info[module].num_ports_mapped > 1 &&
482 	    !(req & (ETH_RESET_PHY << ETH_RESET_SHARED_SHIFT))) {
483 		netdev_err(netdev, "Cannot reset module without \"phy-shared\" flag when shared by multiple ports\n");
484 		err = -EINVAL;
485 		goto out;
486 	}
487 
488 	err = mlxsw_env_module_reset(mlxsw_core, module);
489 	if (err) {
490 		netdev_err(netdev, "Failed to reset module\n");
491 		goto out;
492 	}
493 
494 	*flags &= ~(ETH_RESET_PHY | (ETH_RESET_PHY << ETH_RESET_SHARED_SHIFT));
495 
496 out:
497 	mutex_unlock(&mlxsw_env->module_info_lock);
498 	return err;
499 }
500 EXPORT_SYMBOL(mlxsw_env_reset_module);
501 
502 int
503 mlxsw_env_get_module_power_mode(struct mlxsw_core *mlxsw_core, u8 module,
504 				struct ethtool_module_power_mode_params *params,
505 				struct netlink_ext_ack *extack)
506 {
507 	struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core);
508 	char mcion_pl[MLXSW_REG_MCION_LEN];
509 	u32 status_bits;
510 	int err;
511 
512 	mutex_lock(&mlxsw_env->module_info_lock);
513 
514 	err = __mlxsw_env_validate_module_type(mlxsw_core, module);
515 	if (err) {
516 		NL_SET_ERR_MSG_MOD(extack, "Power mode is not supported on port module type");
517 		goto out;
518 	}
519 
520 	params->policy = mlxsw_env->module_info[module].power_mode_policy;
521 
522 	mlxsw_reg_mcion_pack(mcion_pl, module);
523 	err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mcion), mcion_pl);
524 	if (err) {
525 		NL_SET_ERR_MSG_MOD(extack, "Failed to retrieve module's power mode");
526 		goto out;
527 	}
528 
529 	status_bits = mlxsw_reg_mcion_module_status_bits_get(mcion_pl);
530 	if (!(status_bits & MLXSW_REG_MCION_MODULE_STATUS_BITS_PRESENT_MASK))
531 		goto out;
532 
533 	if (status_bits & MLXSW_REG_MCION_MODULE_STATUS_BITS_LOW_POWER_MASK)
534 		params->mode = ETHTOOL_MODULE_POWER_MODE_LOW;
535 	else
536 		params->mode = ETHTOOL_MODULE_POWER_MODE_HIGH;
537 
538 out:
539 	mutex_unlock(&mlxsw_env->module_info_lock);
540 	return err;
541 }
542 EXPORT_SYMBOL(mlxsw_env_get_module_power_mode);
543 
544 static int mlxsw_env_module_enable_set(struct mlxsw_core *mlxsw_core,
545 				       u8 module, bool enable)
546 {
547 	enum mlxsw_reg_pmaos_admin_status admin_status;
548 	char pmaos_pl[MLXSW_REG_PMAOS_LEN];
549 
550 	mlxsw_reg_pmaos_pack(pmaos_pl, module);
551 	admin_status = enable ? MLXSW_REG_PMAOS_ADMIN_STATUS_ENABLED :
552 				MLXSW_REG_PMAOS_ADMIN_STATUS_DISABLED;
553 	mlxsw_reg_pmaos_admin_status_set(pmaos_pl, admin_status);
554 	mlxsw_reg_pmaos_ase_set(pmaos_pl, true);
555 
556 	return mlxsw_reg_write(mlxsw_core, MLXSW_REG(pmaos), pmaos_pl);
557 }
558 
559 static int mlxsw_env_module_low_power_set(struct mlxsw_core *mlxsw_core,
560 					  u8 module, bool low_power)
561 {
562 	u16 eeprom_override_mask, eeprom_override;
563 	char pmmp_pl[MLXSW_REG_PMMP_LEN];
564 
565 	mlxsw_reg_pmmp_pack(pmmp_pl, module);
566 	mlxsw_reg_pmmp_sticky_set(pmmp_pl, true);
567 	/* Mask all the bits except low power mode. */
568 	eeprom_override_mask = ~MLXSW_REG_PMMP_EEPROM_OVERRIDE_LOW_POWER_MASK;
569 	mlxsw_reg_pmmp_eeprom_override_mask_set(pmmp_pl, eeprom_override_mask);
570 	eeprom_override = low_power ? MLXSW_REG_PMMP_EEPROM_OVERRIDE_LOW_POWER_MASK :
571 				      0;
572 	mlxsw_reg_pmmp_eeprom_override_set(pmmp_pl, eeprom_override);
573 
574 	return mlxsw_reg_write(mlxsw_core, MLXSW_REG(pmmp), pmmp_pl);
575 }
576 
577 static int __mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core,
578 					     u8 module, bool low_power,
579 					     struct netlink_ext_ack *extack)
580 {
581 	int err;
582 
583 	err = mlxsw_env_module_enable_set(mlxsw_core, module, false);
584 	if (err) {
585 		NL_SET_ERR_MSG_MOD(extack, "Failed to disable module");
586 		return err;
587 	}
588 
589 	err = mlxsw_env_module_low_power_set(mlxsw_core, module, low_power);
590 	if (err) {
591 		NL_SET_ERR_MSG_MOD(extack, "Failed to set module's power mode");
592 		goto err_module_low_power_set;
593 	}
594 
595 	err = mlxsw_env_module_enable_set(mlxsw_core, module, true);
596 	if (err) {
597 		NL_SET_ERR_MSG_MOD(extack, "Failed to enable module");
598 		goto err_module_enable_set;
599 	}
600 
601 	return 0;
602 
603 err_module_enable_set:
604 	mlxsw_env_module_low_power_set(mlxsw_core, module, !low_power);
605 err_module_low_power_set:
606 	mlxsw_env_module_enable_set(mlxsw_core, module, true);
607 	return err;
608 }
609 
610 int
611 mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, u8 module,
612 				enum ethtool_module_power_mode_policy policy,
613 				struct netlink_ext_ack *extack)
614 {
615 	struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core);
616 	bool low_power;
617 	int err = 0;
618 
619 	if (policy != ETHTOOL_MODULE_POWER_MODE_POLICY_HIGH &&
620 	    policy != ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO) {
621 		NL_SET_ERR_MSG_MOD(extack, "Unsupported power mode policy");
622 		return -EOPNOTSUPP;
623 	}
624 
625 	mutex_lock(&mlxsw_env->module_info_lock);
626 
627 	err = __mlxsw_env_validate_module_type(mlxsw_core, module);
628 	if (err) {
629 		NL_SET_ERR_MSG_MOD(extack,
630 				   "Power mode set is not supported on port module type");
631 		goto out;
632 	}
633 
634 	if (mlxsw_env->module_info[module].power_mode_policy == policy)
635 		goto out;
636 
637 	/* If any ports are up, we are already in high power mode. */
638 	if (mlxsw_env->module_info[module].num_ports_up)
639 		goto out_set_policy;
640 
641 	low_power = policy == ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO;
642 	err = __mlxsw_env_set_module_power_mode(mlxsw_core, module, low_power,
643 						extack);
644 	if (err)
645 		goto out;
646 
647 out_set_policy:
648 	mlxsw_env->module_info[module].power_mode_policy = policy;
649 out:
650 	mutex_unlock(&mlxsw_env->module_info_lock);
651 	return err;
652 }
653 EXPORT_SYMBOL(mlxsw_env_set_module_power_mode);
654 
655 static int mlxsw_env_module_has_temp_sensor(struct mlxsw_core *mlxsw_core,
656 					    u8 module,
657 					    bool *p_has_temp_sensor)
658 {
659 	char mtbr_pl[MLXSW_REG_MTBR_LEN];
660 	u16 temp;
661 	int err;
662 
663 	mlxsw_reg_mtbr_pack(mtbr_pl, MLXSW_REG_MTBR_BASE_MODULE_INDEX + module,
664 			    1);
665 	err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mtbr), mtbr_pl);
666 	if (err)
667 		return err;
668 
669 	mlxsw_reg_mtbr_temp_unpack(mtbr_pl, 0, &temp, NULL);
670 
671 	switch (temp) {
672 	case MLXSW_REG_MTBR_BAD_SENS_INFO:
673 	case MLXSW_REG_MTBR_NO_CONN:
674 	case MLXSW_REG_MTBR_NO_TEMP_SENS:
675 	case MLXSW_REG_MTBR_INDEX_NA:
676 		*p_has_temp_sensor = false;
677 		break;
678 	default:
679 		*p_has_temp_sensor = temp ? true : false;
680 	}
681 	return 0;
682 }
683 
684 static int mlxsw_env_temp_event_set(struct mlxsw_core *mlxsw_core,
685 				    u16 sensor_index, bool enable)
686 {
687 	char mtmp_pl[MLXSW_REG_MTMP_LEN] = {0};
688 	enum mlxsw_reg_mtmp_tee tee;
689 	int err, threshold_hi;
690 
691 	mlxsw_reg_mtmp_sensor_index_set(mtmp_pl, sensor_index);
692 	err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mtmp), mtmp_pl);
693 	if (err)
694 		return err;
695 
696 	if (enable) {
697 		err = mlxsw_env_module_temp_thresholds_get(mlxsw_core,
698 							   sensor_index -
699 							   MLXSW_REG_MTMP_MODULE_INDEX_MIN,
700 							   SFP_TEMP_HIGH_WARN,
701 							   &threshold_hi);
702 		/* In case it is not possible to query the module's threshold,
703 		 * use the default value.
704 		 */
705 		if (err)
706 			threshold_hi = MLXSW_REG_MTMP_THRESH_HI;
707 		else
708 			/* mlxsw_env_module_temp_thresholds_get() multiplies
709 			 * Celsius degrees by 1000 whereas MTMP expects
710 			 * temperature in 0.125 Celsius degrees units.
711 			 * Convert threshold_hi to correct units.
712 			 */
713 			threshold_hi = threshold_hi / 1000 * 8;
714 
715 		mlxsw_reg_mtmp_temperature_threshold_hi_set(mtmp_pl, threshold_hi);
716 		mlxsw_reg_mtmp_temperature_threshold_lo_set(mtmp_pl, threshold_hi -
717 							    MLXSW_REG_MTMP_HYSTERESIS_TEMP);
718 	}
719 	tee = enable ? MLXSW_REG_MTMP_TEE_GENERATE_EVENT : MLXSW_REG_MTMP_TEE_NO_EVENT;
720 	mlxsw_reg_mtmp_tee_set(mtmp_pl, tee);
721 	return mlxsw_reg_write(mlxsw_core, MLXSW_REG(mtmp), mtmp_pl);
722 }
723 
724 static int mlxsw_env_module_temp_event_enable(struct mlxsw_core *mlxsw_core)
725 {
726 	int i, err, sensor_index;
727 	bool has_temp_sensor;
728 
729 	for (i = 0; i < mlxsw_core_env(mlxsw_core)->module_count; i++) {
730 		err = mlxsw_env_module_has_temp_sensor(mlxsw_core, i,
731 						       &has_temp_sensor);
732 		if (err)
733 			return err;
734 
735 		if (!has_temp_sensor)
736 			continue;
737 
738 		sensor_index = i + MLXSW_REG_MTMP_MODULE_INDEX_MIN;
739 		err = mlxsw_env_temp_event_set(mlxsw_core, sensor_index, true);
740 		if (err)
741 			return err;
742 	}
743 
744 	return 0;
745 }
746 
747 struct mlxsw_env_module_temp_warn_event {
748 	struct mlxsw_env *mlxsw_env;
749 	char mtwe_pl[MLXSW_REG_MTWE_LEN];
750 	struct work_struct work;
751 };
752 
753 static void mlxsw_env_mtwe_event_work(struct work_struct *work)
754 {
755 	struct mlxsw_env_module_temp_warn_event *event;
756 	struct mlxsw_env *mlxsw_env;
757 	int i, sensor_warning;
758 	bool is_overheat;
759 
760 	event = container_of(work, struct mlxsw_env_module_temp_warn_event,
761 			     work);
762 	mlxsw_env = event->mlxsw_env;
763 
764 	for (i = 0; i < mlxsw_env->module_count; i++) {
765 		/* 64-127 of sensor_index are mapped to the port modules
766 		 * sequentially (module 0 is mapped to sensor_index 64,
767 		 * module 1 to sensor_index 65 and so on)
768 		 */
769 		sensor_warning =
770 			mlxsw_reg_mtwe_sensor_warning_get(event->mtwe_pl,
771 							  i + MLXSW_REG_MTMP_MODULE_INDEX_MIN);
772 		mutex_lock(&mlxsw_env->module_info_lock);
773 		is_overheat =
774 			mlxsw_env->module_info[i].is_overheat;
775 
776 		if ((is_overheat && sensor_warning) ||
777 		    (!is_overheat && !sensor_warning)) {
778 			/* Current state is "warning" and MTWE still reports
779 			 * warning OR current state in "no warning" and MTWE
780 			 * does not report warning.
781 			 */
782 			mutex_unlock(&mlxsw_env->module_info_lock);
783 			continue;
784 		} else if (is_overheat && !sensor_warning) {
785 			/* MTWE reports "no warning", turn is_overheat off.
786 			 */
787 			mlxsw_env->module_info[i].is_overheat = false;
788 			mutex_unlock(&mlxsw_env->module_info_lock);
789 		} else {
790 			/* Current state is "no warning" and MTWE reports
791 			 * "warning", increase the counter and turn is_overheat
792 			 * on.
793 			 */
794 			mlxsw_env->module_info[i].is_overheat = true;
795 			mlxsw_env->module_info[i].module_overheat_counter++;
796 			mutex_unlock(&mlxsw_env->module_info_lock);
797 		}
798 	}
799 
800 	kfree(event);
801 }
802 
803 static void
804 mlxsw_env_mtwe_listener_func(const struct mlxsw_reg_info *reg, char *mtwe_pl,
805 			     void *priv)
806 {
807 	struct mlxsw_env_module_temp_warn_event *event;
808 	struct mlxsw_env *mlxsw_env = priv;
809 
810 	event = kmalloc(sizeof(*event), GFP_ATOMIC);
811 	if (!event)
812 		return;
813 
814 	event->mlxsw_env = mlxsw_env;
815 	memcpy(event->mtwe_pl, mtwe_pl, MLXSW_REG_MTWE_LEN);
816 	INIT_WORK(&event->work, mlxsw_env_mtwe_event_work);
817 	mlxsw_core_schedule_work(&event->work);
818 }
819 
820 static const struct mlxsw_listener mlxsw_env_temp_warn_listener =
821 	MLXSW_CORE_EVENTL(mlxsw_env_mtwe_listener_func, MTWE);
822 
823 static int mlxsw_env_temp_warn_event_register(struct mlxsw_core *mlxsw_core)
824 {
825 	struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core);
826 
827 	return mlxsw_core_trap_register(mlxsw_core,
828 					&mlxsw_env_temp_warn_listener,
829 					mlxsw_env);
830 }
831 
832 static void mlxsw_env_temp_warn_event_unregister(struct mlxsw_env *mlxsw_env)
833 {
834 	mlxsw_core_trap_unregister(mlxsw_env->core,
835 				   &mlxsw_env_temp_warn_listener, mlxsw_env);
836 }
837 
838 struct mlxsw_env_module_plug_unplug_event {
839 	struct mlxsw_env *mlxsw_env;
840 	u8 module;
841 	struct work_struct work;
842 };
843 
844 static void mlxsw_env_pmpe_event_work(struct work_struct *work)
845 {
846 	struct mlxsw_env_module_plug_unplug_event *event;
847 	struct mlxsw_env *mlxsw_env;
848 	bool has_temp_sensor;
849 	u16 sensor_index;
850 	int err;
851 
852 	event = container_of(work, struct mlxsw_env_module_plug_unplug_event,
853 			     work);
854 	mlxsw_env = event->mlxsw_env;
855 
856 	mutex_lock(&mlxsw_env->module_info_lock);
857 	mlxsw_env->module_info[event->module].is_overheat = false;
858 	mutex_unlock(&mlxsw_env->module_info_lock);
859 
860 	err = mlxsw_env_module_has_temp_sensor(mlxsw_env->core, event->module,
861 					       &has_temp_sensor);
862 	/* Do not disable events on modules without sensors or faulty sensors
863 	 * because FW returns errors.
864 	 */
865 	if (err)
866 		goto out;
867 
868 	if (!has_temp_sensor)
869 		goto out;
870 
871 	sensor_index = event->module + MLXSW_REG_MTMP_MODULE_INDEX_MIN;
872 	mlxsw_env_temp_event_set(mlxsw_env->core, sensor_index, true);
873 
874 out:
875 	kfree(event);
876 }
877 
878 static void
879 mlxsw_env_pmpe_listener_func(const struct mlxsw_reg_info *reg, char *pmpe_pl,
880 			     void *priv)
881 {
882 	struct mlxsw_env_module_plug_unplug_event *event;
883 	enum mlxsw_reg_pmpe_module_status module_status;
884 	u8 module = mlxsw_reg_pmpe_module_get(pmpe_pl);
885 	struct mlxsw_env *mlxsw_env = priv;
886 
887 	if (WARN_ON_ONCE(module >= mlxsw_env->module_count))
888 		return;
889 
890 	module_status = mlxsw_reg_pmpe_module_status_get(pmpe_pl);
891 	if (module_status != MLXSW_REG_PMPE_MODULE_STATUS_PLUGGED_ENABLED)
892 		return;
893 
894 	event = kmalloc(sizeof(*event), GFP_ATOMIC);
895 	if (!event)
896 		return;
897 
898 	event->mlxsw_env = mlxsw_env;
899 	event->module = module;
900 	INIT_WORK(&event->work, mlxsw_env_pmpe_event_work);
901 	mlxsw_core_schedule_work(&event->work);
902 }
903 
904 static const struct mlxsw_listener mlxsw_env_module_plug_listener =
905 	MLXSW_CORE_EVENTL(mlxsw_env_pmpe_listener_func, PMPE);
906 
907 static int
908 mlxsw_env_module_plug_event_register(struct mlxsw_core *mlxsw_core)
909 {
910 	struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core);
911 
912 	return mlxsw_core_trap_register(mlxsw_core,
913 					&mlxsw_env_module_plug_listener,
914 					mlxsw_env);
915 }
916 
917 static void
918 mlxsw_env_module_plug_event_unregister(struct mlxsw_env *mlxsw_env)
919 {
920 	mlxsw_core_trap_unregister(mlxsw_env->core,
921 				   &mlxsw_env_module_plug_listener,
922 				   mlxsw_env);
923 }
924 
925 static int
926 mlxsw_env_module_oper_state_event_enable(struct mlxsw_core *mlxsw_core)
927 {
928 	int i, err;
929 
930 	for (i = 0; i < mlxsw_core_env(mlxsw_core)->module_count; i++) {
931 		char pmaos_pl[MLXSW_REG_PMAOS_LEN];
932 
933 		mlxsw_reg_pmaos_pack(pmaos_pl, i);
934 		mlxsw_reg_pmaos_e_set(pmaos_pl,
935 				      MLXSW_REG_PMAOS_E_GENERATE_EVENT);
936 		mlxsw_reg_pmaos_ee_set(pmaos_pl, true);
937 		err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(pmaos), pmaos_pl);
938 		if (err)
939 			return err;
940 	}
941 	return 0;
942 }
943 
944 int
945 mlxsw_env_module_overheat_counter_get(struct mlxsw_core *mlxsw_core, u8 module,
946 				      u64 *p_counter)
947 {
948 	struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core);
949 
950 	mutex_lock(&mlxsw_env->module_info_lock);
951 	*p_counter = mlxsw_env->module_info[module].module_overheat_counter;
952 	mutex_unlock(&mlxsw_env->module_info_lock);
953 
954 	return 0;
955 }
956 EXPORT_SYMBOL(mlxsw_env_module_overheat_counter_get);
957 
958 void mlxsw_env_module_port_map(struct mlxsw_core *mlxsw_core, u8 module)
959 {
960 	struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core);
961 
962 	mutex_lock(&mlxsw_env->module_info_lock);
963 	mlxsw_env->module_info[module].num_ports_mapped++;
964 	mutex_unlock(&mlxsw_env->module_info_lock);
965 }
966 EXPORT_SYMBOL(mlxsw_env_module_port_map);
967 
968 void mlxsw_env_module_port_unmap(struct mlxsw_core *mlxsw_core, u8 module)
969 {
970 	struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core);
971 
972 	mutex_lock(&mlxsw_env->module_info_lock);
973 	mlxsw_env->module_info[module].num_ports_mapped--;
974 	mutex_unlock(&mlxsw_env->module_info_lock);
975 }
976 EXPORT_SYMBOL(mlxsw_env_module_port_unmap);
977 
978 int mlxsw_env_module_port_up(struct mlxsw_core *mlxsw_core, u8 module)
979 {
980 	struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core);
981 	int err = 0;
982 
983 	mutex_lock(&mlxsw_env->module_info_lock);
984 
985 	if (mlxsw_env->module_info[module].power_mode_policy !=
986 	    ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO)
987 		goto out_inc;
988 
989 	if (mlxsw_env->module_info[module].num_ports_up != 0)
990 		goto out_inc;
991 
992 	/* Transition to high power mode following first port using the module
993 	 * being put administratively up.
994 	 */
995 	err = __mlxsw_env_set_module_power_mode(mlxsw_core, module, false,
996 						NULL);
997 	if (err)
998 		goto out_unlock;
999 
1000 out_inc:
1001 	mlxsw_env->module_info[module].num_ports_up++;
1002 out_unlock:
1003 	mutex_unlock(&mlxsw_env->module_info_lock);
1004 	return err;
1005 }
1006 EXPORT_SYMBOL(mlxsw_env_module_port_up);
1007 
1008 void mlxsw_env_module_port_down(struct mlxsw_core *mlxsw_core, u8 module)
1009 {
1010 	struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core);
1011 
1012 	mutex_lock(&mlxsw_env->module_info_lock);
1013 
1014 	mlxsw_env->module_info[module].num_ports_up--;
1015 
1016 	if (mlxsw_env->module_info[module].power_mode_policy !=
1017 	    ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO)
1018 		goto out_unlock;
1019 
1020 	if (mlxsw_env->module_info[module].num_ports_up != 0)
1021 		goto out_unlock;
1022 
1023 	/* Transition to low power mode following last port using the module
1024 	 * being put administratively down.
1025 	 */
1026 	__mlxsw_env_set_module_power_mode(mlxsw_core, module, true, NULL);
1027 
1028 out_unlock:
1029 	mutex_unlock(&mlxsw_env->module_info_lock);
1030 }
1031 EXPORT_SYMBOL(mlxsw_env_module_port_down);
1032 
1033 static int
1034 mlxsw_env_module_type_set(struct mlxsw_core *mlxsw_core)
1035 {
1036 	struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core);
1037 	int i;
1038 
1039 	for (i = 0; i < mlxsw_env->module_count; i++) {
1040 		char pmtm_pl[MLXSW_REG_PMTM_LEN];
1041 		int err;
1042 
1043 		mlxsw_reg_pmtm_pack(pmtm_pl, 0, i);
1044 		err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(pmtm), pmtm_pl);
1045 		if (err)
1046 			return err;
1047 
1048 		mlxsw_env->module_info[i].type =
1049 			mlxsw_reg_pmtm_module_type_get(pmtm_pl);
1050 	}
1051 
1052 	return 0;
1053 }
1054 
1055 int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env)
1056 {
1057 	char mgpir_pl[MLXSW_REG_MGPIR_LEN];
1058 	struct mlxsw_env *env;
1059 	u8 module_count;
1060 	int i, err;
1061 
1062 	mlxsw_reg_mgpir_pack(mgpir_pl);
1063 	err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mgpir), mgpir_pl);
1064 	if (err)
1065 		return err;
1066 
1067 	mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL, &module_count);
1068 
1069 	env = kzalloc(struct_size(env, module_info, module_count), GFP_KERNEL);
1070 	if (!env)
1071 		return -ENOMEM;
1072 
1073 	/* Firmware defaults to high power mode policy where modules are
1074 	 * transitioned to high power mode following plug-in.
1075 	 */
1076 	for (i = 0; i < module_count; i++)
1077 		env->module_info[i].power_mode_policy =
1078 			ETHTOOL_MODULE_POWER_MODE_POLICY_HIGH;
1079 
1080 	mutex_init(&env->module_info_lock);
1081 	env->core = mlxsw_core;
1082 	env->module_count = module_count;
1083 	*p_env = env;
1084 
1085 	err = mlxsw_env_temp_warn_event_register(mlxsw_core);
1086 	if (err)
1087 		goto err_temp_warn_event_register;
1088 
1089 	err = mlxsw_env_module_plug_event_register(mlxsw_core);
1090 	if (err)
1091 		goto err_module_plug_event_register;
1092 
1093 	err = mlxsw_env_module_oper_state_event_enable(mlxsw_core);
1094 	if (err)
1095 		goto err_oper_state_event_enable;
1096 
1097 	err = mlxsw_env_module_temp_event_enable(mlxsw_core);
1098 	if (err)
1099 		goto err_temp_event_enable;
1100 
1101 	err = mlxsw_env_module_type_set(mlxsw_core);
1102 	if (err)
1103 		goto err_type_set;
1104 
1105 	return 0;
1106 
1107 err_type_set:
1108 err_temp_event_enable:
1109 err_oper_state_event_enable:
1110 	mlxsw_env_module_plug_event_unregister(env);
1111 err_module_plug_event_register:
1112 	mlxsw_env_temp_warn_event_unregister(env);
1113 err_temp_warn_event_register:
1114 	mutex_destroy(&env->module_info_lock);
1115 	kfree(env);
1116 	return err;
1117 }
1118 
1119 void mlxsw_env_fini(struct mlxsw_env *env)
1120 {
1121 	mlxsw_env_module_plug_event_unregister(env);
1122 	/* Make sure there is no more event work scheduled. */
1123 	mlxsw_core_flush_owq();
1124 	mlxsw_env_temp_warn_event_unregister(env);
1125 	mutex_destroy(&env->module_info_lock);
1126 	kfree(env);
1127 }
1128