17a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann/*
27a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann *  linux/drivers/net/ehea/ehea_main.c
37a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann *
47a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann *  eHEA ethernet device driver for IBM eServer System p
57a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann *
67a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann *  (C) Copyright IBM Corp. 2006
77a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann *
87a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann *  Authors:
9508d2b5d261abbd7fb728092c5025c5063060c04Doug Maxey *	 Christoph Raisch <raisch@de.ibm.com>
10508d2b5d261abbd7fb728092c5025c5063060c04Doug Maxey *	 Jan-Bernd Themann <themann@de.ibm.com>
11508d2b5d261abbd7fb728092c5025c5063060c04Doug Maxey *	 Thomas Klein <tklein@de.ibm.com>
127a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann *
137a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann *
147a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann * This program is free software; you can redistribute it and/or modify
157a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann * it under the terms of the GNU General Public License as published by
167a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann * the Free Software Foundation; either version 2, or (at your option)
177a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann * any later version.
187a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann *
197a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann * This program is distributed in the hope that it will be useful,
207a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann * but WITHOUT ANY WARRANTY; without even the implied warranty of
217a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
227a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann * GNU General Public License for more details.
237a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann *
247a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann * You should have received a copy of the GNU General Public License
257a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann * along with this program; if not, write to the Free Software
267a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
277a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann */
287a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
298c4877a4128e7931077b024a891a4b284d8756a3Joe Perches#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
308c4877a4128e7931077b024a891a4b284d8756a3Joe Perches
317a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann#include <linux/in.h>
327a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann#include <linux/ip.h>
337a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann#include <linux/tcp.h>
347a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann#include <linux/udp.h>
357a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann#include <linux/if.h>
367a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann#include <linux/list.h>
375a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
387a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann#include <linux/if_ether.h>
392a6f4e4983918b18fe5d3fb364afe33db7139870Jan-Bernd Themann#include <linux/notifier.h>
402a6f4e4983918b18fe5d3fb364afe33db7139870Jan-Bernd Themann#include <linux/reboot.h>
4148cfb14f8b89d4d5b3df6c16f08b258686fb12adHannes Hering#include <linux/memory.h>
4221eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein#include <asm/kexec.h>
4306f89edf89f254346c95d0c569cecd606459d83eDaniel Walker#include <linux/mutex.h>
44268bb0ce3e87872cb9290c322b0d35bce230d88fLinus Torvalds#include <linux/prefetch.h>
452a6f4e4983918b18fe5d3fb364afe33db7139870Jan-Bernd Themann
467a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann#include <net/ip.h>
477a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
487a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann#include "ehea.h"
497a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann#include "ehea_qmr.h"
507a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann#include "ehea_phyp.h"
517a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
527a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
537a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd ThemannMODULE_LICENSE("GPL");
547a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd ThemannMODULE_AUTHOR("Christoph Raisch <raisch@de.ibm.com>");
557a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd ThemannMODULE_DESCRIPTION("IBM eServer HEA Driver");
567a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd ThemannMODULE_VERSION(DRV_VERSION);
577a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
587a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
597a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic int msg_level = -1;
607a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic int rq1_entries = EHEA_DEF_ENTRIES_RQ1;
617a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic int rq2_entries = EHEA_DEF_ENTRIES_RQ2;
627a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic int rq3_entries = EHEA_DEF_ENTRIES_RQ3;
637a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic int sq_entries = EHEA_DEF_ENTRIES_SQ;
64b95644685d530de5e9f9658bd8087e50840b831dAnton Blanchardstatic int use_mcs = 1;
65508d2b5d261abbd7fb728092c5025c5063060c04Doug Maxeystatic int prop_carrier_state;
667a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
677a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannmodule_param(msg_level, int, 0);
687a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannmodule_param(rq1_entries, int, 0);
697a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannmodule_param(rq2_entries, int, 0);
707a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannmodule_param(rq3_entries, int, 0);
717a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannmodule_param(sq_entries, int, 0);
728759cf76e9a6322fc68dcbfaa1cbad00c74b199eJan-Bernd Themannmodule_param(prop_carrier_state, int, 0);
7318604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themannmodule_param(use_mcs, int, 0);
747a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
757a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd ThemannMODULE_PARM_DESC(msg_level, "msg_level");
768759cf76e9a6322fc68dcbfaa1cbad00c74b199eJan-Bernd ThemannMODULE_PARM_DESC(prop_carrier_state, "Propagate carrier state of physical "
778759cf76e9a6322fc68dcbfaa1cbad00c74b199eJan-Bernd Themann		 "port to stack. 1:yes, 0:no.  Default = 0 ");
787a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd ThemannMODULE_PARM_DESC(rq3_entries, "Number of entries for Receive Queue 3 "
797a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		 "[2^x - 1], x = [6..14]. Default = "
807a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		 __MODULE_STRING(EHEA_DEF_ENTRIES_RQ3) ")");
817a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd ThemannMODULE_PARM_DESC(rq2_entries, "Number of entries for Receive Queue 2 "
827a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		 "[2^x - 1], x = [6..14]. Default = "
837a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		 __MODULE_STRING(EHEA_DEF_ENTRIES_RQ2) ")");
847a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd ThemannMODULE_PARM_DESC(rq1_entries, "Number of entries for Receive Queue 1 "
857a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		 "[2^x - 1], x = [6..14]. Default = "
867a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		 __MODULE_STRING(EHEA_DEF_ENTRIES_RQ1) ")");
877a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd ThemannMODULE_PARM_DESC(sq_entries, " Number of entries for the Send Queue  "
887a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		 "[2^x - 1], x = [6..14]. Default = "
897a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		 __MODULE_STRING(EHEA_DEF_ENTRIES_SQ) ")");
90b95644685d530de5e9f9658bd8087e50840b831dAnton BlanchardMODULE_PARM_DESC(use_mcs, " Multiple receive queues, 1: enable, 0: disable, "
91b95644685d530de5e9f9658bd8087e50840b831dAnton Blanchard		 "Default = 1");
927a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
93508d2b5d261abbd7fb728092c5025c5063060c04Doug Maxeystatic int port_name_cnt;
9444c821525778c5d2e81da293195d5d589e8ad845Thomas Kleinstatic LIST_HEAD(adapter_list);
9548e4cc777c091b037acaf39036a77ece43fe1ab9Stephen Rothwellstatic unsigned long ehea_driver_flags;
9606f89edf89f254346c95d0c569cecd606459d83eDaniel Walkerstatic DEFINE_MUTEX(dlpar_mem_lock);
971886e5d2c694e7fb59434c717e704e7fd8475d2eThadeu Lima de Souza Cascardostatic struct ehea_fw_handle_array ehea_fw_handles;
981886e5d2c694e7fb59434c717e704e7fd8475d2eThadeu Lima de Souza Cascardostatic struct ehea_bcmc_reg_array ehea_bcmc_regs;
9921eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
100d1dea38d54311f6b3dd37ce485e794bd133e3593Thomas Klein
1012dc11581376829303b98eadb2de253bee065a56aGrant Likelystatic int __devinit ehea_probe_adapter(struct platform_device *dev,
102d1d25aaba85fd24ab18b0a4d22f19be02aac65c9Jan-Bernd Themann					const struct of_device_id *id);
103d1dea38d54311f6b3dd37ce485e794bd133e3593Thomas Klein
1042dc11581376829303b98eadb2de253bee065a56aGrant Likelystatic int __devexit ehea_remove(struct platform_device *dev);
105d1dea38d54311f6b3dd37ce485e794bd133e3593Thomas Klein
106d1dea38d54311f6b3dd37ce485e794bd133e3593Thomas Kleinstatic struct of_device_id ehea_device_table[] = {
107d1dea38d54311f6b3dd37ce485e794bd133e3593Thomas Klein	{
108d1dea38d54311f6b3dd37ce485e794bd133e3593Thomas Klein		.name = "lhea",
109d1dea38d54311f6b3dd37ce485e794bd133e3593Thomas Klein		.compatible = "IBM,lhea",
110d1dea38d54311f6b3dd37ce485e794bd133e3593Thomas Klein	},
111d1dea38d54311f6b3dd37ce485e794bd133e3593Thomas Klein	{},
112d1dea38d54311f6b3dd37ce485e794bd133e3593Thomas Klein};
113b0afffe89be619f42ae4215554ed66e67de7bb0eJan-Bernd ThemannMODULE_DEVICE_TABLE(of, ehea_device_table);
114d1dea38d54311f6b3dd37ce485e794bd133e3593Thomas Klein
1156b08f3ae8eec27a9e557468a48540bc64fd4a524Joachim Fenkesstatic struct of_platform_driver ehea_driver = {
1164018294b53d1dae026880e45f174c1cc63b5d435Grant Likely	.driver = {
1174018294b53d1dae026880e45f174c1cc63b5d435Grant Likely		.name = "ehea",
1184018294b53d1dae026880e45f174c1cc63b5d435Grant Likely		.owner = THIS_MODULE,
1194018294b53d1dae026880e45f174c1cc63b5d435Grant Likely		.of_match_table = ehea_device_table,
1204018294b53d1dae026880e45f174c1cc63b5d435Grant Likely	},
121d1dea38d54311f6b3dd37ce485e794bd133e3593Thomas Klein	.probe = ehea_probe_adapter,
122d1dea38d54311f6b3dd37ce485e794bd133e3593Thomas Klein	.remove = ehea_remove,
123d1dea38d54311f6b3dd37ce485e794bd133e3593Thomas Klein};
124d1dea38d54311f6b3dd37ce485e794bd133e3593Thomas Klein
125508d2b5d261abbd7fb728092c5025c5063060c04Doug Maxeyvoid ehea_dump(void *adr, int len, char *msg)
126508d2b5d261abbd7fb728092c5025c5063060c04Doug Maxey{
1277a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int x;
1287a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	unsigned char *deb = adr;
1297a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	for (x = 0; x < len; x += 16) {
1308c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_info("%s adr=%p ofs=%04x %016llx %016llx\n",
1318c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			msg, deb, x, *((u64 *)&deb[0]), *((u64 *)&deb[8]));
1327a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		deb += 16;
1337a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
1347a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
1357a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
1361886e5d2c694e7fb59434c717e704e7fd8475d2eThadeu Lima de Souza Cascardostatic void ehea_schedule_port_reset(struct ehea_port *port)
1372f69ae01c83a94af5dc3c20e8135b974687ed004Jan-Bernd Themann{
1382f69ae01c83a94af5dc3c20e8135b974687ed004Jan-Bernd Themann	if (!test_bit(__EHEA_DISABLE_PORT_RESET, &port->flags))
1392f69ae01c83a94af5dc3c20e8135b974687ed004Jan-Bernd Themann		schedule_work(&port->reset_task);
1402f69ae01c83a94af5dc3c20e8135b974687ed004Jan-Bernd Themann}
1412f69ae01c83a94af5dc3c20e8135b974687ed004Jan-Bernd Themann
14221eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Kleinstatic void ehea_update_firmware_handles(void)
14321eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein{
14421eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	struct ehea_fw_handle_entry *arr = NULL;
14521eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	struct ehea_adapter *adapter;
14621eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	int num_adapters = 0;
14721eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	int num_ports = 0;
14821eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	int num_portres = 0;
14921eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	int i = 0;
15021eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	int num_fw_handles, k, l;
15121eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
15221eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	/* Determine number of handles */
15352e21b1bd96444c452f6eab7dc438a8a898aa14aJan-Bernd Themann	mutex_lock(&ehea_fw_handles.lock);
15452e21b1bd96444c452f6eab7dc438a8a898aa14aJan-Bernd Themann
15521eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	list_for_each_entry(adapter, &adapter_list, list) {
15621eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein		num_adapters++;
15721eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
15821eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein		for (k = 0; k < EHEA_MAX_PORTS; k++) {
15921eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein			struct ehea_port *port = adapter->port[k];
16021eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
16121eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein			if (!port || (port->state != EHEA_PORT_UP))
16221eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein				continue;
16321eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
16421eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein			num_ports++;
165723f28e49c9f8578b418dfd1ec8c7b9cc13e2b63Anton Blanchard			num_portres += port->num_def_qps;
16621eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein		}
16721eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	}
16821eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
16921eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	num_fw_handles = num_adapters * EHEA_NUM_ADAPTER_FW_HANDLES +
17021eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein			 num_ports * EHEA_NUM_PORT_FW_HANDLES +
17121eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein			 num_portres * EHEA_NUM_PORTRES_FW_HANDLES;
17221eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
17321eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	if (num_fw_handles) {
174baeb2ffab4e67bb9174e6166e070a9a8ec94b0f6Joe Perches		arr = kcalloc(num_fw_handles, sizeof(*arr), GFP_KERNEL);
17521eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein		if (!arr)
17652e21b1bd96444c452f6eab7dc438a8a898aa14aJan-Bernd Themann			goto out;  /* Keep the existing array */
17721eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	} else
17821eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein		goto out_update;
17921eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
18021eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	list_for_each_entry(adapter, &adapter_list, list) {
18152e21b1bd96444c452f6eab7dc438a8a898aa14aJan-Bernd Themann		if (num_adapters == 0)
18252e21b1bd96444c452f6eab7dc438a8a898aa14aJan-Bernd Themann			break;
18352e21b1bd96444c452f6eab7dc438a8a898aa14aJan-Bernd Themann
18421eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein		for (k = 0; k < EHEA_MAX_PORTS; k++) {
18521eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein			struct ehea_port *port = adapter->port[k];
18621eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
1878e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches			if (!port || (port->state != EHEA_PORT_UP) ||
1888e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches			    (num_ports == 0))
18921eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein				continue;
19021eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
191723f28e49c9f8578b418dfd1ec8c7b9cc13e2b63Anton Blanchard			for (l = 0; l < port->num_def_qps; l++) {
19221eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein				struct ehea_port_res *pr = &port->port_res[l];
19321eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
19421eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein				arr[i].adh = adapter->handle;
19521eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein				arr[i++].fwh = pr->qp->fw_handle;
19621eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein				arr[i].adh = adapter->handle;
19721eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein				arr[i++].fwh = pr->send_cq->fw_handle;
19821eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein				arr[i].adh = adapter->handle;
19921eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein				arr[i++].fwh = pr->recv_cq->fw_handle;
20021eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein				arr[i].adh = adapter->handle;
20121eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein				arr[i++].fwh = pr->eq->fw_handle;
20221eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein				arr[i].adh = adapter->handle;
20321eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein				arr[i++].fwh = pr->send_mr.handle;
20421eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein				arr[i].adh = adapter->handle;
20521eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein				arr[i++].fwh = pr->recv_mr.handle;
20621eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein			}
20721eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein			arr[i].adh = adapter->handle;
20821eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein			arr[i++].fwh = port->qp_eq->fw_handle;
20952e21b1bd96444c452f6eab7dc438a8a898aa14aJan-Bernd Themann			num_ports--;
21021eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein		}
21121eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
21221eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein		arr[i].adh = adapter->handle;
21321eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein		arr[i++].fwh = adapter->neq->fw_handle;
21421eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
21521eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein		if (adapter->mr.handle) {
21621eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein			arr[i].adh = adapter->handle;
21721eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein			arr[i++].fwh = adapter->mr.handle;
21821eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein		}
21952e21b1bd96444c452f6eab7dc438a8a898aa14aJan-Bernd Themann		num_adapters--;
22021eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	}
22121eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
22221eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Kleinout_update:
22321eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	kfree(ehea_fw_handles.arr);
22421eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	ehea_fw_handles.arr = arr;
22521eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	ehea_fw_handles.num_entries = i;
22652e21b1bd96444c452f6eab7dc438a8a898aa14aJan-Bernd Themannout:
22752e21b1bd96444c452f6eab7dc438a8a898aa14aJan-Bernd Themann	mutex_unlock(&ehea_fw_handles.lock);
22821eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein}
22921eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
23021eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Kleinstatic void ehea_update_bcmc_registrations(void)
23121eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein{
23252e21b1bd96444c452f6eab7dc438a8a898aa14aJan-Bernd Themann	unsigned long flags;
23321eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	struct ehea_bcmc_reg_entry *arr = NULL;
23421eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	struct ehea_adapter *adapter;
23521eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	struct ehea_mc_list *mc_entry;
23621eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	int num_registrations = 0;
23721eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	int i = 0;
23821eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	int k;
23921eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
24052e21b1bd96444c452f6eab7dc438a8a898aa14aJan-Bernd Themann	spin_lock_irqsave(&ehea_bcmc_regs.lock, flags);
24152e21b1bd96444c452f6eab7dc438a8a898aa14aJan-Bernd Themann
24221eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	/* Determine number of registrations */
24321eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	list_for_each_entry(adapter, &adapter_list, list)
24421eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein		for (k = 0; k < EHEA_MAX_PORTS; k++) {
24521eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein			struct ehea_port *port = adapter->port[k];
24621eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
24721eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein			if (!port || (port->state != EHEA_PORT_UP))
24821eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein				continue;
24921eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
25021eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein			num_registrations += 2;	/* Broadcast registrations */
25121eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
25221eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein			list_for_each_entry(mc_entry, &port->mc_list->list,list)
25321eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein				num_registrations += 2;
25421eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein		}
25521eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
25621eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	if (num_registrations) {
257baeb2ffab4e67bb9174e6166e070a9a8ec94b0f6Joe Perches		arr = kcalloc(num_registrations, sizeof(*arr), GFP_ATOMIC);
25821eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein		if (!arr)
25952e21b1bd96444c452f6eab7dc438a8a898aa14aJan-Bernd Themann			goto out;  /* Keep the existing array */
26021eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	} else
26121eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein		goto out_update;
26221eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
26321eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	list_for_each_entry(adapter, &adapter_list, list) {
26421eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein		for (k = 0; k < EHEA_MAX_PORTS; k++) {
26521eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein			struct ehea_port *port = adapter->port[k];
26621eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
26721eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein			if (!port || (port->state != EHEA_PORT_UP))
26821eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein				continue;
26921eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
27052e21b1bd96444c452f6eab7dc438a8a898aa14aJan-Bernd Themann			if (num_registrations == 0)
27152e21b1bd96444c452f6eab7dc438a8a898aa14aJan-Bernd Themann				goto out_update;
27252e21b1bd96444c452f6eab7dc438a8a898aa14aJan-Bernd Themann
27321eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein			arr[i].adh = adapter->handle;
27421eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein			arr[i].port_id = port->logical_port_id;
27521eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein			arr[i].reg_type = EHEA_BCMC_BROADCAST |
27621eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein					  EHEA_BCMC_UNTAGGED;
27721eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein			arr[i++].macaddr = port->mac_addr;
27821eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
27921eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein			arr[i].adh = adapter->handle;
28021eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein			arr[i].port_id = port->logical_port_id;
28121eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein			arr[i].reg_type = EHEA_BCMC_BROADCAST |
28221eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein					  EHEA_BCMC_VLANID_ALL;
28321eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein			arr[i++].macaddr = port->mac_addr;
28452e21b1bd96444c452f6eab7dc438a8a898aa14aJan-Bernd Themann			num_registrations -= 2;
28521eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
28621eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein			list_for_each_entry(mc_entry,
28721eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein					    &port->mc_list->list, list) {
28852e21b1bd96444c452f6eab7dc438a8a898aa14aJan-Bernd Themann				if (num_registrations == 0)
28952e21b1bd96444c452f6eab7dc438a8a898aa14aJan-Bernd Themann					goto out_update;
29052e21b1bd96444c452f6eab7dc438a8a898aa14aJan-Bernd Themann
29121eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein				arr[i].adh = adapter->handle;
29221eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein				arr[i].port_id = port->logical_port_id;
29321eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein				arr[i].reg_type = EHEA_BCMC_SCOPE_ALL |
29421eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein						  EHEA_BCMC_MULTICAST |
29521eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein						  EHEA_BCMC_UNTAGGED;
29621eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein				arr[i++].macaddr = mc_entry->macaddr;
29721eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
29821eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein				arr[i].adh = adapter->handle;
29921eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein				arr[i].port_id = port->logical_port_id;
30021eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein				arr[i].reg_type = EHEA_BCMC_SCOPE_ALL |
30121eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein						  EHEA_BCMC_MULTICAST |
30221eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein						  EHEA_BCMC_VLANID_ALL;
30321eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein				arr[i++].macaddr = mc_entry->macaddr;
30452e21b1bd96444c452f6eab7dc438a8a898aa14aJan-Bernd Themann				num_registrations -= 2;
30521eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein			}
30621eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein		}
30721eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	}
30821eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
30921eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Kleinout_update:
31021eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	kfree(ehea_bcmc_regs.arr);
31121eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	ehea_bcmc_regs.arr = arr;
31221eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	ehea_bcmc_regs.num_entries = i;
31352e21b1bd96444c452f6eab7dc438a8a898aa14aJan-Bernd Themannout:
31452e21b1bd96444c452f6eab7dc438a8a898aa14aJan-Bernd Themann	spin_unlock_irqrestore(&ehea_bcmc_regs.lock, flags);
31521eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein}
31621eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
317239c562c94dcdd2aeb3d0c0e604627dec043183eAnton Blanchardstatic struct rtnl_link_stats64 *ehea_get_stats64(struct net_device *dev,
318239c562c94dcdd2aeb3d0c0e604627dec043183eAnton Blanchard					struct rtnl_link_stats64 *stats)
3197a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
3207a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_port *port = netdev_priv(dev);
3212aefcad8666e0c7c1aff51c0dacc164a1b681895brenohl@br.ibm.com	u64 rx_packets = 0, tx_packets = 0, rx_bytes = 0, tx_bytes = 0;
3227a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int i;
3237a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
3242aefcad8666e0c7c1aff51c0dacc164a1b681895brenohl@br.ibm.com	for (i = 0; i < port->num_def_qps; i++) {
3252aefcad8666e0c7c1aff51c0dacc164a1b681895brenohl@br.ibm.com		rx_packets += port->port_res[i].rx_packets;
3262aefcad8666e0c7c1aff51c0dacc164a1b681895brenohl@br.ibm.com		rx_bytes   += port->port_res[i].rx_bytes;
3272aefcad8666e0c7c1aff51c0dacc164a1b681895brenohl@br.ibm.com	}
3282aefcad8666e0c7c1aff51c0dacc164a1b681895brenohl@br.ibm.com
329723f28e49c9f8578b418dfd1ec8c7b9cc13e2b63Anton Blanchard	for (i = 0; i < port->num_def_qps; i++) {
3302aefcad8666e0c7c1aff51c0dacc164a1b681895brenohl@br.ibm.com		tx_packets += port->port_res[i].tx_packets;
3312aefcad8666e0c7c1aff51c0dacc164a1b681895brenohl@br.ibm.com		tx_bytes   += port->port_res[i].tx_bytes;
3322aefcad8666e0c7c1aff51c0dacc164a1b681895brenohl@br.ibm.com	}
3332aefcad8666e0c7c1aff51c0dacc164a1b681895brenohl@br.ibm.com
3342aefcad8666e0c7c1aff51c0dacc164a1b681895brenohl@br.ibm.com	stats->tx_packets = tx_packets;
3352aefcad8666e0c7c1aff51c0dacc164a1b681895brenohl@br.ibm.com	stats->rx_bytes = rx_bytes;
3362aefcad8666e0c7c1aff51c0dacc164a1b681895brenohl@br.ibm.com	stats->tx_bytes = tx_bytes;
3372aefcad8666e0c7c1aff51c0dacc164a1b681895brenohl@br.ibm.com	stats->rx_packets = rx_packets;
3382aefcad8666e0c7c1aff51c0dacc164a1b681895brenohl@br.ibm.com
3392aefcad8666e0c7c1aff51c0dacc164a1b681895brenohl@br.ibm.com	return &port->stats;
3402aefcad8666e0c7c1aff51c0dacc164a1b681895brenohl@br.ibm.com}
3412aefcad8666e0c7c1aff51c0dacc164a1b681895brenohl@br.ibm.com
3422aefcad8666e0c7c1aff51c0dacc164a1b681895brenohl@br.ibm.comstatic void ehea_update_stats(struct work_struct *work)
3432aefcad8666e0c7c1aff51c0dacc164a1b681895brenohl@br.ibm.com{
3442aefcad8666e0c7c1aff51c0dacc164a1b681895brenohl@br.ibm.com	struct ehea_port *port =
3452aefcad8666e0c7c1aff51c0dacc164a1b681895brenohl@br.ibm.com		container_of(work, struct ehea_port, stats_work.work);
3462aefcad8666e0c7c1aff51c0dacc164a1b681895brenohl@br.ibm.com	struct net_device *dev = port->netdev;
347239c562c94dcdd2aeb3d0c0e604627dec043183eAnton Blanchard	struct rtnl_link_stats64 *stats = &port->stats;
3482aefcad8666e0c7c1aff51c0dacc164a1b681895brenohl@br.ibm.com	struct hcp_ehea_port_cb2 *cb2;
3492aefcad8666e0c7c1aff51c0dacc164a1b681895brenohl@br.ibm.com	u64 hret;
3507a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
3513d8009c780ee90fccb5c171caf30aff839f13547Brian King	cb2 = (void *)get_zeroed_page(GFP_KERNEL);
3527a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (!cb2) {
3532aefcad8666e0c7c1aff51c0dacc164a1b681895brenohl@br.ibm.com		netdev_err(dev, "No mem for cb2. Some interface statistics were not updated\n");
3542aefcad8666e0c7c1aff51c0dacc164a1b681895brenohl@br.ibm.com		goto resched;
3557a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
3567a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
3577a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	hret = ehea_h_query_ehea_port(port->adapter->handle,
3587a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				      port->logical_port_id,
3597a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				      H_PORT_CB2, H_PORT_CB2_ALL, cb2);
3607a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (hret != H_SUCCESS) {
3618c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		netdev_err(dev, "query_ehea_port failed\n");
3627a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out_herr;
3637a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
3647a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
3657a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (netif_msg_hw(port))
3667a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ehea_dump(cb2, sizeof(*cb2), "net_device_stats");
3677a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
3687a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	stats->multicast = cb2->rxmcp;
3697a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	stats->rx_errors = cb2->rxuerr;
3707a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
3717a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannout_herr:
3723faf2693bd6800c2521799f6a9ae174d9f080ed2Thomas Klein	free_page((unsigned long)cb2);
3732aefcad8666e0c7c1aff51c0dacc164a1b681895brenohl@br.ibm.comresched:
37467c170a24fc6669f8f7c0864d75caadef0a8e5e6Anton Blanchard	schedule_delayed_work(&port->stats_work,
37567c170a24fc6669f8f7c0864d75caadef0a8e5e6Anton Blanchard			      round_jiffies_relative(msecs_to_jiffies(1000)));
3767a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
3777a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
3787a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic void ehea_refill_rq1(struct ehea_port_res *pr, int index, int nr_of_wqes)
3797a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
3807a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct sk_buff **skb_arr_rq1 = pr->rq1_skba.arr;
3817a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct net_device *dev = pr->port->netdev;
3827a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int max_index_mask = pr->rq1_skba.len - 1;
3832c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	int fill_wqes = pr->rq1_skba.os_skbs + nr_of_wqes;
3842c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	int adder = 0;
3857a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int i;
3867a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
3872c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	pr->rq1_skba.os_skbs = 0;
3882c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann
3892c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	if (unlikely(test_bit(__EHEA_STOP_XFER, &ehea_driver_flags))) {
39044fb3126d7e6fb411775551b4653643f1d28ebe9Thomas Klein		if (nr_of_wqes > 0)
39144fb3126d7e6fb411775551b4653643f1d28ebe9Thomas Klein			pr->rq1_skba.index = index;
3922c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		pr->rq1_skba.os_skbs = fill_wqes;
3937a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		return;
3942c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	}
3957a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
3962c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	for (i = 0; i < fill_wqes; i++) {
3977a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		if (!skb_arr_rq1[index]) {
3987a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			skb_arr_rq1[index] = netdev_alloc_skb(dev,
3997a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann							      EHEA_L_PKT_SIZE);
4007a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			if (!skb_arr_rq1[index]) {
4018c4877a4128e7931077b024a891a4b284d8756a3Joe Perches				netdev_info(dev, "Unable to allocate enough skb in the array\n");
4022c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann				pr->rq1_skba.os_skbs = fill_wqes - i;
4037a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				break;
4047a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			}
4057a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		}
4067a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		index--;
4077a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		index &= max_index_mask;
4082c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		adder++;
4097a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
4102c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann
4112c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	if (adder == 0)
4122c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		return;
4132c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann
4147a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	/* Ring doorbell */
4152c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	ehea_update_rq1a(pr->qp, adder);
4167a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
4177a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
418e2878806227d223467f84f900ef4c6733ee166dfThomas Kleinstatic void ehea_init_fill_rq1(struct ehea_port_res *pr, int nr_rq1a)
4197a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
4207a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct sk_buff **skb_arr_rq1 = pr->rq1_skba.arr;
4217a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct net_device *dev = pr->port->netdev;
4227a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int i;
4237a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
4245c7e57f7cddb83d81d83fefa5822dfe80891130eBreno Leitao	if (nr_rq1a > pr->rq1_skba.len) {
4258c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		netdev_err(dev, "NR_RQ1A bigger than skb array len\n");
4265c7e57f7cddb83d81d83fefa5822dfe80891130eBreno Leitao		return;
4275c7e57f7cddb83d81d83fefa5822dfe80891130eBreno Leitao	}
4285c7e57f7cddb83d81d83fefa5822dfe80891130eBreno Leitao
4295c7e57f7cddb83d81d83fefa5822dfe80891130eBreno Leitao	for (i = 0; i < nr_rq1a; i++) {
4307a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		skb_arr_rq1[i] = netdev_alloc_skb(dev, EHEA_L_PKT_SIZE);
4315c7e57f7cddb83d81d83fefa5822dfe80891130eBreno Leitao		if (!skb_arr_rq1[i]) {
4328c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			netdev_info(dev, "Not enough memory to allocate skb array\n");
433e2878806227d223467f84f900ef4c6733ee166dfThomas Klein			break;
4345c7e57f7cddb83d81d83fefa5822dfe80891130eBreno Leitao		}
4357a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
4367a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	/* Ring doorbell */
437f76957fc8fc4fa9735f01e59653b2792b077de06Breno Leitao	ehea_update_rq1a(pr->qp, i - 1);
4387a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
4397a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
4407a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic int ehea_refill_rq_def(struct ehea_port_res *pr,
4417a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			      struct ehea_q_skb_arr *q_skba, int rq_nr,
4427a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			      int num_wqes, int wqe_type, int packet_size)
4437a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
4447a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct net_device *dev = pr->port->netdev;
4457a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_qp *qp = pr->qp;
4467a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct sk_buff **skb_arr = q_skba->arr;
4477a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_rwqe *rwqe;
4487a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int i, index, max_index_mask, fill_wqes;
4492c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	int adder = 0;
4507a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int ret = 0;
4517a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
4527a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	fill_wqes = q_skba->os_skbs + num_wqes;
4532c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	q_skba->os_skbs = 0;
4547a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
4552c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	if (unlikely(test_bit(__EHEA_STOP_XFER, &ehea_driver_flags))) {
4562c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		q_skba->os_skbs = fill_wqes;
4577a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		return ret;
4582c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	}
4597a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
4607a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	index = q_skba->index;
4617a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	max_index_mask = q_skba->len - 1;
4627a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	for (i = 0; i < fill_wqes; i++) {
4632c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		u64 tmp_addr;
46489d71a66c40d629e3b1285def543ab1425558cd5Eric Dumazet		struct sk_buff *skb;
46589d71a66c40d629e3b1285def543ab1425558cd5Eric Dumazet
46689d71a66c40d629e3b1285def543ab1425558cd5Eric Dumazet		skb = netdev_alloc_skb_ip_align(dev, packet_size);
4677a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		if (!skb) {
4687a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			q_skba->os_skbs = fill_wqes - i;
469e2878806227d223467f84f900ef4c6733ee166dfThomas Klein			if (q_skba->os_skbs == q_skba->len - 2) {
4708c4877a4128e7931077b024a891a4b284d8756a3Joe Perches				netdev_info(pr->port->netdev,
4718c4877a4128e7931077b024a891a4b284d8756a3Joe Perches					    "rq%i ran dry - no mem for skb\n",
4728c4877a4128e7931077b024a891a4b284d8756a3Joe Perches					    rq_nr);
473e2878806227d223467f84f900ef4c6733ee166dfThomas Klein				ret = -ENOMEM;
474e2878806227d223467f84f900ef4c6733ee166dfThomas Klein			}
4757a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			break;
4767a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		}
4777a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
4787a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		skb_arr[index] = skb;
4792c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		tmp_addr = ehea_map_vaddr(skb->data);
4802c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		if (tmp_addr == -1) {
4812c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann			dev_kfree_skb(skb);
4822c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann			q_skba->os_skbs = fill_wqes - i;
4832c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann			ret = 0;
4842c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann			break;
4852c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		}
4867a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
4877a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		rwqe = ehea_get_next_rwqe(qp, rq_nr);
4887a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		rwqe->wr_id = EHEA_BMASK_SET(EHEA_WR_ID_TYPE, wqe_type)
489d1d25aaba85fd24ab18b0a4d22f19be02aac65c9Jan-Bernd Themann			    | EHEA_BMASK_SET(EHEA_WR_ID_INDEX, index);
4907a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		rwqe->sg_list[0].l_key = pr->recv_mr.lkey;
4912c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		rwqe->sg_list[0].vaddr = tmp_addr;
4927a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		rwqe->sg_list[0].len = packet_size;
4937a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		rwqe->data_segments = 1;
4947a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
4957a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		index++;
4967a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		index &= max_index_mask;
4972c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		adder++;
4987a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
49944c821525778c5d2e81da293195d5d589e8ad845Thomas Klein
5007a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	q_skba->index = index;
5012c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	if (adder == 0)
5022c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		goto out;
5037a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
5047a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	/* Ring doorbell */
5057a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	iosync();
5067a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (rq_nr == 2)
5072c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		ehea_update_rq2a(pr->qp, adder);
5087a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	else
5092c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		ehea_update_rq3a(pr->qp, adder);
51044c821525778c5d2e81da293195d5d589e8ad845Thomas Kleinout:
5117a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return ret;
5127a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
5137a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
5147a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
5157a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic int ehea_refill_rq2(struct ehea_port_res *pr, int nr_of_wqes)
5167a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
5177a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return ehea_refill_rq_def(pr, &pr->rq2_skba, 2,
5187a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				  nr_of_wqes, EHEA_RWQE2_TYPE,
51989d71a66c40d629e3b1285def543ab1425558cd5Eric Dumazet				  EHEA_RQ2_PKT_SIZE);
5207a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
5217a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
5227a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
5237a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic int ehea_refill_rq3(struct ehea_port_res *pr, int nr_of_wqes)
5247a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
5257a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return ehea_refill_rq_def(pr, &pr->rq3_skba, 3,
5267a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				  nr_of_wqes, EHEA_RWQE3_TYPE,
52789d71a66c40d629e3b1285def543ab1425558cd5Eric Dumazet				  EHEA_MAX_PACKET_SIZE);
5287a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
5297a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
5307a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic inline int ehea_check_cqe(struct ehea_cqe *cqe, int *rq_num)
5317a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
5327a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	*rq_num = (cqe->type & EHEA_CQE_TYPE_RQ) >> 5;
5337a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if ((cqe->status & EHEA_CQE_STAT_ERR_MASK) == 0)
5347a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		return 0;
5357a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (((cqe->status & EHEA_CQE_STAT_ERR_TCP) != 0) &&
5367a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	    (cqe->header_length == 0))
5377a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		return 0;
5387a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return -EINVAL;
5397a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
5407a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
5417a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic inline void ehea_fill_skb(struct net_device *dev,
542b95644685d530de5e9f9658bd8087e50840b831dAnton Blanchard				 struct sk_buff *skb, struct ehea_cqe *cqe,
543b95644685d530de5e9f9658bd8087e50840b831dAnton Blanchard				 struct ehea_port_res *pr)
5447a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
5457a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int length = cqe->num_bytes_transfered - 4;	/*remove CRC */
5467a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
5477a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	skb_put(skb, length);
5487a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	skb->protocol = eth_type_trans(skb, dev);
54971085ce8285dc5f3011694f6ba7259201135c6d6Breno Leitao
55071085ce8285dc5f3011694f6ba7259201135c6d6Breno Leitao	/* The packet was not an IPV4 packet so a complemented checksum was
55171085ce8285dc5f3011694f6ba7259201135c6d6Breno Leitao	   calculated. The value is found in the Internet Checksum field. */
55271085ce8285dc5f3011694f6ba7259201135c6d6Breno Leitao	if (cqe->status & EHEA_CQE_BLIND_CKSUM) {
55371085ce8285dc5f3011694f6ba7259201135c6d6Breno Leitao		skb->ip_summed = CHECKSUM_COMPLETE;
55471085ce8285dc5f3011694f6ba7259201135c6d6Breno Leitao		skb->csum = csum_unfold(~cqe->inet_checksum_value);
55571085ce8285dc5f3011694f6ba7259201135c6d6Breno Leitao	} else
55671085ce8285dc5f3011694f6ba7259201135c6d6Breno Leitao		skb->ip_summed = CHECKSUM_UNNECESSARY;
557b95644685d530de5e9f9658bd8087e50840b831dAnton Blanchard
558b95644685d530de5e9f9658bd8087e50840b831dAnton Blanchard	skb_record_rx_queue(skb, pr - &pr->port->port_res[0]);
5597a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
5607a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
5617a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic inline struct sk_buff *get_skb_by_index(struct sk_buff **skb_array,
5627a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann					       int arr_len,
5637a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann					       struct ehea_cqe *cqe)
5647a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
5657a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int skb_index = EHEA_BMASK_GET(EHEA_WR_ID_INDEX, cqe->wr_id);
5667a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct sk_buff *skb;
5677a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	void *pref;
5687a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int x;
5697a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
5707a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	x = skb_index + 1;
5717a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	x &= (arr_len - 1);
5727a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
5737a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	pref = skb_array[x];
5740b2febf38a33d7c40fb7bb4a58c113a1fa33c412Hannes Hering	if (pref) {
5750b2febf38a33d7c40fb7bb4a58c113a1fa33c412Hannes Hering		prefetchw(pref);
5760b2febf38a33d7c40fb7bb4a58c113a1fa33c412Hannes Hering		prefetchw(pref + EHEA_CACHE_LINE);
5770b2febf38a33d7c40fb7bb4a58c113a1fa33c412Hannes Hering
5780b2febf38a33d7c40fb7bb4a58c113a1fa33c412Hannes Hering		pref = (skb_array[x]->data);
5790b2febf38a33d7c40fb7bb4a58c113a1fa33c412Hannes Hering		prefetch(pref);
5800b2febf38a33d7c40fb7bb4a58c113a1fa33c412Hannes Hering		prefetch(pref + EHEA_CACHE_LINE);
5810b2febf38a33d7c40fb7bb4a58c113a1fa33c412Hannes Hering		prefetch(pref + EHEA_CACHE_LINE * 2);
5820b2febf38a33d7c40fb7bb4a58c113a1fa33c412Hannes Hering		prefetch(pref + EHEA_CACHE_LINE * 3);
5830b2febf38a33d7c40fb7bb4a58c113a1fa33c412Hannes Hering	}
5840b2febf38a33d7c40fb7bb4a58c113a1fa33c412Hannes Hering
5857a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	skb = skb_array[skb_index];
5867a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	skb_array[skb_index] = NULL;
5877a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return skb;
5887a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
5897a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
5907a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic inline struct sk_buff *get_skb_by_index_ll(struct sk_buff **skb_array,
5917a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann						  int arr_len, int wqe_index)
5927a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
5937a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct sk_buff *skb;
5947a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	void *pref;
5957a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int x;
5967a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
5977a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	x = wqe_index + 1;
5987a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	x &= (arr_len - 1);
5997a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
6007a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	pref = skb_array[x];
6010b2febf38a33d7c40fb7bb4a58c113a1fa33c412Hannes Hering	if (pref) {
6020b2febf38a33d7c40fb7bb4a58c113a1fa33c412Hannes Hering		prefetchw(pref);
6030b2febf38a33d7c40fb7bb4a58c113a1fa33c412Hannes Hering		prefetchw(pref + EHEA_CACHE_LINE);
6047a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
6050b2febf38a33d7c40fb7bb4a58c113a1fa33c412Hannes Hering		pref = (skb_array[x]->data);
6060b2febf38a33d7c40fb7bb4a58c113a1fa33c412Hannes Hering		prefetchw(pref);
6070b2febf38a33d7c40fb7bb4a58c113a1fa33c412Hannes Hering		prefetchw(pref + EHEA_CACHE_LINE);
6080b2febf38a33d7c40fb7bb4a58c113a1fa33c412Hannes Hering	}
6097a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
6107a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	skb = skb_array[wqe_index];
6117a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	skb_array[wqe_index] = NULL;
6127a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return skb;
6137a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
6147a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
6157a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic int ehea_treat_poll_error(struct ehea_port_res *pr, int rq,
6167a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				 struct ehea_cqe *cqe, int *processed_rq2,
6177a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				 int *processed_rq3)
6187a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
6197a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct sk_buff *skb;
6207a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
621acbddb591ba76bb20204fd6a407cb87d3f5f751eJan-Bernd Themann	if (cqe->status & EHEA_CQE_STAT_ERR_TCP)
622acbddb591ba76bb20204fd6a407cb87d3f5f751eJan-Bernd Themann		pr->p_stats.err_tcp_cksum++;
623acbddb591ba76bb20204fd6a407cb87d3f5f751eJan-Bernd Themann	if (cqe->status & EHEA_CQE_STAT_ERR_IP)
624acbddb591ba76bb20204fd6a407cb87d3f5f751eJan-Bernd Themann		pr->p_stats.err_ip_cksum++;
625acbddb591ba76bb20204fd6a407cb87d3f5f751eJan-Bernd Themann	if (cqe->status & EHEA_CQE_STAT_ERR_CRC)
626acbddb591ba76bb20204fd6a407cb87d3f5f751eJan-Bernd Themann		pr->p_stats.err_frame_crc++;
627acbddb591ba76bb20204fd6a407cb87d3f5f751eJan-Bernd Themann
6287a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (rq == 2) {
6297a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		*processed_rq2 += 1;
6307a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		skb = get_skb_by_index(pr->rq2_skba.arr, pr->rq2_skba.len, cqe);
6317a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		dev_kfree_skb(skb);
6327a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	} else if (rq == 3) {
6337a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		*processed_rq3 += 1;
6347a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		skb = get_skb_by_index(pr->rq3_skba.arr, pr->rq3_skba.len, cqe);
6357a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		dev_kfree_skb(skb);
6367a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
6377a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
6387a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (cqe->status & EHEA_CQE_STAT_FAT_ERR_MASK) {
63958dd8258fccbb68e0d0e1898038442822cb833c0Thomas Klein		if (netif_msg_rx_err(pr->port)) {
6408c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			pr_err("Critical receive error for QP %d. Resetting port.\n",
6418c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			       pr->qp->init_attr.qp_nr);
64258dd8258fccbb68e0d0e1898038442822cb833c0Thomas Klein			ehea_dump(cqe, sizeof(*cqe), "CQE");
64358dd8258fccbb68e0d0e1898038442822cb833c0Thomas Klein		}
6442f69ae01c83a94af5dc3c20e8135b974687ed004Jan-Bernd Themann		ehea_schedule_port_reset(pr->port);
6457a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		return 1;
6467a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
6477a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
6487a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return 0;
6497a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
6507a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
651bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemmingerstatic int ehea_proc_rwqes(struct net_device *dev,
652bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger			   struct ehea_port_res *pr,
653bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger			   int budget)
6547a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
65518604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann	struct ehea_port *port = pr->port;
6567a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_qp *qp = pr->qp;
6577a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_cqe *cqe;
6587a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct sk_buff *skb;
6597a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct sk_buff **skb_arr_rq1 = pr->rq1_skba.arr;
6607a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct sk_buff **skb_arr_rq2 = pr->rq2_skba.arr;
6617a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct sk_buff **skb_arr_rq3 = pr->rq3_skba.arr;
6627a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int skb_arr_rq1_len = pr->rq1_skba.len;
6637a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int skb_arr_rq2_len = pr->rq2_skba.len;
6647a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int skb_arr_rq3_len = pr->rq3_skba.len;
6657a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int processed, processed_rq1, processed_rq2, processed_rq3;
666ce45b873028fdf94a24f0850cd554e6fda593e16Breno Leitao	u64 processed_bytes = 0;
667bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger	int wqe_index, last_wqe_index, rq, port_reset;
6687a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
6697a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	processed = processed_rq1 = processed_rq2 = processed_rq3 = 0;
6707a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	last_wqe_index = 0;
6717a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
6727a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	cqe = ehea_poll_rq1(qp, &wqe_index);
673bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger	while ((processed < budget) && cqe) {
6747a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ehea_inc_rq1(qp);
6757a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		processed_rq1++;
6767a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		processed++;
6777a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		if (netif_msg_rx_status(port))
6787a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			ehea_dump(cqe, sizeof(*cqe), "CQE");
6797a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
6807a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		last_wqe_index = wqe_index;
6817a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		rmb();
6827a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		if (!ehea_check_cqe(cqe, &rq)) {
683508d2b5d261abbd7fb728092c5025c5063060c04Doug Maxey			if (rq == 1) {
684508d2b5d261abbd7fb728092c5025c5063060c04Doug Maxey				/* LL RQ1 */
6857a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				skb = get_skb_by_index_ll(skb_arr_rq1,
6867a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann							  skb_arr_rq1_len,
6877a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann							  wqe_index);
6887a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				if (unlikely(!skb)) {
689782615aea84e57dc7f2f922cea823df3de635a78Breno Leitao					netif_info(port, rx_err, dev,
6908c4877a4128e7931077b024a891a4b284d8756a3Joe Perches						  "LL rq1: skb=NULL\n");
69118604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann
692bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger					skb = netdev_alloc_skb(dev,
6937a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann							       EHEA_L_PKT_SIZE);
6945c7e57f7cddb83d81d83fefa5822dfe80891130eBreno Leitao					if (!skb) {
695782615aea84e57dc7f2f922cea823df3de635a78Breno Leitao						netdev_err(dev, "Not enough memory to allocate skb\n");
6967a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann						break;
6975c7e57f7cddb83d81d83fefa5822dfe80891130eBreno Leitao					}
6987a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				}
699508d2b5d261abbd7fb728092c5025c5063060c04Doug Maxey				skb_copy_to_linear_data(skb, ((char *)cqe) + 64,
700d1d25aaba85fd24ab18b0a4d22f19be02aac65c9Jan-Bernd Themann						 cqe->num_bytes_transfered - 4);
701b95644685d530de5e9f9658bd8087e50840b831dAnton Blanchard				ehea_fill_skb(dev, skb, cqe, pr);
702508d2b5d261abbd7fb728092c5025c5063060c04Doug Maxey			} else if (rq == 2) {
703508d2b5d261abbd7fb728092c5025c5063060c04Doug Maxey				/* RQ2 */
7047a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				skb = get_skb_by_index(skb_arr_rq2,
7057a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann						       skb_arr_rq2_len, cqe);
7067a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				if (unlikely(!skb)) {
7078c4877a4128e7931077b024a891a4b284d8756a3Joe Perches					netif_err(port, rx_err, dev,
7088c4877a4128e7931077b024a891a4b284d8756a3Joe Perches						  "rq2: skb=NULL\n");
7097a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann					break;
7107a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				}
711b95644685d530de5e9f9658bd8087e50840b831dAnton Blanchard				ehea_fill_skb(dev, skb, cqe, pr);
7127a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				processed_rq2++;
713508d2b5d261abbd7fb728092c5025c5063060c04Doug Maxey			} else {
714508d2b5d261abbd7fb728092c5025c5063060c04Doug Maxey				/* RQ3 */
7157a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				skb = get_skb_by_index(skb_arr_rq3,
7167a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann						       skb_arr_rq3_len, cqe);
7177a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				if (unlikely(!skb)) {
7188c4877a4128e7931077b024a891a4b284d8756a3Joe Perches					netif_err(port, rx_err, dev,
7198c4877a4128e7931077b024a891a4b284d8756a3Joe Perches						  "rq3: skb=NULL\n");
7207a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann					break;
7217a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				}
722b95644685d530de5e9f9658bd8087e50840b831dAnton Blanchard				ehea_fill_skb(dev, skb, cqe, pr);
7237a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				processed_rq3++;
7247a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			}
7257a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
726ce45b873028fdf94a24f0850cd554e6fda593e16Breno Leitao			processed_bytes += skb->len;
7273428414f71e12f8111dfa16e4d958e6ed055268aAnton Blanchard
7283428414f71e12f8111dfa16e4d958e6ed055268aAnton Blanchard			if (cqe->status & EHEA_CQE_VLAN_TAG_XTRACT)
7293428414f71e12f8111dfa16e4d958e6ed055268aAnton Blanchard				__vlan_hwaccel_put_tag(skb, cqe->vlan_tag);
7303428414f71e12f8111dfa16e4d958e6ed055268aAnton Blanchard
7313428414f71e12f8111dfa16e4d958e6ed055268aAnton Blanchard			napi_gro_receive(&pr->napi, skb);
73218604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann		} else {
733acbddb591ba76bb20204fd6a407cb87d3f5f751eJan-Bernd Themann			pr->p_stats.poll_receive_errors++;
7347a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			port_reset = ehea_treat_poll_error(pr, rq, cqe,
7357a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann							   &processed_rq2,
7367a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann							   &processed_rq3);
7377a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			if (port_reset)
7387a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				break;
7397a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		}
7407a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		cqe = ehea_poll_rq1(qp, &wqe_index);
7417a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
7427a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
7437a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	pr->rx_packets += processed;
744ce45b873028fdf94a24f0850cd554e6fda593e16Breno Leitao	pr->rx_bytes += processed_bytes;
7457a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
7467a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ehea_refill_rq1(pr, last_wqe_index, processed_rq1);
7477a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ehea_refill_rq2(pr, processed_rq2);
7487a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ehea_refill_rq3(pr, processed_rq3);
7497a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
750bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger	return processed;
7517a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
7527a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
7532928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch#define SWQE_RESTART_CHECK 0xdeadbeaff00d0000ull
7542928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch
7552928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detschstatic void reset_sq_restart_flag(struct ehea_port *port)
7562928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch{
7572928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch	int i;
7582928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch
759723f28e49c9f8578b418dfd1ec8c7b9cc13e2b63Anton Blanchard	for (i = 0; i < port->num_def_qps; i++) {
7602928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch		struct ehea_port_res *pr = &port->port_res[i];
7612928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch		pr->sq_restart_flag = 0;
7622928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch	}
763a8bb69f78194dc483f6c4a4bf8860c1ede35fa25Breno Leitao	wake_up(&port->restart_wq);
7642928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch}
7652928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch
7662928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detschstatic void check_sqs(struct ehea_port *port)
7672928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch{
7682928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch	struct ehea_swqe *swqe;
7692928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch	int swqe_index;
7702928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch	int i, k;
7712928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch
772723f28e49c9f8578b418dfd1ec8c7b9cc13e2b63Anton Blanchard	for (i = 0; i < port->num_def_qps; i++) {
7732928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch		struct ehea_port_res *pr = &port->port_res[i];
774a8bb69f78194dc483f6c4a4bf8860c1ede35fa25Breno Leitao		int ret;
7752928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch		k = 0;
7762928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch		swqe = ehea_get_swqe(pr->qp, &swqe_index);
7772928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch		memset(swqe, 0, SWQE_HEADER_SIZE);
7782928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch		atomic_dec(&pr->swqe_avail);
7792928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch
7802928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch		swqe->tx_control |= EHEA_SWQE_PURGE;
7812928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch		swqe->wr_id = SWQE_RESTART_CHECK;
7822928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch		swqe->tx_control |= EHEA_SWQE_SIGNALLED_COMPLETION;
7832928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch		swqe->tx_control |= EHEA_SWQE_IMM_DATA_PRESENT;
7842928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch		swqe->immediate_data_length = 80;
7852928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch
7862928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch		ehea_post_swqe(pr->qp, swqe);
7872928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch
788a8bb69f78194dc483f6c4a4bf8860c1ede35fa25Breno Leitao		ret = wait_event_timeout(port->restart_wq,
789a8bb69f78194dc483f6c4a4bf8860c1ede35fa25Breno Leitao					 pr->sq_restart_flag == 0,
790a8bb69f78194dc483f6c4a4bf8860c1ede35fa25Breno Leitao					 msecs_to_jiffies(100));
791a8bb69f78194dc483f6c4a4bf8860c1ede35fa25Breno Leitao
792a8bb69f78194dc483f6c4a4bf8860c1ede35fa25Breno Leitao		if (!ret) {
7938c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			pr_err("HW/SW queues out of sync\n");
794a8bb69f78194dc483f6c4a4bf8860c1ede35fa25Breno Leitao			ehea_schedule_port_reset(pr->port);
795a8bb69f78194dc483f6c4a4bf8860c1ede35fa25Breno Leitao			return;
7962928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch		}
7972928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch	}
7982928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch}
7992928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch
8002928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch
80118604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themannstatic struct ehea_cqe *ehea_proc_cqes(struct ehea_port_res *pr, int my_quota)
8027a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
803acbddb591ba76bb20204fd6a407cb87d3f5f751eJan-Bernd Themann	struct sk_buff *skb;
8047a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_cq *send_cq = pr->send_cq;
8057a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_cqe *cqe;
80618604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann	int quota = my_quota;
8077a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int cqe_counter = 0;
8087a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int swqe_av = 0;
809acbddb591ba76bb20204fd6a407cb87d3f5f751eJan-Bernd Themann	int index;
810b95644685d530de5e9f9658bd8087e50840b831dAnton Blanchard	struct netdev_queue *txq = netdev_get_tx_queue(pr->port->netdev,
811b95644685d530de5e9f9658bd8087e50840b831dAnton Blanchard						pr - &pr->port->port_res[0]);
8127a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
81318604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann	cqe = ehea_poll_cq(send_cq);
814508d2b5d261abbd7fb728092c5025c5063060c04Doug Maxey	while (cqe && (quota > 0)) {
81518604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann		ehea_inc_cq(send_cq);
81618604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann
8177a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		cqe_counter++;
8187a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		rmb();
8192928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch
8202928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch		if (cqe->wr_id == SWQE_RESTART_CHECK) {
8212928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch			pr->sq_restart_flag = 1;
8222928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch			swqe_av++;
8232928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch			break;
8242928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch		}
8252928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch
8267a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		if (cqe->status & EHEA_CQE_STAT_ERR_MASK) {
8278c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			pr_err("Bad send completion status=0x%04X\n",
8288c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			       cqe->status);
829ea96ceac80cc82cb1c54a37bb8aaf4e695e87d0aThomas Klein
8307a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			if (netif_msg_tx_err(pr->port))
8317a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				ehea_dump(cqe, sizeof(*cqe), "Send CQE");
832ea96ceac80cc82cb1c54a37bb8aaf4e695e87d0aThomas Klein
833ea96ceac80cc82cb1c54a37bb8aaf4e695e87d0aThomas Klein			if (cqe->status & EHEA_CQE_STAT_RESET_MASK) {
8348c4877a4128e7931077b024a891a4b284d8756a3Joe Perches				pr_err("Resetting port\n");
835ea96ceac80cc82cb1c54a37bb8aaf4e695e87d0aThomas Klein				ehea_schedule_port_reset(pr->port);
836ea96ceac80cc82cb1c54a37bb8aaf4e695e87d0aThomas Klein				break;
837ea96ceac80cc82cb1c54a37bb8aaf4e695e87d0aThomas Klein			}
8387a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		}
8397a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
8407a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		if (netif_msg_tx_done(pr->port))
8417a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			ehea_dump(cqe, sizeof(*cqe), "CQE");
8427a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
8437a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		if (likely(EHEA_BMASK_GET(EHEA_WR_ID_TYPE, cqe->wr_id)
844acbddb591ba76bb20204fd6a407cb87d3f5f751eJan-Bernd Themann			   == EHEA_SWQE2_TYPE)) {
845acbddb591ba76bb20204fd6a407cb87d3f5f751eJan-Bernd Themann
846acbddb591ba76bb20204fd6a407cb87d3f5f751eJan-Bernd Themann			index = EHEA_BMASK_GET(EHEA_WR_ID_INDEX, cqe->wr_id);
847acbddb591ba76bb20204fd6a407cb87d3f5f751eJan-Bernd Themann			skb = pr->sq_skba.arr[index];
848acbddb591ba76bb20204fd6a407cb87d3f5f751eJan-Bernd Themann			dev_kfree_skb(skb);
849acbddb591ba76bb20204fd6a407cb87d3f5f751eJan-Bernd Themann			pr->sq_skba.arr[index] = NULL;
850acbddb591ba76bb20204fd6a407cb87d3f5f751eJan-Bernd Themann		}
8517a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
8527a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		swqe_av += EHEA_BMASK_GET(EHEA_WR_ID_REFILL, cqe->wr_id);
8537a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		quota--;
85418604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann
85518604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann		cqe = ehea_poll_cq(send_cq);
856ee289b6440c3b0ccb9459495783e8c299bec6604Joe Perches	}
8577a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
8587a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ehea_update_feca(send_cq, cqe_counter);
8597a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	atomic_add(swqe_av, &pr->swqe_avail);
8607a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
861b95644685d530de5e9f9658bd8087e50840b831dAnton Blanchard	if (unlikely(netif_tx_queue_stopped(txq) &&
862b95644685d530de5e9f9658bd8087e50840b831dAnton Blanchard		     (atomic_read(&pr->swqe_avail) >= pr->swqe_refill_th))) {
863b95644685d530de5e9f9658bd8087e50840b831dAnton Blanchard		__netif_tx_lock(txq, smp_processor_id());
864b95644685d530de5e9f9658bd8087e50840b831dAnton Blanchard		if (netif_tx_queue_stopped(txq) &&
865b95644685d530de5e9f9658bd8087e50840b831dAnton Blanchard		    (atomic_read(&pr->swqe_avail) >= pr->swqe_refill_th))
866b95644685d530de5e9f9658bd8087e50840b831dAnton Blanchard			netif_tx_wake_queue(txq);
867b95644685d530de5e9f9658bd8087e50840b831dAnton Blanchard		__netif_tx_unlock(txq);
8687a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
869b95644685d530de5e9f9658bd8087e50840b831dAnton Blanchard
8705b27d42755fa6536a89f32b107fb2a53267696c2Breno Leitao	wake_up(&pr->port->swqe_avail_wq);
8717a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
87218604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann	return cqe;
8737a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
8747a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
875bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger#define EHEA_POLL_MAX_CQES 65535
87618604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann
877bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemmingerstatic int ehea_poll(struct napi_struct *napi, int budget)
8787a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
879508d2b5d261abbd7fb728092c5025c5063060c04Doug Maxey	struct ehea_port_res *pr = container_of(napi, struct ehea_port_res,
880508d2b5d261abbd7fb728092c5025c5063060c04Doug Maxey						napi);
881bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger	struct net_device *dev = pr->port->netdev;
88218604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann	struct ehea_cqe *cqe;
88318604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann	struct ehea_cqe *cqe_skb = NULL;
884222ca96b69ae8afb2ad13b99070b09309e7d9657Anton Blanchard	int wqe_index;
885bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger	int rx = 0;
88618604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann
887bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger	cqe_skb = ehea_proc_cqes(pr, EHEA_POLL_MAX_CQES);
888222ca96b69ae8afb2ad13b99070b09309e7d9657Anton Blanchard	rx += ehea_proc_rwqes(dev, pr, budget - rx);
889bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger
890222ca96b69ae8afb2ad13b99070b09309e7d9657Anton Blanchard	while (rx != budget) {
891288379f050284087578b77e04f040b57db3db3f8Ben Hutchings		napi_complete(napi);
89218604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann		ehea_reset_cq_ep(pr->recv_cq);
89318604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann		ehea_reset_cq_ep(pr->send_cq);
89418604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann		ehea_reset_cq_n1(pr->recv_cq);
89518604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann		ehea_reset_cq_n1(pr->send_cq);
896a91fb143de61dce847e319ca79b9937a665ad622Jan-Bernd Themann		rmb();
89718604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann		cqe = ehea_poll_rq1(pr->qp, &wqe_index);
89818604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann		cqe_skb = ehea_poll_cq(pr->send_cq);
89918604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann
900e542aa6bd50ba163253e60ba8e7e51c0d56162a7Jan-Bernd Themann		if (!cqe && !cqe_skb)
901bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger			return rx;
90218604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann
903288379f050284087578b77e04f040b57db3db3f8Ben Hutchings		if (!napi_reschedule(napi))
904bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger			return rx;
90518604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann
906bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger		cqe_skb = ehea_proc_cqes(pr, EHEA_POLL_MAX_CQES);
907bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger		rx += ehea_proc_rwqes(dev, pr, budget - rx);
908bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger	}
909e542aa6bd50ba163253e60ba8e7e51c0d56162a7Jan-Bernd Themann
910bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger	return rx;
9117a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
9127a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
9138d22c9711aa5e704fc5f89027f5cf64838767c98Jan-Bernd Themann#ifdef CONFIG_NET_POLL_CONTROLLER
9148d22c9711aa5e704fc5f89027f5cf64838767c98Jan-Bernd Themannstatic void ehea_netpoll(struct net_device *dev)
9158d22c9711aa5e704fc5f89027f5cf64838767c98Jan-Bernd Themann{
9168d22c9711aa5e704fc5f89027f5cf64838767c98Jan-Bernd Themann	struct ehea_port *port = netdev_priv(dev);
917bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger	int i;
9188d22c9711aa5e704fc5f89027f5cf64838767c98Jan-Bernd Themann
919bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger	for (i = 0; i < port->num_def_qps; i++)
920288379f050284087578b77e04f040b57db3db3f8Ben Hutchings		napi_schedule(&port->port_res[i].napi);
9218d22c9711aa5e704fc5f89027f5cf64838767c98Jan-Bernd Themann}
9228d22c9711aa5e704fc5f89027f5cf64838767c98Jan-Bernd Themann#endif
9238d22c9711aa5e704fc5f89027f5cf64838767c98Jan-Bernd Themann
9247d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t ehea_recv_irq_handler(int irq, void *param)
9257a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
9267a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_port_res *pr = param;
92718604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann
928288379f050284087578b77e04f040b57db3db3f8Ben Hutchings	napi_schedule(&pr->napi);
92918604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann
9307a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return IRQ_HANDLED;
9317a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
9327a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
9337d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t ehea_qp_aff_irq_handler(int irq, void *param)
9347a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
9357a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_port *port = param;
9367a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_eqe *eqe;
937d2db9eea7901d83e494340c93d131fc1fd463e4cJan-Bernd Themann	struct ehea_qp *qp;
9387a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	u32 qp_token;
939ea96ceac80cc82cb1c54a37bb8aaf4e695e87d0aThomas Klein	u64 resource_type, aer, aerr;
940ea96ceac80cc82cb1c54a37bb8aaf4e695e87d0aThomas Klein	int reset_port = 0;
9417a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
9427a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	eqe = ehea_poll_eq(port->qp_eq);
943bb3a6449c18f6203e59195a98d633f5b5b57c133Thomas Klein
9447a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	while (eqe) {
9457a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		qp_token = EHEA_BMASK_GET(EHEA_EQE_QP_TOKEN, eqe->entry);
9468c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("QP aff_err: entry=0x%llx, token=0x%x\n",
9478c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		       eqe->entry, qp_token);
948d2db9eea7901d83e494340c93d131fc1fd463e4cJan-Bernd Themann
949d2db9eea7901d83e494340c93d131fc1fd463e4cJan-Bernd Themann		qp = port->port_res[qp_token].qp;
950ea96ceac80cc82cb1c54a37bb8aaf4e695e87d0aThomas Klein
951ea96ceac80cc82cb1c54a37bb8aaf4e695e87d0aThomas Klein		resource_type = ehea_error_data(port->adapter, qp->fw_handle,
952ea96ceac80cc82cb1c54a37bb8aaf4e695e87d0aThomas Klein						&aer, &aerr);
953ea96ceac80cc82cb1c54a37bb8aaf4e695e87d0aThomas Klein
954ea96ceac80cc82cb1c54a37bb8aaf4e695e87d0aThomas Klein		if (resource_type == EHEA_AER_RESTYPE_QP) {
955ea96ceac80cc82cb1c54a37bb8aaf4e695e87d0aThomas Klein			if ((aer & EHEA_AER_RESET_MASK) ||
956ea96ceac80cc82cb1c54a37bb8aaf4e695e87d0aThomas Klein			    (aerr & EHEA_AERR_RESET_MASK))
957ea96ceac80cc82cb1c54a37bb8aaf4e695e87d0aThomas Klein				 reset_port = 1;
958ea96ceac80cc82cb1c54a37bb8aaf4e695e87d0aThomas Klein		} else
959ea96ceac80cc82cb1c54a37bb8aaf4e695e87d0aThomas Klein			reset_port = 1;   /* Reset in case of CQ or EQ error */
960ea96ceac80cc82cb1c54a37bb8aaf4e695e87d0aThomas Klein
961bb3a6449c18f6203e59195a98d633f5b5b57c133Thomas Klein		eqe = ehea_poll_eq(port->qp_eq);
9627a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
9637a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
964ea96ceac80cc82cb1c54a37bb8aaf4e695e87d0aThomas Klein	if (reset_port) {
9658c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("Resetting port\n");
966ea96ceac80cc82cb1c54a37bb8aaf4e695e87d0aThomas Klein		ehea_schedule_port_reset(port);
967ea96ceac80cc82cb1c54a37bb8aaf4e695e87d0aThomas Klein	}
968d2db9eea7901d83e494340c93d131fc1fd463e4cJan-Bernd Themann
9697a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return IRQ_HANDLED;
9707a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
9717a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
9727a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic struct ehea_port *ehea_get_port(struct ehea_adapter *adapter,
9737a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				       int logical_port)
9747a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
9757a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int i;
9767a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
9771acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	for (i = 0; i < EHEA_MAX_PORTS; i++)
97841b69c705152e93b3c6c872678dffd8a19b14d61Thomas Klein		if (adapter->port[i])
979d1d25aaba85fd24ab18b0a4d22f19be02aac65c9Jan-Bernd Themann			if (adapter->port[i]->logical_port_id == logical_port)
98041b69c705152e93b3c6c872678dffd8a19b14d61Thomas Klein				return adapter->port[i];
9817a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return NULL;
9827a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
9837a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
9847a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannint ehea_sense_port_attr(struct ehea_port *port)
9857a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
9867a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int ret;
9877a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	u64 hret;
9887a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct hcp_ehea_port_cb0 *cb0;
9897a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
990508d2b5d261abbd7fb728092c5025c5063060c04Doug Maxey	/* may be called via ehea_neq_tasklet() */
9913faf2693bd6800c2521799f6a9ae174d9f080ed2Thomas Klein	cb0 = (void *)get_zeroed_page(GFP_ATOMIC);
992508d2b5d261abbd7fb728092c5025c5063060c04Doug Maxey	if (!cb0) {
9938c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("no mem for cb0\n");
9947a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ret = -ENOMEM;
9957a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out;
9967a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
9977a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
9987a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	hret = ehea_h_query_ehea_port(port->adapter->handle,
9997a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				      port->logical_port_id, H_PORT_CB0,
10007a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				      EHEA_BMASK_SET(H_PORT_CB0_ALL, 0xFFFF),
10017a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				      cb0);
10027a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (hret != H_SUCCESS) {
10037a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ret = -EIO;
10047a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out_free;
10057a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
10067a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
10077a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	/* MAC address */
10087a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	port->mac_addr = cb0->port_mac_addr << 16;
10097a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
1010508d2b5d261abbd7fb728092c5025c5063060c04Doug Maxey	if (!is_valid_ether_addr((u8 *)&port->mac_addr)) {
10117a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ret = -EADDRNOTAVAIL;
10127a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out_free;
10137a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
10147a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
10157a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	/* Port speed */
10167a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	switch (cb0->port_speed) {
10177a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	case H_SPEED_10M_H:
10187a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		port->port_speed = EHEA_SPEED_10M;
10197a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		port->full_duplex = 0;
10207a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		break;
10217a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	case H_SPEED_10M_F:
10227a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		port->port_speed = EHEA_SPEED_10M;
10237a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		port->full_duplex = 1;
10247a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		break;
10257a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	case H_SPEED_100M_H:
10267a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		port->port_speed = EHEA_SPEED_100M;
10277a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		port->full_duplex = 0;
10287a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		break;
10297a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	case H_SPEED_100M_F:
10307a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		port->port_speed = EHEA_SPEED_100M;
10317a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		port->full_duplex = 1;
10327a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		break;
10337a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	case H_SPEED_1G_F:
10347a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		port->port_speed = EHEA_SPEED_1G;
10357a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		port->full_duplex = 1;
10367a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		break;
10377a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	case H_SPEED_10G_F:
10387a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		port->port_speed = EHEA_SPEED_10G;
10397a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		port->full_duplex = 1;
10407a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		break;
10417a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	default:
10427a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		port->port_speed = 0;
10437a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		port->full_duplex = 0;
10447a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		break;
10457a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
10467a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
1047e919b5938b11e1d48a6dcdcb2860e890a954f10dThomas Klein	port->autoneg = 1;
104818604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann	port->num_mcs = cb0->num_default_qps;
1049e919b5938b11e1d48a6dcdcb2860e890a954f10dThomas Klein
10507a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	/* Number of default QPs */
105118604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann	if (use_mcs)
105218604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann		port->num_def_qps = cb0->num_default_qps;
105318604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann	else
105418604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann		port->num_def_qps = 1;
10557a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
10567a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (!port->num_def_qps) {
10577a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ret = -EINVAL;
10587a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out_free;
10597a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
10607a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
10617a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ret = 0;
10627a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannout_free:
10637a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (ret || netif_msg_probe(port))
10647a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ehea_dump(cb0, sizeof(*cb0), "ehea_sense_port_attr");
10653faf2693bd6800c2521799f6a9ae174d9f080ed2Thomas Klein	free_page((unsigned long)cb0);
10667a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannout:
10677a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return ret;
10687a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
10697a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
10707a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannint ehea_set_portspeed(struct ehea_port *port, u32 port_speed)
10717a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
10727a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct hcp_ehea_port_cb4 *cb4;
10737a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	u64 hret;
10747a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int ret = 0;
10757a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
10763faf2693bd6800c2521799f6a9ae174d9f080ed2Thomas Klein	cb4 = (void *)get_zeroed_page(GFP_KERNEL);
10777a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (!cb4) {
10788c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("no mem for cb4\n");
10797a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ret = -ENOMEM;
10807a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out;
10817a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
10827a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
10837a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	cb4->port_speed = port_speed;
10847a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
10857a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	netif_carrier_off(port->netdev);
10867a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
10877a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	hret = ehea_h_modify_ehea_port(port->adapter->handle,
10887a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				       port->logical_port_id,
10897a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				       H_PORT_CB4, H_PORT_CB4_SPEED, cb4);
10907a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (hret == H_SUCCESS) {
10917a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		port->autoneg = port_speed == EHEA_SPEED_AUTONEG ? 1 : 0;
10927a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
10937a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		hret = ehea_h_query_ehea_port(port->adapter->handle,
10947a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann					      port->logical_port_id,
10957a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann					      H_PORT_CB4, H_PORT_CB4_SPEED,
10967a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann					      cb4);
10977a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		if (hret == H_SUCCESS) {
10987a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			switch (cb4->port_speed) {
10997a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			case H_SPEED_10M_H:
11007a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				port->port_speed = EHEA_SPEED_10M;
11017a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				port->full_duplex = 0;
11027a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				break;
11037a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			case H_SPEED_10M_F:
11047a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				port->port_speed = EHEA_SPEED_10M;
11057a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				port->full_duplex = 1;
11067a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				break;
11077a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			case H_SPEED_100M_H:
11087a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				port->port_speed = EHEA_SPEED_100M;
11097a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				port->full_duplex = 0;
11107a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				break;
11117a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			case H_SPEED_100M_F:
11127a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				port->port_speed = EHEA_SPEED_100M;
11137a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				port->full_duplex = 1;
11147a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				break;
11157a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			case H_SPEED_1G_F:
11167a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				port->port_speed = EHEA_SPEED_1G;
11177a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				port->full_duplex = 1;
11187a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				break;
11197a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			case H_SPEED_10G_F:
11207a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				port->port_speed = EHEA_SPEED_10G;
11217a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				port->full_duplex = 1;
11227a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				break;
11237a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			default:
11247a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				port->port_speed = 0;
11257a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				port->full_duplex = 0;
11267a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				break;
11277a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			}
11287a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		} else {
11298c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			pr_err("Failed sensing port speed\n");
11307a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			ret = -EIO;
11317a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		}
11327a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	} else {
11337a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		if (hret == H_AUTHORITY) {
11348c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			pr_info("Hypervisor denied setting port speed\n");
11357a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			ret = -EPERM;
11367a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		} else {
11377a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			ret = -EIO;
11388c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			pr_err("Failed setting port speed\n");
11397a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		}
11407a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
11418759cf76e9a6322fc68dcbfaa1cbad00c74b199eJan-Bernd Themann	if (!prop_carrier_state || (port->phy_link == EHEA_PHY_LINK_UP))
11428759cf76e9a6322fc68dcbfaa1cbad00c74b199eJan-Bernd Themann		netif_carrier_on(port->netdev);
11438759cf76e9a6322fc68dcbfaa1cbad00c74b199eJan-Bernd Themann
11443faf2693bd6800c2521799f6a9ae174d9f080ed2Thomas Klein	free_page((unsigned long)cb4);
11457a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannout:
11467a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return ret;
11477a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
11487a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
11497a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic void ehea_parse_eqe(struct ehea_adapter *adapter, u64 eqe)
11507a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
11517a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int ret;
11527a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	u8 ec;
11537a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	u8 portnum;
11547a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_port *port;
11558c4877a4128e7931077b024a891a4b284d8756a3Joe Perches	struct net_device *dev;
11567a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
11577a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ec = EHEA_BMASK_GET(NEQE_EVENT_CODE, eqe);
11587a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	portnum = EHEA_BMASK_GET(NEQE_PORTNUM, eqe);
11597a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	port = ehea_get_port(adapter, portnum);
11608c4877a4128e7931077b024a891a4b284d8756a3Joe Perches	dev = port->netdev;
11617a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
11627a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	switch (ec) {
11637a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	case EHEA_EC_PORTSTATE_CHG:	/* port state change */
11647a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
11657a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		if (!port) {
11668c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			netdev_err(dev, "unknown portnum %x\n", portnum);
11677a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			break;
11687a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		}
11697a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
11707a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		if (EHEA_BMASK_GET(NEQE_PORT_UP, eqe)) {
11718c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			if (!netif_carrier_ok(dev)) {
11721e1675ccf758cbb4303ab052d58405cda6c745a7Jan-Bernd Themann				ret = ehea_sense_port_attr(port);
11737a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				if (ret) {
11748c4877a4128e7931077b024a891a4b284d8756a3Joe Perches					netdev_err(dev, "failed resensing port attributes\n");
11757a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann					break;
11767a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				}
11777a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
11788c4877a4128e7931077b024a891a4b284d8756a3Joe Perches				netif_info(port, link, dev,
11798c4877a4128e7931077b024a891a4b284d8756a3Joe Perches					   "Logical port up: %dMbps %s Duplex\n",
11808c4877a4128e7931077b024a891a4b284d8756a3Joe Perches					   port->port_speed,
11818c4877a4128e7931077b024a891a4b284d8756a3Joe Perches					   port->full_duplex == 1 ?
11828c4877a4128e7931077b024a891a4b284d8756a3Joe Perches					   "Full" : "Half");
11837a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
11848c4877a4128e7931077b024a891a4b284d8756a3Joe Perches				netif_carrier_on(dev);
11858c4877a4128e7931077b024a891a4b284d8756a3Joe Perches				netif_wake_queue(dev);
11867a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			}
11877a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		} else
11888c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			if (netif_carrier_ok(dev)) {
11898c4877a4128e7931077b024a891a4b284d8756a3Joe Perches				netif_info(port, link, dev,
11908c4877a4128e7931077b024a891a4b284d8756a3Joe Perches					   "Logical port down\n");
11918c4877a4128e7931077b024a891a4b284d8756a3Joe Perches				netif_carrier_off(dev);
1192b95644685d530de5e9f9658bd8087e50840b831dAnton Blanchard				netif_tx_disable(dev);
11937a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			}
11947a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
11957a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		if (EHEA_BMASK_GET(NEQE_EXTSWITCH_PORT_UP, eqe)) {
11968759cf76e9a6322fc68dcbfaa1cbad00c74b199eJan-Bernd Themann			port->phy_link = EHEA_PHY_LINK_UP;
11978c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			netif_info(port, link, dev,
11988c4877a4128e7931077b024a891a4b284d8756a3Joe Perches				   "Physical port up\n");
11998759cf76e9a6322fc68dcbfaa1cbad00c74b199eJan-Bernd Themann			if (prop_carrier_state)
12008c4877a4128e7931077b024a891a4b284d8756a3Joe Perches				netif_carrier_on(dev);
12017a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		} else {
12028759cf76e9a6322fc68dcbfaa1cbad00c74b199eJan-Bernd Themann			port->phy_link = EHEA_PHY_LINK_DOWN;
12038c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			netif_info(port, link, dev,
12048c4877a4128e7931077b024a891a4b284d8756a3Joe Perches				   "Physical port down\n");
12058759cf76e9a6322fc68dcbfaa1cbad00c74b199eJan-Bernd Themann			if (prop_carrier_state)
12068c4877a4128e7931077b024a891a4b284d8756a3Joe Perches				netif_carrier_off(dev);
12077a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		}
12087a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
12097a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		if (EHEA_BMASK_GET(NEQE_EXTSWITCH_PRIMARY, eqe))
12108c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			netdev_info(dev,
12118c4877a4128e7931077b024a891a4b284d8756a3Joe Perches				    "External switch port is primary port\n");
12127a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		else
12138c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			netdev_info(dev,
12148c4877a4128e7931077b024a891a4b284d8756a3Joe Perches				    "External switch port is backup port\n");
12157a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
12167a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		break;
12177a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	case EHEA_EC_ADAPTER_MALFUNC:
12188c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		netdev_err(dev, "Adapter malfunction\n");
12197a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		break;
12207a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	case EHEA_EC_PORT_MALFUNC:
12218c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		netdev_info(dev, "Port malfunction\n");
12228c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		netif_carrier_off(dev);
1223b95644685d530de5e9f9658bd8087e50840b831dAnton Blanchard		netif_tx_disable(dev);
12247a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		break;
12257a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	default:
12268c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		netdev_err(dev, "unknown event code %x, eqe=0x%llX\n", ec, eqe);
12277a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		break;
12287a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
12297a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
12307a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
12317a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic void ehea_neq_tasklet(unsigned long data)
12327a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
1233508d2b5d261abbd7fb728092c5025c5063060c04Doug Maxey	struct ehea_adapter *adapter = (struct ehea_adapter *)data;
12347a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_eqe *eqe;
12357a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	u64 event_mask;
12367a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
12377a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	eqe = ehea_poll_eq(adapter->neq);
12388c4877a4128e7931077b024a891a4b284d8756a3Joe Perches	pr_debug("eqe=%p\n", eqe);
12397a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
12407a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	while (eqe) {
12418c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_debug("*eqe=%lx\n", (unsigned long) eqe->entry);
12427a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ehea_parse_eqe(adapter, eqe->entry);
12437a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		eqe = ehea_poll_eq(adapter->neq);
12448c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_debug("next eqe=%p\n", eqe);
12457a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
12467a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
12477a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	event_mask = EHEA_BMASK_SET(NELR_PORTSTATE_CHG, 1)
12487a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		   | EHEA_BMASK_SET(NELR_ADAPTER_MALFUNC, 1)
12497a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		   | EHEA_BMASK_SET(NELR_PORT_MALFUNC, 1);
12507a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
12517a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ehea_h_reset_events(adapter->handle,
12527a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			    adapter->neq->fw_handle, event_mask);
12537a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
12547a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
12557d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t ehea_interrupt_neq(int irq, void *param)
12567a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
12577a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_adapter *adapter = param;
12587a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	tasklet_hi_schedule(&adapter->neq_tasklet);
12597a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return IRQ_HANDLED;
12607a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
12617a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
12627a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
12637a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic int ehea_fill_port_res(struct ehea_port_res *pr)
12647a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
12657a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int ret;
12667a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_qp_init_attr *init_attr = &pr->qp->init_attr;
12677a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
1268f76957fc8fc4fa9735f01e59653b2792b077de06Breno Leitao	ehea_init_fill_rq1(pr, pr->rq1_skba.len);
12697a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
1270e2878806227d223467f84f900ef4c6733ee166dfThomas Klein	ret = ehea_refill_rq2(pr, init_attr->act_nr_rwqes_rq2 - 1);
12717a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
12727a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ret |= ehea_refill_rq3(pr, init_attr->act_nr_rwqes_rq3 - 1);
12737a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
12747a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return ret;
12757a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
12767a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
12777a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic int ehea_reg_interrupts(struct net_device *dev)
12787a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
12797a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_port *port = netdev_priv(dev);
12807a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_port_res *pr;
12817a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int i, ret;
12827a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
12837a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
12847a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	snprintf(port->int_aff_name, EHEA_IRQ_NAME_SIZE - 1, "%s-aff",
12857a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		 dev->name);
12867a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
12876b08f3ae8eec27a9e557468a48540bc64fd4a524Joachim Fenkes	ret = ibmebus_request_irq(port->qp_eq->attr.ist1,
12887a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				  ehea_qp_aff_irq_handler,
128938515e908ba3a9c467ad3bf347b9bce69216df94Thomas Gleixner				  IRQF_DISABLED, port->int_aff_name, port);
12907a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (ret) {
12918c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		netdev_err(dev, "failed registering irq for qp_aff_irq_handler:ist=%X\n",
12928c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			   port->qp_eq->attr.ist1);
12937a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out_free_qpeq;
12947a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
12957a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
12968c4877a4128e7931077b024a891a4b284d8756a3Joe Perches	netif_info(port, ifup, dev,
12978c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		   "irq_handle 0x%X for function qp_aff_irq_handler registered\n",
12988c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		   port->qp_eq->attr.ist1);
12997a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
130018604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann
1301723f28e49c9f8578b418dfd1ec8c7b9cc13e2b63Anton Blanchard	for (i = 0; i < port->num_def_qps; i++) {
13027a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		pr = &port->port_res[i];
13037a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		snprintf(pr->int_send_name, EHEA_IRQ_NAME_SIZE - 1,
130418604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann			 "%s-queue%d", dev->name, i);
13056b08f3ae8eec27a9e557468a48540bc64fd4a524Joachim Fenkes		ret = ibmebus_request_irq(pr->eq->attr.ist1,
130618604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann					  ehea_recv_irq_handler,
130738515e908ba3a9c467ad3bf347b9bce69216df94Thomas Gleixner					  IRQF_DISABLED, pr->int_send_name,
13087a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann					  pr);
13097a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		if (ret) {
13108c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			netdev_err(dev, "failed registering irq for ehea_queue port_res_nr:%d, ist=%X\n",
13118c4877a4128e7931077b024a891a4b284d8756a3Joe Perches				   i, pr->eq->attr.ist1);
13127a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			goto out_free_req;
13137a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		}
13148c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		netif_info(port, ifup, dev,
13158c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			   "irq_handle 0x%X for function ehea_queue_int %d registered\n",
13168c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			   pr->eq->attr.ist1, i);
13177a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
13187a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannout:
13197a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return ret;
13207a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
132118604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann
13227a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannout_free_req:
13237a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	while (--i >= 0) {
132418604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann		u32 ist = port->port_res[i].eq->attr.ist1;
13256b08f3ae8eec27a9e557468a48540bc64fd4a524Joachim Fenkes		ibmebus_free_irq(ist, &port->port_res[i]);
13267a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
132718604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann
13287a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannout_free_qpeq:
13296b08f3ae8eec27a9e557468a48540bc64fd4a524Joachim Fenkes	ibmebus_free_irq(port->qp_eq->attr.ist1, port);
13307a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	i = port->num_def_qps;
133118604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann
13327a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	goto out;
133318604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann
13347a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
13357a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
13367a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic void ehea_free_interrupts(struct net_device *dev)
13377a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
13387a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_port *port = netdev_priv(dev);
13397a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_port_res *pr;
13407a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int i;
13417a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
13427a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	/* send */
134318604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann
1344723f28e49c9f8578b418dfd1ec8c7b9cc13e2b63Anton Blanchard	for (i = 0; i < port->num_def_qps; i++) {
13457a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		pr = &port->port_res[i];
13466b08f3ae8eec27a9e557468a48540bc64fd4a524Joachim Fenkes		ibmebus_free_irq(pr->eq->attr.ist1, pr);
13478c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		netif_info(port, intr, dev,
13488c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			   "free send irq for res %d with handle 0x%X\n",
13498c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			   i, pr->eq->attr.ist1);
13507a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
13517a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
13527a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	/* associated events */
13536b08f3ae8eec27a9e557468a48540bc64fd4a524Joachim Fenkes	ibmebus_free_irq(port->qp_eq->attr.ist1, port);
13548c4877a4128e7931077b024a891a4b284d8756a3Joe Perches	netif_info(port, intr, dev,
13558c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		   "associated event interrupt for handle 0x%X freed\n",
13568c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		   port->qp_eq->attr.ist1);
13577a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
13587a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
13597a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic int ehea_configure_port(struct ehea_port *port)
13607a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
13617a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int ret, i;
13627a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	u64 hret, mask;
13637a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct hcp_ehea_port_cb0 *cb0;
13647a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
13657a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ret = -ENOMEM;
13663faf2693bd6800c2521799f6a9ae174d9f080ed2Thomas Klein	cb0 = (void *)get_zeroed_page(GFP_KERNEL);
13677a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (!cb0)
13687a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out;
13697a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
13707a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	cb0->port_rc = EHEA_BMASK_SET(PXLY_RC_VALID, 1)
13717a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		     | EHEA_BMASK_SET(PXLY_RC_IP_CHKSUM, 1)
13727a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		     | EHEA_BMASK_SET(PXLY_RC_TCP_UDP_CHKSUM, 1)
13737a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		     | EHEA_BMASK_SET(PXLY_RC_VLAN_XTRACT, 1)
13747a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		     | EHEA_BMASK_SET(PXLY_RC_VLAN_TAG_FILTER,
13757a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				      PXLY_RC_VLAN_FILTER)
13767a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		     | EHEA_BMASK_SET(PXLY_RC_JUMBO_FRAME, 1);
13777a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
137818604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann	for (i = 0; i < port->num_mcs; i++)
137918604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann		if (use_mcs)
138018604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann			cb0->default_qpn_arr[i] =
138118604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann				port->port_res[i].qp->init_attr.qp_nr;
138218604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann		else
138318604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann			cb0->default_qpn_arr[i] =
138418604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann				port->port_res[0].qp->init_attr.qp_nr;
1385e542aa6bd50ba163253e60ba8e7e51c0d56162a7Jan-Bernd Themann
13867a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (netif_msg_ifup(port))
13877a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ehea_dump(cb0, sizeof(*cb0), "ehea_configure_port");
13887a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
13897a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	mask = EHEA_BMASK_SET(H_PORT_CB0_PRC, 1)
13907a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	     | EHEA_BMASK_SET(H_PORT_CB0_DEFQPNARRAY, 1);
13917a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
13927a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	hret = ehea_h_modify_ehea_port(port->adapter->handle,
13937a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				       port->logical_port_id,
13947a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				       H_PORT_CB0, mask, cb0);
13957a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ret = -EIO;
13967a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (hret != H_SUCCESS)
13977a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out_free;
13987a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
13997a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ret = 0;
14007a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
14017a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannout_free:
14023faf2693bd6800c2521799f6a9ae174d9f080ed2Thomas Klein	free_page((unsigned long)cb0);
14037a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannout:
14047a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return ret;
14057a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
14067a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
14071886e5d2c694e7fb59434c717e704e7fd8475d2eThadeu Lima de Souza Cascardostatic int ehea_gen_smrs(struct ehea_port_res *pr)
14087a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
1409e542aa6bd50ba163253e60ba8e7e51c0d56162a7Jan-Bernd Themann	int ret;
14107a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_adapter *adapter = pr->port->adapter;
14117a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
1412e542aa6bd50ba163253e60ba8e7e51c0d56162a7Jan-Bernd Themann	ret = ehea_gen_smr(adapter, &adapter->mr, &pr->send_mr);
1413e542aa6bd50ba163253e60ba8e7e51c0d56162a7Jan-Bernd Themann	if (ret)
14147a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out;
14157a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
1416e542aa6bd50ba163253e60ba8e7e51c0d56162a7Jan-Bernd Themann	ret = ehea_gen_smr(adapter, &adapter->mr, &pr->recv_mr);
1417e542aa6bd50ba163253e60ba8e7e51c0d56162a7Jan-Bernd Themann	if (ret)
1418e542aa6bd50ba163253e60ba8e7e51c0d56162a7Jan-Bernd Themann		goto out_free;
14197a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
14207a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return 0;
14217a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
1422e542aa6bd50ba163253e60ba8e7e51c0d56162a7Jan-Bernd Themannout_free:
1423e542aa6bd50ba163253e60ba8e7e51c0d56162a7Jan-Bernd Themann	ehea_rem_mr(&pr->send_mr);
14247a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannout:
14258c4877a4128e7931077b024a891a4b284d8756a3Joe Perches	pr_err("Generating SMRS failed\n");
14267a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return -EIO;
14277a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
14287a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
14291886e5d2c694e7fb59434c717e704e7fd8475d2eThadeu Lima de Souza Cascardostatic int ehea_rem_smrs(struct ehea_port_res *pr)
14307a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
14318e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches	if ((ehea_rem_mr(&pr->send_mr)) ||
14328e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches	    (ehea_rem_mr(&pr->recv_mr)))
1433e542aa6bd50ba163253e60ba8e7e51c0d56162a7Jan-Bernd Themann		return -EIO;
1434e542aa6bd50ba163253e60ba8e7e51c0d56162a7Jan-Bernd Themann	else
1435e542aa6bd50ba163253e60ba8e7e51c0d56162a7Jan-Bernd Themann		return 0;
14367a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
14377a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
14387a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic int ehea_init_q_skba(struct ehea_q_skb_arr *q_skba, int max_q_entries)
14397a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
1440508d2b5d261abbd7fb728092c5025c5063060c04Doug Maxey	int arr_size = sizeof(void *) * max_q_entries;
14417a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
144289bf67f1f080c947c92f8773482d9e57767ca292Eric Dumazet	q_skba->arr = vzalloc(arr_size);
14437a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (!q_skba->arr)
14447a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		return -ENOMEM;
14457a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
14467a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	q_skba->len = max_q_entries;
14477a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	q_skba->index = 0;
14487a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	q_skba->os_skbs = 0;
14497a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
14507a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return 0;
14517a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
14527a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
14537a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic int ehea_init_port_res(struct ehea_port *port, struct ehea_port_res *pr,
14547a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			      struct port_res_cfg *pr_cfg, int queue_token)
14557a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
14567a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_adapter *adapter = port->adapter;
14577a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	enum ehea_eq_type eq_type = EHEA_EQ;
14587a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_qp_init_attr *init_attr = NULL;
14597a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int ret = -EIO;
1460ce45b873028fdf94a24f0850cd554e6fda593e16Breno Leitao	u64 tx_bytes, rx_bytes, tx_packets, rx_packets;
1461ce45b873028fdf94a24f0850cd554e6fda593e16Breno Leitao
1462ce45b873028fdf94a24f0850cd554e6fda593e16Breno Leitao	tx_bytes = pr->tx_bytes;
1463ce45b873028fdf94a24f0850cd554e6fda593e16Breno Leitao	tx_packets = pr->tx_packets;
1464ce45b873028fdf94a24f0850cd554e6fda593e16Breno Leitao	rx_bytes = pr->rx_bytes;
1465ce45b873028fdf94a24f0850cd554e6fda593e16Breno Leitao	rx_packets = pr->rx_packets;
14667a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
14677a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	memset(pr, 0, sizeof(struct ehea_port_res));
14687a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
1469ce45b873028fdf94a24f0850cd554e6fda593e16Breno Leitao	pr->tx_bytes = rx_bytes;
1470ce45b873028fdf94a24f0850cd554e6fda593e16Breno Leitao	pr->tx_packets = tx_packets;
1471ce45b873028fdf94a24f0850cd554e6fda593e16Breno Leitao	pr->rx_bytes = rx_bytes;
1472ce45b873028fdf94a24f0850cd554e6fda593e16Breno Leitao	pr->rx_packets = rx_packets;
1473ce45b873028fdf94a24f0850cd554e6fda593e16Breno Leitao
14747a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	pr->port = port;
14757a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
147618604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann	pr->eq = ehea_create_eq(adapter, eq_type, EHEA_MAX_ENTRIES_EQ, 0);
147718604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann	if (!pr->eq) {
14788c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("create_eq failed (eq)\n");
14797a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out_free;
14807a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
14817a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
14827a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	pr->recv_cq = ehea_create_cq(adapter, pr_cfg->max_entries_rcq,
148318604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann				     pr->eq->fw_handle,
14847a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				     port->logical_port_id);
14857a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (!pr->recv_cq) {
14868c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("create_cq failed (cq_recv)\n");
14877a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out_free;
14887a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
14897a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
14907a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	pr->send_cq = ehea_create_cq(adapter, pr_cfg->max_entries_scq,
149118604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann				     pr->eq->fw_handle,
14927a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				     port->logical_port_id);
14937a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (!pr->send_cq) {
14948c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("create_cq failed (cq_send)\n");
14957a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out_free;
14967a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
14977a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
14987a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (netif_msg_ifup(port))
14998c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_info("Send CQ: act_nr_cqes=%d, Recv CQ: act_nr_cqes=%d\n",
15008c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			pr->send_cq->attr.act_nr_of_cqes,
15018c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			pr->recv_cq->attr.act_nr_of_cqes);
15027a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
15037a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	init_attr = kzalloc(sizeof(*init_attr), GFP_KERNEL);
15047a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (!init_attr) {
15057a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ret = -ENOMEM;
15068c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("no mem for ehea_qp_init_attr\n");
15077a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out_free;
15087a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
15097a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
15107a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	init_attr->low_lat_rq1 = 1;
15117a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	init_attr->signalingtype = 1;	/* generate CQE if specified in WQE */
15127a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	init_attr->rq_count = 3;
15137a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	init_attr->qp_token = queue_token;
15147a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	init_attr->max_nr_send_wqes = pr_cfg->max_entries_sq;
15157a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	init_attr->max_nr_rwqes_rq1 = pr_cfg->max_entries_rq1;
15167a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	init_attr->max_nr_rwqes_rq2 = pr_cfg->max_entries_rq2;
15177a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	init_attr->max_nr_rwqes_rq3 = pr_cfg->max_entries_rq3;
15187a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	init_attr->wqe_size_enc_sq = EHEA_SG_SQ;
15197a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	init_attr->wqe_size_enc_rq1 = EHEA_SG_RQ1;
15207a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	init_attr->wqe_size_enc_rq2 = EHEA_SG_RQ2;
15217a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	init_attr->wqe_size_enc_rq3 = EHEA_SG_RQ3;
15227a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	init_attr->rq2_threshold = EHEA_RQ2_THRESHOLD;
15237a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	init_attr->rq3_threshold = EHEA_RQ3_THRESHOLD;
15247a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	init_attr->port_nr = port->logical_port_id;
15257a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	init_attr->send_cq_handle = pr->send_cq->fw_handle;
15267a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	init_attr->recv_cq_handle = pr->recv_cq->fw_handle;
15277a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	init_attr->aff_eq_handle = port->qp_eq->fw_handle;
15287a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
15297a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	pr->qp = ehea_create_qp(adapter, adapter->pd, init_attr);
15307a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (!pr->qp) {
15318c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("create_qp failed\n");
15327a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ret = -EIO;
15337a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out_free;
15347a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
15357a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
15367a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (netif_msg_ifup(port))
15378c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_info("QP: qp_nr=%d\n act_nr_snd_wqe=%d\n nr_rwqe_rq1=%d\n nr_rwqe_rq2=%d\n nr_rwqe_rq3=%d\n",
15388c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			init_attr->qp_nr,
15398c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			init_attr->act_nr_send_wqes,
15408c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			init_attr->act_nr_rwqes_rq1,
15418c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			init_attr->act_nr_rwqes_rq2,
15428c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			init_attr->act_nr_rwqes_rq3);
15437a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
154444fb3126d7e6fb411775551b4653643f1d28ebe9Thomas Klein	pr->sq_skba_size = init_attr->act_nr_send_wqes + 1;
154544fb3126d7e6fb411775551b4653643f1d28ebe9Thomas Klein
154644fb3126d7e6fb411775551b4653643f1d28ebe9Thomas Klein	ret = ehea_init_q_skba(&pr->sq_skba, pr->sq_skba_size);
15477a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ret |= ehea_init_q_skba(&pr->rq1_skba, init_attr->act_nr_rwqes_rq1 + 1);
15487a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ret |= ehea_init_q_skba(&pr->rq2_skba, init_attr->act_nr_rwqes_rq2 + 1);
15497a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ret |= ehea_init_q_skba(&pr->rq3_skba, init_attr->act_nr_rwqes_rq3 + 1);
15507a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (ret)
15517a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out_free;
15527a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
15537a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	pr->swqe_refill_th = init_attr->act_nr_send_wqes / 10;
15547a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (ehea_gen_smrs(pr) != 0) {
15557a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ret = -EIO;
15567a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out_free;
15577a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
155818604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann
15597a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	atomic_set(&pr->swqe_avail, init_attr->act_nr_send_wqes - 1);
15607a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
15617a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	kfree(init_attr);
156218604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann
1563bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger	netif_napi_add(pr->port->netdev, &pr->napi, ehea_poll, 64);
156418604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann
15657a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ret = 0;
15667a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	goto out;
15677a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
15687a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannout_free:
15697a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	kfree(init_attr);
15707a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	vfree(pr->sq_skba.arr);
15717a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	vfree(pr->rq1_skba.arr);
15727a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	vfree(pr->rq2_skba.arr);
15737a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	vfree(pr->rq3_skba.arr);
15747a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ehea_destroy_qp(pr->qp);
15757a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ehea_destroy_cq(pr->send_cq);
15767a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ehea_destroy_cq(pr->recv_cq);
157718604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann	ehea_destroy_eq(pr->eq);
15787a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannout:
15797a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return ret;
15807a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
15817a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
15827a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic int ehea_clean_portres(struct ehea_port *port, struct ehea_port_res *pr)
15837a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
15847a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int ret, i;
15857a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
1586357eb46d8f275b4e8484541234ea3ba06065e258Hannes Hering	if (pr->qp)
1587357eb46d8f275b4e8484541234ea3ba06065e258Hannes Hering		netif_napi_del(&pr->napi);
1588357eb46d8f275b4e8484541234ea3ba06065e258Hannes Hering
15897a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ret = ehea_destroy_qp(pr->qp);
15907a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
15917a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (!ret) {
15927a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ehea_destroy_cq(pr->send_cq);
15937a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ehea_destroy_cq(pr->recv_cq);
159418604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann		ehea_destroy_eq(pr->eq);
15957a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
15967a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		for (i = 0; i < pr->rq1_skba.len; i++)
15977a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			if (pr->rq1_skba.arr[i])
15987a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				dev_kfree_skb(pr->rq1_skba.arr[i]);
15997a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
16007a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		for (i = 0; i < pr->rq2_skba.len; i++)
16017a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			if (pr->rq2_skba.arr[i])
16027a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				dev_kfree_skb(pr->rq2_skba.arr[i]);
16037a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
16047a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		for (i = 0; i < pr->rq3_skba.len; i++)
16057a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			if (pr->rq3_skba.arr[i])
16067a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				dev_kfree_skb(pr->rq3_skba.arr[i]);
16077a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
16087a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		for (i = 0; i < pr->sq_skba.len; i++)
16097a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			if (pr->sq_skba.arr[i])
16107a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				dev_kfree_skb(pr->sq_skba.arr[i]);
16117a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
16127a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		vfree(pr->rq1_skba.arr);
16137a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		vfree(pr->rq2_skba.arr);
16147a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		vfree(pr->rq3_skba.arr);
16157a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		vfree(pr->sq_skba.arr);
16167a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ret = ehea_rem_smrs(pr);
16177a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
16187a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return ret;
16197a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
16207a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
162113946f5e4eefd5162733a75c03bb9f52c9c69614Anton Blanchardstatic void write_swqe2_immediate(struct sk_buff *skb, struct ehea_swqe *swqe,
162213946f5e4eefd5162733a75c03bb9f52c9c69614Anton Blanchard				  u32 lkey)
16237a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
1624e743d31312d00932391b123dfac3324d2b9e8c81Eric Dumazet	int skb_data_size = skb_headlen(skb);
16257a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	u8 *imm_data = &swqe->u.immdata_desc.immediate_data[0];
16267a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_vsgentry *sg1entry = &swqe->u.immdata_desc.sg_entry;
162713946f5e4eefd5162733a75c03bb9f52c9c69614Anton Blanchard	unsigned int immediate_len = SWQE2_MAX_IMM;
162813946f5e4eefd5162733a75c03bb9f52c9c69614Anton Blanchard
162913946f5e4eefd5162733a75c03bb9f52c9c69614Anton Blanchard	swqe->descriptors = 0;
16307a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
163113946f5e4eefd5162733a75c03bb9f52c9c69614Anton Blanchard	if (skb_is_gso(skb)) {
163213946f5e4eefd5162733a75c03bb9f52c9c69614Anton Blanchard		swqe->tx_control |= EHEA_SWQE_TSO;
163313946f5e4eefd5162733a75c03bb9f52c9c69614Anton Blanchard		swqe->mss = skb_shinfo(skb)->gso_size;
163413946f5e4eefd5162733a75c03bb9f52c9c69614Anton Blanchard		/*
163513946f5e4eefd5162733a75c03bb9f52c9c69614Anton Blanchard		 * For TSO packets we only copy the headers into the
163613946f5e4eefd5162733a75c03bb9f52c9c69614Anton Blanchard		 * immediate area.
163713946f5e4eefd5162733a75c03bb9f52c9c69614Anton Blanchard		 */
163813946f5e4eefd5162733a75c03bb9f52c9c69614Anton Blanchard		immediate_len = ETH_HLEN + ip_hdrlen(skb) + tcp_hdrlen(skb);
163913946f5e4eefd5162733a75c03bb9f52c9c69614Anton Blanchard	}
16407a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
164113946f5e4eefd5162733a75c03bb9f52c9c69614Anton Blanchard	if (skb_is_gso(skb) || skb_data_size >= SWQE2_MAX_IMM) {
164213946f5e4eefd5162733a75c03bb9f52c9c69614Anton Blanchard		skb_copy_from_linear_data(skb, imm_data, immediate_len);
164313946f5e4eefd5162733a75c03bb9f52c9c69614Anton Blanchard		swqe->immediate_data_length = immediate_len;
16447a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
164513946f5e4eefd5162733a75c03bb9f52c9c69614Anton Blanchard		if (skb_data_size > immediate_len) {
16467a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			sg1entry->l_key = lkey;
164713946f5e4eefd5162733a75c03bb9f52c9c69614Anton Blanchard			sg1entry->len = skb_data_size - immediate_len;
164844a5b3d539893988dc6b63054c59d031df1fd7bcThomas Klein			sg1entry->vaddr =
164913946f5e4eefd5162733a75c03bb9f52c9c69614Anton Blanchard				ehea_map_vaddr(skb->data + immediate_len);
16507a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			swqe->descriptors++;
16517a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		}
16527a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	} else {
1653d626f62b11e00c16e81e4308ab93d3f13551812aArnaldo Carvalho de Melo		skb_copy_from_linear_data(skb, imm_data, skb_data_size);
16547a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		swqe->immediate_data_length = skb_data_size;
16557a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
16567a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
16577a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
16587a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic inline void write_swqe2_data(struct sk_buff *skb, struct net_device *dev,
16597a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				    struct ehea_swqe *swqe, u32 lkey)
16607a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
16617a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_vsgentry *sg_list, *sg1entry, *sgentry;
16627a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	skb_frag_t *frag;
16637a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int nfrags, sg1entry_contains_frag_data, i;
16647a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
16657a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	nfrags = skb_shinfo(skb)->nr_frags;
16667a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	sg1entry = &swqe->u.immdata_desc.sg_entry;
1667508d2b5d261abbd7fb728092c5025c5063060c04Doug Maxey	sg_list = (struct ehea_vsgentry *)&swqe->u.immdata_desc.sg_list;
16687a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	sg1entry_contains_frag_data = 0;
16697a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
167013946f5e4eefd5162733a75c03bb9f52c9c69614Anton Blanchard	write_swqe2_immediate(skb, swqe, lkey);
16717a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
16727a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	/* write descriptors */
16737a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (nfrags > 0) {
16747a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		if (swqe->descriptors == 0) {
16757a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			/* sg1entry not yet used */
16767a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			frag = &skb_shinfo(skb)->frags[0];
16777a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
16787a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			/* copy sg1entry data */
16797a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			sg1entry->l_key = lkey;
16809e903e085262ffbf1fc44a17ac06058aca03524aEric Dumazet			sg1entry->len = skb_frag_size(frag);
168144a5b3d539893988dc6b63054c59d031df1fd7bcThomas Klein			sg1entry->vaddr =
1682618c4a0ad41a42edd4f06259623f78f2e8da66e8Ian Campbell				ehea_map_vaddr(skb_frag_address(frag));
16837a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			swqe->descriptors++;
16847a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			sg1entry_contains_frag_data = 1;
16857a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		}
16867a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
16877a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		for (i = sg1entry_contains_frag_data; i < nfrags; i++) {
16887a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
16897a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			frag = &skb_shinfo(skb)->frags[i];
16907a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			sgentry = &sg_list[i - sg1entry_contains_frag_data];
16917a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
16927a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			sgentry->l_key = lkey;
16930110bba5e7731524940f9e02ce3d4aae75087f68Eric Dumazet			sgentry->len = skb_frag_size(frag);
1694618c4a0ad41a42edd4f06259623f78f2e8da66e8Ian Campbell			sgentry->vaddr = ehea_map_vaddr(skb_frag_address(frag));
16957a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			swqe->descriptors++;
16967a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		}
16977a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
16987a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
16997a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
17007a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic int ehea_broadcast_reg_helper(struct ehea_port *port, u32 hcallid)
17017a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
17027a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int ret = 0;
17037a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	u64 hret;
17047a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	u8 reg_type;
17057a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
17067a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	/* De/Register untagged packets */
17077a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	reg_type = EHEA_BCMC_BROADCAST | EHEA_BCMC_UNTAGGED;
17087a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	hret = ehea_h_reg_dereg_bcmc(port->adapter->handle,
17097a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				     port->logical_port_id,
17107a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				     reg_type, port->mac_addr, 0, hcallid);
17117a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (hret != H_SUCCESS) {
17128c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("%sregistering bc address failed (tagged)\n",
17138c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		       hcallid == H_REG_BCMC ? "" : "de");
17147a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ret = -EIO;
17157a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out_herr;
17167a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
17177a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
17187a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	/* De/Register VLAN packets */
17197a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	reg_type = EHEA_BCMC_BROADCAST | EHEA_BCMC_VLANID_ALL;
17207a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	hret = ehea_h_reg_dereg_bcmc(port->adapter->handle,
17217a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				     port->logical_port_id,
17227a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				     reg_type, port->mac_addr, 0, hcallid);
17237a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (hret != H_SUCCESS) {
17248c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("%sregistering bc address failed (vlan)\n",
17258c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		       hcallid == H_REG_BCMC ? "" : "de");
17267a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ret = -EIO;
17277a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
17287a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannout_herr:
17297a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return ret;
17307a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
17317a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
17327a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic int ehea_set_mac_addr(struct net_device *dev, void *sa)
17337a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
17347a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_port *port = netdev_priv(dev);
17357a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct sockaddr *mac_addr = sa;
17367a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct hcp_ehea_port_cb0 *cb0;
17377a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int ret;
17387a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	u64 hret;
17397a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
17407a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (!is_valid_ether_addr(mac_addr->sa_data)) {
17417a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ret = -EADDRNOTAVAIL;
17427a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out;
17437a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
17447a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
17453faf2693bd6800c2521799f6a9ae174d9f080ed2Thomas Klein	cb0 = (void *)get_zeroed_page(GFP_KERNEL);
17467a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (!cb0) {
17478c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("no mem for cb0\n");
17487a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ret = -ENOMEM;
17497a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out;
17507a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
17517a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
17527a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	memcpy(&(cb0->port_mac_addr), &(mac_addr->sa_data[0]), ETH_ALEN);
17537a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
17547a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	cb0->port_mac_addr = cb0->port_mac_addr >> 16;
17557a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
17567a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	hret = ehea_h_modify_ehea_port(port->adapter->handle,
17577a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				       port->logical_port_id, H_PORT_CB0,
17587a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				       EHEA_BMASK_SET(H_PORT_CB0_MAC, 1), cb0);
17597a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (hret != H_SUCCESS) {
17607a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ret = -EIO;
17617a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out_free;
17627a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
17637a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
17647a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	memcpy(dev->dev_addr, mac_addr->sa_data, dev->addr_len);
17657a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
17667a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	/* Deregister old MAC in pHYP */
176700aaea2f95d73d4e2b5e45cf77c3cbb16c59e87fJan-Bernd Themann	if (port->state == EHEA_PORT_UP) {
176800aaea2f95d73d4e2b5e45cf77c3cbb16c59e87fJan-Bernd Themann		ret = ehea_broadcast_reg_helper(port, H_DEREG_BCMC);
176900aaea2f95d73d4e2b5e45cf77c3cbb16c59e87fJan-Bernd Themann		if (ret)
177000aaea2f95d73d4e2b5e45cf77c3cbb16c59e87fJan-Bernd Themann			goto out_upregs;
177100aaea2f95d73d4e2b5e45cf77c3cbb16c59e87fJan-Bernd Themann	}
17727a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
17737a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	port->mac_addr = cb0->port_mac_addr << 16;
17747a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
17757a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	/* Register new MAC in pHYP */
177600aaea2f95d73d4e2b5e45cf77c3cbb16c59e87fJan-Bernd Themann	if (port->state == EHEA_PORT_UP) {
177700aaea2f95d73d4e2b5e45cf77c3cbb16c59e87fJan-Bernd Themann		ret = ehea_broadcast_reg_helper(port, H_REG_BCMC);
177800aaea2f95d73d4e2b5e45cf77c3cbb16c59e87fJan-Bernd Themann		if (ret)
177900aaea2f95d73d4e2b5e45cf77c3cbb16c59e87fJan-Bernd Themann			goto out_upregs;
178000aaea2f95d73d4e2b5e45cf77c3cbb16c59e87fJan-Bernd Themann	}
17817a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
17827a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ret = 0;
178321eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
178421eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Kleinout_upregs:
178521eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	ehea_update_bcmc_registrations();
17867a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannout_free:
17873faf2693bd6800c2521799f6a9ae174d9f080ed2Thomas Klein	free_page((unsigned long)cb0);
17887a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannout:
17897a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return ret;
17907a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
17917a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
17927a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic void ehea_promiscuous_error(u64 hret, int enable)
17937a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
17947674a588e93c6fa1fde8e452a4c025c49037cb96Thomas Klein	if (hret == H_AUTHORITY)
17958c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_info("Hypervisor denied %sabling promiscuous mode\n",
17968c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			enable == 1 ? "en" : "dis");
17977674a588e93c6fa1fde8e452a4c025c49037cb96Thomas Klein	else
17988c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("failed %sabling promiscuous mode\n",
17998c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		       enable == 1 ? "en" : "dis");
18007a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
18017a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
18027a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic void ehea_promiscuous(struct net_device *dev, int enable)
18037a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
18047a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_port *port = netdev_priv(dev);
18057a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct hcp_ehea_port_cb7 *cb7;
18067a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	u64 hret;
18077a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
1808aa3bc6c68e3c1064969f5f2962be84491ffb69a0Nicolas Kaiser	if (enable == port->promisc)
18097a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		return;
18107a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
18113faf2693bd6800c2521799f6a9ae174d9f080ed2Thomas Klein	cb7 = (void *)get_zeroed_page(GFP_ATOMIC);
18127a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (!cb7) {
18138c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("no mem for cb7\n");
18147a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out;
18157a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
18167a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
18177a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	/* Modify Pxs_DUCQPN in CB7 */
18187a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	cb7->def_uc_qpn = enable == 1 ? port->port_res[0].qp->fw_handle : 0;
18197a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
18207a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	hret = ehea_h_modify_ehea_port(port->adapter->handle,
18217a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				       port->logical_port_id,
18227a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				       H_PORT_CB7, H_PORT_CB7_DUCQPN, cb7);
18237a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (hret) {
18247a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ehea_promiscuous_error(hret, enable);
18257a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out;
18267a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
18277a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
18287a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	port->promisc = enable;
18297a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannout:
18303faf2693bd6800c2521799f6a9ae174d9f080ed2Thomas Klein	free_page((unsigned long)cb7);
18317a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
18327a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
18337a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic u64 ehea_multicast_reg_helper(struct ehea_port *port, u64 mc_mac_addr,
18347a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				     u32 hcallid)
18357a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
18367a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	u64 hret;
18377a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	u8 reg_type;
18387a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
18397a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	reg_type = EHEA_BCMC_SCOPE_ALL | EHEA_BCMC_MULTICAST
18407a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		 | EHEA_BCMC_UNTAGGED;
18417a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
18427a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	hret = ehea_h_reg_dereg_bcmc(port->adapter->handle,
18437a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				     port->logical_port_id,
18447a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				     reg_type, mc_mac_addr, 0, hcallid);
18457a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (hret)
18467a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out;
18477a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
18487a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	reg_type = EHEA_BCMC_SCOPE_ALL | EHEA_BCMC_MULTICAST
18497a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		 | EHEA_BCMC_VLANID_ALL;
18507a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
18517a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	hret = ehea_h_reg_dereg_bcmc(port->adapter->handle,
18527a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				     port->logical_port_id,
18537a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				     reg_type, mc_mac_addr, 0, hcallid);
18547a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannout:
18557a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return hret;
18567a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
18577a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
18587a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic int ehea_drop_multicast_list(struct net_device *dev)
18597a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
18607a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_port *port = netdev_priv(dev);
18617a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_mc_list *mc_entry = port->mc_list;
18627a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct list_head *pos;
18637a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct list_head *temp;
18647a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int ret = 0;
18657a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	u64 hret;
18667a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
18677a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	list_for_each_safe(pos, temp, &(port->mc_list->list)) {
18687a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		mc_entry = list_entry(pos, struct ehea_mc_list, list);
18697a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
18707a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		hret = ehea_multicast_reg_helper(port, mc_entry->macaddr,
18717a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann						 H_DEREG_BCMC);
18727a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		if (hret) {
18738c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			pr_err("failed deregistering mcast MAC\n");
18747a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			ret = -EIO;
18757a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		}
18767a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
18777a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		list_del(pos);
18787a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		kfree(mc_entry);
18797a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
18807a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return ret;
18817a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
18827a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
18837a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic void ehea_allmulti(struct net_device *dev, int enable)
18847a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
18857a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_port *port = netdev_priv(dev);
18867a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	u64 hret;
18877a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
18887a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (!port->allmulti) {
18897a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		if (enable) {
18907a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			/* Enable ALLMULTI */
18917a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			ehea_drop_multicast_list(dev);
18927a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			hret = ehea_multicast_reg_helper(port, 0, H_REG_BCMC);
18937a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			if (!hret)
18947a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				port->allmulti = 1;
18957a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			else
18968c4877a4128e7931077b024a891a4b284d8756a3Joe Perches				netdev_err(dev,
18978c4877a4128e7931077b024a891a4b284d8756a3Joe Perches					   "failed enabling IFF_ALLMULTI\n");
18987a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		}
18997a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	} else
19007a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		if (!enable) {
19017a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			/* Disable ALLMULTI */
19027a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			hret = ehea_multicast_reg_helper(port, 0, H_DEREG_BCMC);
19037a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			if (!hret)
19047a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				port->allmulti = 0;
19057a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			else
19068c4877a4128e7931077b024a891a4b284d8756a3Joe Perches				netdev_err(dev,
19078c4877a4128e7931077b024a891a4b284d8756a3Joe Perches					   "failed disabling IFF_ALLMULTI\n");
19087a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		}
19097a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
19107a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
1911508d2b5d261abbd7fb728092c5025c5063060c04Doug Maxeystatic void ehea_add_multicast_entry(struct ehea_port *port, u8 *mc_mac_addr)
19127a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
19137a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_mc_list *ehea_mcl_entry;
19147a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	u64 hret;
19157a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
19161e1675ccf758cbb4303ab052d58405cda6c745a7Jan-Bernd Themann	ehea_mcl_entry = kzalloc(sizeof(*ehea_mcl_entry), GFP_ATOMIC);
19177a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (!ehea_mcl_entry) {
19188c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("no mem for mcl_entry\n");
19197a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		return;
19207a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
19217a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
19227a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	INIT_LIST_HEAD(&ehea_mcl_entry->list);
19237a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
19247a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	memcpy(&ehea_mcl_entry->macaddr, mc_mac_addr, ETH_ALEN);
19257a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
19267a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	hret = ehea_multicast_reg_helper(port, ehea_mcl_entry->macaddr,
19277a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann					 H_REG_BCMC);
19287a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (!hret)
19297a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		list_add(&ehea_mcl_entry->list, &port->mc_list->list);
19307a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	else {
19318c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("failed registering mcast MAC\n");
19327a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		kfree(ehea_mcl_entry);
19337a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
19347a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
19357a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
19367a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic void ehea_set_multicast_list(struct net_device *dev)
19377a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
19387a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_port *port = netdev_priv(dev);
193922bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko	struct netdev_hw_addr *ha;
194048e2f183cb1709600012265a2e723f45a350d5feJiri Pirko	int ret;
19417a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
1942a4910b744486254cfa61995954c118fb2283c4fdBreno Leitao	if (port->promisc) {
19437a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ehea_promiscuous(dev, 1);
19447a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		return;
19457a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
19467a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ehea_promiscuous(dev, 0);
19477a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
19487a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (dev->flags & IFF_ALLMULTI) {
19497a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ehea_allmulti(dev, 1);
195021eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein		goto out;
19517a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
19527a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ehea_allmulti(dev, 0);
19537a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
19544cd24eaf0c6ee7f0242e34ee77ec899f255e66b5Jiri Pirko	if (!netdev_mc_empty(dev)) {
19557a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ret = ehea_drop_multicast_list(dev);
19567a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		if (ret) {
19577a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			/* Dropping the current multicast list failed.
19587a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			 * Enabling ALL_MULTI is the best we can do.
19597a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			 */
19607a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			ehea_allmulti(dev, 1);
19617a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		}
19627a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
19634cd24eaf0c6ee7f0242e34ee77ec899f255e66b5Jiri Pirko		if (netdev_mc_count(dev) > port->adapter->max_mc_mac) {
19648c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			pr_info("Mcast registration limit reached (0x%llx). Use ALLMULTI!\n",
19658c4877a4128e7931077b024a891a4b284d8756a3Joe Perches				port->adapter->max_mc_mac);
19667a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			goto out;
19677a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		}
19687a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
196922bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko		netdev_for_each_mc_addr(ha, dev)
197022bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko			ehea_add_multicast_entry(port, ha->addr);
1971508d2b5d261abbd7fb728092c5025c5063060c04Doug Maxey
19727a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
19737a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannout:
197421eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	ehea_update_bcmc_registrations();
19757a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
19767a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
19777a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic int ehea_change_mtu(struct net_device *dev, int new_mtu)
19787a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
19797a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if ((new_mtu < 68) || (new_mtu > EHEA_MAX_PACKET_SIZE))
19807a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		return -EINVAL;
19817a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	dev->mtu = new_mtu;
19827a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return 0;
19837a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
19847a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
1985d695c335f9165cb73f9389479cce755e8207b5f4Anton Blanchardstatic void xmit_common(struct sk_buff *skb, struct ehea_swqe *swqe)
19867a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
1987d695c335f9165cb73f9389479cce755e8207b5f4Anton Blanchard	swqe->tx_control |= EHEA_SWQE_IMM_DATA_PRESENT | EHEA_SWQE_CRC;
1988d1d25aaba85fd24ab18b0a4d22f19be02aac65c9Jan-Bernd Themann
1989d695c335f9165cb73f9389479cce755e8207b5f4Anton Blanchard	if (skb->protocol != htons(ETH_P_IP))
1990d695c335f9165cb73f9389479cce755e8207b5f4Anton Blanchard		return;
19917a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
1992d695c335f9165cb73f9389479cce755e8207b5f4Anton Blanchard	if (skb->ip_summed == CHECKSUM_PARTIAL)
1993d695c335f9165cb73f9389479cce755e8207b5f4Anton Blanchard		swqe->tx_control |= EHEA_SWQE_IP_CHECKSUM;
19947a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
1995d695c335f9165cb73f9389479cce755e8207b5f4Anton Blanchard	swqe->ip_start = skb_network_offset(skb);
1996d695c335f9165cb73f9389479cce755e8207b5f4Anton Blanchard	swqe->ip_end = swqe->ip_start + ip_hdrlen(skb) - 1;
19977a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
1998d695c335f9165cb73f9389479cce755e8207b5f4Anton Blanchard	switch (ip_hdr(skb)->protocol) {
1999d695c335f9165cb73f9389479cce755e8207b5f4Anton Blanchard	case IPPROTO_UDP:
2000d695c335f9165cb73f9389479cce755e8207b5f4Anton Blanchard		if (skb->ip_summed == CHECKSUM_PARTIAL)
2001d695c335f9165cb73f9389479cce755e8207b5f4Anton Blanchard			swqe->tx_control |= EHEA_SWQE_TCP_CHECKSUM;
20027a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
2003d695c335f9165cb73f9389479cce755e8207b5f4Anton Blanchard		swqe->tcp_offset = swqe->ip_end + 1 +
2004d695c335f9165cb73f9389479cce755e8207b5f4Anton Blanchard				   offsetof(struct udphdr, check);
2005d695c335f9165cb73f9389479cce755e8207b5f4Anton Blanchard		break;
2006d695c335f9165cb73f9389479cce755e8207b5f4Anton Blanchard
2007d695c335f9165cb73f9389479cce755e8207b5f4Anton Blanchard	case IPPROTO_TCP:
2008d695c335f9165cb73f9389479cce755e8207b5f4Anton Blanchard		if (skb->ip_summed == CHECKSUM_PARTIAL)
2009d695c335f9165cb73f9389479cce755e8207b5f4Anton Blanchard			swqe->tx_control |= EHEA_SWQE_TCP_CHECKSUM;
2010d695c335f9165cb73f9389479cce755e8207b5f4Anton Blanchard
2011d695c335f9165cb73f9389479cce755e8207b5f4Anton Blanchard		swqe->tcp_offset = swqe->ip_end + 1 +
2012d695c335f9165cb73f9389479cce755e8207b5f4Anton Blanchard				   offsetof(struct tcphdr, check);
2013d695c335f9165cb73f9389479cce755e8207b5f4Anton Blanchard		break;
20147a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
2015d695c335f9165cb73f9389479cce755e8207b5f4Anton Blanchard}
2016d695c335f9165cb73f9389479cce755e8207b5f4Anton Blanchard
2017d695c335f9165cb73f9389479cce755e8207b5f4Anton Blanchardstatic void ehea_xmit2(struct sk_buff *skb, struct net_device *dev,
2018d695c335f9165cb73f9389479cce755e8207b5f4Anton Blanchard		       struct ehea_swqe *swqe, u32 lkey)
2019d695c335f9165cb73f9389479cce755e8207b5f4Anton Blanchard{
2020d695c335f9165cb73f9389479cce755e8207b5f4Anton Blanchard	swqe->tx_control |= EHEA_SWQE_DESCRIPTORS_PRESENT;
2021d695c335f9165cb73f9389479cce755e8207b5f4Anton Blanchard
2022d695c335f9165cb73f9389479cce755e8207b5f4Anton Blanchard	xmit_common(skb, swqe);
20237a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
20247a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	write_swqe2_data(skb, dev, swqe, lkey);
20257a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
20267a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
20277a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic void ehea_xmit3(struct sk_buff *skb, struct net_device *dev,
20287a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		       struct ehea_swqe *swqe)
20297a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
20307a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	u8 *imm_data = &swqe->u.immdata_nodesc.immediate_data[0];
20317a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
2032d695c335f9165cb73f9389479cce755e8207b5f4Anton Blanchard	xmit_common(skb, swqe);
2033d1d25aaba85fd24ab18b0a4d22f19be02aac65c9Jan-Bernd Themann
203430e2e90b4de735769c8c9dc2397388fdf305e5caAnton Blanchard	if (!skb->data_len)
2035d626f62b11e00c16e81e4308ab93d3f13551812aArnaldo Carvalho de Melo		skb_copy_from_linear_data(skb, imm_data, skb->len);
203630e2e90b4de735769c8c9dc2397388fdf305e5caAnton Blanchard	else
203730e2e90b4de735769c8c9dc2397388fdf305e5caAnton Blanchard		skb_copy_bits(skb, 0, imm_data, skb->len);
2038d695c335f9165cb73f9389479cce755e8207b5f4Anton Blanchard
20397a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	swqe->immediate_data_length = skb->len;
20407a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	dev_kfree_skb(skb);
20417a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
20427a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
20437a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic int ehea_start_xmit(struct sk_buff *skb, struct net_device *dev)
20447a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
20457a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_port *port = netdev_priv(dev);
20467a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_swqe *swqe;
20477a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	u32 lkey;
20487a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int swqe_index;
204918604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann	struct ehea_port_res *pr;
2050b95644685d530de5e9f9658bd8087e50840b831dAnton Blanchard	struct netdev_queue *txq;
205118604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann
2052b95644685d530de5e9f9658bd8087e50840b831dAnton Blanchard	pr = &port->port_res[skb_get_queue_mapping(skb)];
2053b95644685d530de5e9f9658bd8087e50840b831dAnton Blanchard	txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb));
205418604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann
20557a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	swqe = ehea_get_swqe(pr->qp, &swqe_index);
20567a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	memset(swqe, 0, SWQE_HEADER_SIZE);
20577a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	atomic_dec(&pr->swqe_avail);
20587a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
2059e5ccd96110d5ac0f73b695ba606feb6d69472f26Eric Dumazet	if (vlan_tx_tag_present(skb)) {
2060e5ccd96110d5ac0f73b695ba606feb6d69472f26Eric Dumazet		swqe->tx_control |= EHEA_SWQE_VLAN_INSERT;
2061e5ccd96110d5ac0f73b695ba606feb6d69472f26Eric Dumazet		swqe->vlan_tag = vlan_tx_tag_get(skb);
2062e5ccd96110d5ac0f73b695ba606feb6d69472f26Eric Dumazet	}
2063e5ccd96110d5ac0f73b695ba606feb6d69472f26Eric Dumazet
2064ce45b873028fdf94a24f0850cd554e6fda593e16Breno Leitao	pr->tx_packets++;
2065ce45b873028fdf94a24f0850cd554e6fda593e16Breno Leitao	pr->tx_bytes += skb->len;
2066ce45b873028fdf94a24f0850cd554e6fda593e16Breno Leitao
20677a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (skb->len <= SWQE3_MAX_IMM) {
20687a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		u32 sig_iv = port->sig_comp_iv;
20697a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		u32 swqe_num = pr->swqe_id_counter;
20707a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ehea_xmit3(skb, dev, swqe);
20717a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		swqe->wr_id = EHEA_BMASK_SET(EHEA_WR_ID_TYPE, EHEA_SWQE3_TYPE)
20727a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			| EHEA_BMASK_SET(EHEA_WR_ID_COUNT, swqe_num);
20737a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		if (pr->swqe_ll_count >= (sig_iv - 1)) {
20747a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			swqe->wr_id |= EHEA_BMASK_SET(EHEA_WR_ID_REFILL,
20757a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann						      sig_iv);
20767a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			swqe->tx_control |= EHEA_SWQE_SIGNALLED_COMPLETION;
20777a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			pr->swqe_ll_count = 0;
20787a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		} else
20797a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			pr->swqe_ll_count += 1;
20807a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	} else {
20817a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		swqe->wr_id =
20827a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			EHEA_BMASK_SET(EHEA_WR_ID_TYPE, EHEA_SWQE2_TYPE)
20837a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		      | EHEA_BMASK_SET(EHEA_WR_ID_COUNT, pr->swqe_id_counter)
2084acbddb591ba76bb20204fd6a407cb87d3f5f751eJan-Bernd Themann		      | EHEA_BMASK_SET(EHEA_WR_ID_REFILL, 1)
20857a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		      | EHEA_BMASK_SET(EHEA_WR_ID_INDEX, pr->sq_skba.index);
20867a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		pr->sq_skba.arr[pr->sq_skba.index] = skb;
20877a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
20887a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		pr->sq_skba.index++;
20897a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		pr->sq_skba.index &= (pr->sq_skba.len - 1);
20907a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
20917a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		lkey = pr->send_mr.lkey;
20927a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ehea_xmit2(skb, dev, swqe, lkey);
2093acbddb591ba76bb20204fd6a407cb87d3f5f751eJan-Bernd Themann		swqe->tx_control |= EHEA_SWQE_SIGNALLED_COMPLETION;
20947a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
20957a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	pr->swqe_id_counter += 1;
20967a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
20978c4877a4128e7931077b024a891a4b284d8756a3Joe Perches	netif_info(port, tx_queued, dev,
20988c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		   "post swqe on QP %d\n", pr->qp->init_attr.qp_nr);
20998c4877a4128e7931077b024a891a4b284d8756a3Joe Perches	if (netif_msg_tx_queued(port))
2100bff0a55f34e62970203c4af9c8ef4dc7d73e2f96Jan-Bernd Themann		ehea_dump(swqe, 512, "swqe");
21017a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
21022c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	if (unlikely(test_bit(__EHEA_STOP_XFER, &ehea_driver_flags))) {
2103b95644685d530de5e9f9658bd8087e50840b831dAnton Blanchard		netif_tx_stop_queue(txq);
21042c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		swqe->tx_control |= EHEA_SWQE_PURGE;
21052c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	}
210644c821525778c5d2e81da293195d5d589e8ad845Thomas Klein
21077a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ehea_post_swqe(pr->qp, swqe);
21087a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
21097a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (unlikely(atomic_read(&pr->swqe_avail) <= 1)) {
2110b95644685d530de5e9f9658bd8087e50840b831dAnton Blanchard		pr->p_stats.queue_stopped++;
2111b95644685d530de5e9f9658bd8087e50840b831dAnton Blanchard		netif_tx_stop_queue(txq);
21127a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
21132c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann
21147a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return NETDEV_TX_OK;
21157a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
21167a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
21178e586137e6b63af1e881b328466ab5ffbe562510Jiri Pirkostatic int ehea_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
21187a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
21197a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_port *port = netdev_priv(dev);
21207a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_adapter *adapter = port->adapter;
21217a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct hcp_ehea_port_cb1 *cb1;
21227a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int index;
21237a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	u64 hret;
21248e586137e6b63af1e881b328466ab5ffbe562510Jiri Pirko	int err = 0;
21257a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
21263faf2693bd6800c2521799f6a9ae174d9f080ed2Thomas Klein	cb1 = (void *)get_zeroed_page(GFP_KERNEL);
21277a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (!cb1) {
21288c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("no mem for cb1\n");
21298e586137e6b63af1e881b328466ab5ffbe562510Jiri Pirko		err = -ENOMEM;
21307a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out;
21317a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
21327a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
21337a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	hret = ehea_h_query_ehea_port(adapter->handle, port->logical_port_id,
21347a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				      H_PORT_CB1, H_PORT_CB1_ALL, cb1);
21357a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (hret != H_SUCCESS) {
21368c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("query_ehea_port failed\n");
21378e586137e6b63af1e881b328466ab5ffbe562510Jiri Pirko		err = -EINVAL;
21387a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out;
21397a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
21407a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
21417a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	index = (vid / 64);
2142dec590c1bb05c1553b68cab7aa3ea36d77e7f9a3Thomas Klein	cb1->vlan_filter[index] |= ((u64)(0x8000000000000000 >> (vid & 0x3F)));
21437a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
21447a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	hret = ehea_h_modify_ehea_port(adapter->handle, port->logical_port_id,
21457a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				       H_PORT_CB1, H_PORT_CB1_ALL, cb1);
21468e586137e6b63af1e881b328466ab5ffbe562510Jiri Pirko	if (hret != H_SUCCESS) {
21478c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("modify_ehea_port failed\n");
21488e586137e6b63af1e881b328466ab5ffbe562510Jiri Pirko		err = -EINVAL;
21498e586137e6b63af1e881b328466ab5ffbe562510Jiri Pirko	}
21507a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannout:
21513faf2693bd6800c2521799f6a9ae174d9f080ed2Thomas Klein	free_page((unsigned long)cb1);
21528e586137e6b63af1e881b328466ab5ffbe562510Jiri Pirko	return err;
21537a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
21547a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
21558e586137e6b63af1e881b328466ab5ffbe562510Jiri Pirkostatic int ehea_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
21567a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
21577a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_port *port = netdev_priv(dev);
21587a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_adapter *adapter = port->adapter;
21597a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct hcp_ehea_port_cb1 *cb1;
21607a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int index;
21617a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	u64 hret;
21628e586137e6b63af1e881b328466ab5ffbe562510Jiri Pirko	int err = 0;
21637a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
21643faf2693bd6800c2521799f6a9ae174d9f080ed2Thomas Klein	cb1 = (void *)get_zeroed_page(GFP_KERNEL);
21657a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (!cb1) {
21668c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("no mem for cb1\n");
21678e586137e6b63af1e881b328466ab5ffbe562510Jiri Pirko		err = -ENOMEM;
21687a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out;
21697a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
21707a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
21717a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	hret = ehea_h_query_ehea_port(adapter->handle, port->logical_port_id,
21727a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				      H_PORT_CB1, H_PORT_CB1_ALL, cb1);
21737a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (hret != H_SUCCESS) {
21748c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("query_ehea_port failed\n");
21758e586137e6b63af1e881b328466ab5ffbe562510Jiri Pirko		err = -EINVAL;
21767a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out;
21777a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
21787a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
21797a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	index = (vid / 64);
2180dec590c1bb05c1553b68cab7aa3ea36d77e7f9a3Thomas Klein	cb1->vlan_filter[index] &= ~((u64)(0x8000000000000000 >> (vid & 0x3F)));
21817a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
21827a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	hret = ehea_h_modify_ehea_port(adapter->handle, port->logical_port_id,
21837a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				       H_PORT_CB1, H_PORT_CB1_ALL, cb1);
21848e586137e6b63af1e881b328466ab5ffbe562510Jiri Pirko	if (hret != H_SUCCESS) {
21858c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("modify_ehea_port failed\n");
21868e586137e6b63af1e881b328466ab5ffbe562510Jiri Pirko		err = -EINVAL;
21878e586137e6b63af1e881b328466ab5ffbe562510Jiri Pirko	}
21887a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannout:
21893faf2693bd6800c2521799f6a9ae174d9f080ed2Thomas Klein	free_page((unsigned long)cb1);
21908e586137e6b63af1e881b328466ab5ffbe562510Jiri Pirko	return err;
21917a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
21927a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
21931886e5d2c694e7fb59434c717e704e7fd8475d2eThadeu Lima de Souza Cascardostatic int ehea_activate_qp(struct ehea_adapter *adapter, struct ehea_qp *qp)
21947a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
21957a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int ret = -EIO;
21967a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	u64 hret;
21977a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	u16 dummy16 = 0;
21987a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	u64 dummy64 = 0;
2199508d2b5d261abbd7fb728092c5025c5063060c04Doug Maxey	struct hcp_modify_qp_cb0 *cb0;
22007a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
22013faf2693bd6800c2521799f6a9ae174d9f080ed2Thomas Klein	cb0 = (void *)get_zeroed_page(GFP_KERNEL);
22027a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (!cb0) {
22037a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ret = -ENOMEM;
22047a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out;
22057a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
22067a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
22077a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	hret = ehea_h_query_ehea_qp(adapter->handle, 0, qp->fw_handle,
22087a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				    EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF), cb0);
22097a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (hret != H_SUCCESS) {
22108c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("query_ehea_qp failed (1)\n");
22117a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out;
22127a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
22137a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
22147a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	cb0->qp_ctl_reg = H_QP_CR_STATE_INITIALIZED;
22157a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	hret = ehea_h_modify_ehea_qp(adapter->handle, 0, qp->fw_handle,
22167a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				     EHEA_BMASK_SET(H_QPCB0_QP_CTL_REG, 1), cb0,
22177a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				     &dummy64, &dummy64, &dummy16, &dummy16);
22187a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (hret != H_SUCCESS) {
22198c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("modify_ehea_qp failed (1)\n");
22207a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out;
22217a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
22227a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
22237a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	hret = ehea_h_query_ehea_qp(adapter->handle, 0, qp->fw_handle,
22247a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				    EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF), cb0);
22257a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (hret != H_SUCCESS) {
22268c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("query_ehea_qp failed (2)\n");
22277a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out;
22287a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
22297a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
22307a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	cb0->qp_ctl_reg = H_QP_CR_ENABLED | H_QP_CR_STATE_INITIALIZED;
22317a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	hret = ehea_h_modify_ehea_qp(adapter->handle, 0, qp->fw_handle,
22327a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				     EHEA_BMASK_SET(H_QPCB0_QP_CTL_REG, 1), cb0,
22337a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				     &dummy64, &dummy64, &dummy16, &dummy16);
22347a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (hret != H_SUCCESS) {
22358c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("modify_ehea_qp failed (2)\n");
22367a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out;
22377a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
22387a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
22397a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	hret = ehea_h_query_ehea_qp(adapter->handle, 0, qp->fw_handle,
22407a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				    EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF), cb0);
22417a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (hret != H_SUCCESS) {
22428c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("query_ehea_qp failed (3)\n");
22437a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out;
22447a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
22457a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
22467a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	cb0->qp_ctl_reg = H_QP_CR_ENABLED | H_QP_CR_STATE_RDY2SND;
22477a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	hret = ehea_h_modify_ehea_qp(adapter->handle, 0, qp->fw_handle,
22487a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				     EHEA_BMASK_SET(H_QPCB0_QP_CTL_REG, 1), cb0,
22497a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				     &dummy64, &dummy64, &dummy16, &dummy16);
22507a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (hret != H_SUCCESS) {
22518c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("modify_ehea_qp failed (3)\n");
22527a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out;
22537a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
22547a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
22557a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	hret = ehea_h_query_ehea_qp(adapter->handle, 0, qp->fw_handle,
22567a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				    EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF), cb0);
22577a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (hret != H_SUCCESS) {
22588c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("query_ehea_qp failed (4)\n");
22597a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out;
22607a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
22617a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
22627a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ret = 0;
22637a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannout:
22643faf2693bd6800c2521799f6a9ae174d9f080ed2Thomas Klein	free_page((unsigned long)cb0);
22657a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return ret;
22667a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
22677a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
2268723f28e49c9f8578b418dfd1ec8c7b9cc13e2b63Anton Blanchardstatic int ehea_port_res_setup(struct ehea_port *port, int def_qps)
22697a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
22707a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int ret, i;
22717a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct port_res_cfg pr_cfg, pr_cfg_small_rx;
22727a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	enum ehea_eq_type eq_type = EHEA_EQ;
22737a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
22747a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	port->qp_eq = ehea_create_eq(port->adapter, eq_type,
22757a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				   EHEA_MAX_ENTRIES_EQ, 1);
22767a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (!port->qp_eq) {
22777a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ret = -EINVAL;
22788c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("ehea_create_eq failed (qp_eq)\n");
22797a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out_kill_eq;
22807a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
22817a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
22827a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	pr_cfg.max_entries_rcq = rq1_entries + rq2_entries + rq3_entries;
228318604c54854549ee0ad65e27ca9cb91c96af784cJan-Bernd Themann	pr_cfg.max_entries_scq = sq_entries * 2;
22847a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	pr_cfg.max_entries_sq = sq_entries;
22857a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	pr_cfg.max_entries_rq1 = rq1_entries;
22867a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	pr_cfg.max_entries_rq2 = rq2_entries;
22877a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	pr_cfg.max_entries_rq3 = rq3_entries;
22887a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
22897a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	pr_cfg_small_rx.max_entries_rcq = 1;
22907a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	pr_cfg_small_rx.max_entries_scq = sq_entries;
22917a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	pr_cfg_small_rx.max_entries_sq = sq_entries;
22927a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	pr_cfg_small_rx.max_entries_rq1 = 1;
22937a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	pr_cfg_small_rx.max_entries_rq2 = 1;
22947a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	pr_cfg_small_rx.max_entries_rq3 = 1;
22957a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
22967a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	for (i = 0; i < def_qps; i++) {
22977a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ret = ehea_init_port_res(port, &port->port_res[i], &pr_cfg, i);
22987a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		if (ret)
22997a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			goto out_clean_pr;
23007a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
2301723f28e49c9f8578b418dfd1ec8c7b9cc13e2b63Anton Blanchard	for (i = def_qps; i < def_qps; i++) {
23027a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ret = ehea_init_port_res(port, &port->port_res[i],
23037a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann					 &pr_cfg_small_rx, i);
23047a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		if (ret)
23057a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			goto out_clean_pr;
23067a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
23077a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
23087a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return 0;
23097a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
23107a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannout_clean_pr:
23117a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	while (--i >= 0)
23127a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ehea_clean_portres(port, &port->port_res[i]);
23137a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
23147a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannout_kill_eq:
23157a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ehea_destroy_eq(port->qp_eq);
23167a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return ret;
23177a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
23187a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
23197a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic int ehea_clean_all_portres(struct ehea_port *port)
23207a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
23217a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int ret = 0;
23227a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int i;
23237a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
2324723f28e49c9f8578b418dfd1ec8c7b9cc13e2b63Anton Blanchard	for (i = 0; i < port->num_def_qps; i++)
23257a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ret |= ehea_clean_portres(port, &port->port_res[i]);
23267a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
23277a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ret |= ehea_destroy_eq(port->qp_eq);
23287a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
23297a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return ret;
23307a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
23317a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
233235cf2e2e3b96c070a615d699bf514ffec6afd19eThomas Kleinstatic void ehea_remove_adapter_mr(struct ehea_adapter *adapter)
23331211bb6dcd935c48e864d4eecbf8a684e982419aThomas Klein{
233435cf2e2e3b96c070a615d699bf514ffec6afd19eThomas Klein	if (adapter->active_ports)
233535cf2e2e3b96c070a615d699bf514ffec6afd19eThomas Klein		return;
23361211bb6dcd935c48e864d4eecbf8a684e982419aThomas Klein
23371211bb6dcd935c48e864d4eecbf8a684e982419aThomas Klein	ehea_rem_mr(&adapter->mr);
23381211bb6dcd935c48e864d4eecbf8a684e982419aThomas Klein}
23391211bb6dcd935c48e864d4eecbf8a684e982419aThomas Klein
234035cf2e2e3b96c070a615d699bf514ffec6afd19eThomas Kleinstatic int ehea_add_adapter_mr(struct ehea_adapter *adapter)
23411211bb6dcd935c48e864d4eecbf8a684e982419aThomas Klein{
234235cf2e2e3b96c070a615d699bf514ffec6afd19eThomas Klein	if (adapter->active_ports)
234335cf2e2e3b96c070a615d699bf514ffec6afd19eThomas Klein		return 0;
23441211bb6dcd935c48e864d4eecbf8a684e982419aThomas Klein
23451211bb6dcd935c48e864d4eecbf8a684e982419aThomas Klein	return ehea_reg_kernel_mr(adapter, &adapter->mr);
23461211bb6dcd935c48e864d4eecbf8a684e982419aThomas Klein}
23471211bb6dcd935c48e864d4eecbf8a684e982419aThomas Klein
23487a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic int ehea_up(struct net_device *dev)
23497a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
23507a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int ret, i;
23517a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_port *port = netdev_priv(dev);
23527a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
23537a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (port->state == EHEA_PORT_UP)
23547a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		return 0;
23557a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
2356723f28e49c9f8578b418dfd1ec8c7b9cc13e2b63Anton Blanchard	ret = ehea_port_res_setup(port, port->num_def_qps);
23577a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (ret) {
23588c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		netdev_err(dev, "port_res_failed\n");
23597a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out;
23607a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
23617a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
23627a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	/* Set default QP for this port */
23637a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ret = ehea_configure_port(port);
23647a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (ret) {
23658c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		netdev_err(dev, "ehea_configure_port failed. ret:%d\n", ret);
23667a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out_clean_pr;
23677a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
23687a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
23697a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ret = ehea_reg_interrupts(dev);
23707a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (ret) {
23718c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		netdev_err(dev, "reg_interrupts failed. ret:%d\n", ret);
2372f9e29228e6f2058e7b086115ecb7008630ebd832Thomas Klein		goto out_clean_pr;
23737a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
23747a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
2375723f28e49c9f8578b418dfd1ec8c7b9cc13e2b63Anton Blanchard	for (i = 0; i < port->num_def_qps; i++) {
23767a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ret = ehea_activate_qp(port->adapter, port->port_res[i].qp);
23777a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		if (ret) {
23788c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			netdev_err(dev, "activate_qp failed\n");
23797a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			goto out_free_irqs;
23807a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		}
23817a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
23827a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
2383508d2b5d261abbd7fb728092c5025c5063060c04Doug Maxey	for (i = 0; i < port->num_def_qps; i++) {
23847a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ret = ehea_fill_port_res(&port->port_res[i]);
23857a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		if (ret) {
23868c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			netdev_err(dev, "out_free_irqs\n");
23877a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			goto out_free_irqs;
23887a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		}
23897a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
23907a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
239121eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	ret = ehea_broadcast_reg_helper(port, H_REG_BCMC);
239221eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	if (ret) {
239321eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein		ret = -EIO;
239421eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein		goto out_free_irqs;
239521eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	}
239621eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
23977a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	port->state = EHEA_PORT_UP;
239821eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
239921eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	ret = 0;
24007a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	goto out;
24017a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
24027a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannout_free_irqs:
24037a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ehea_free_interrupts(dev);
24047a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
24057a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannout_clean_pr:
24067a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ehea_clean_all_portres(port);
24077a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannout:
240844c821525778c5d2e81da293195d5d589e8ad845Thomas Klein	if (ret)
24098c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		netdev_info(dev, "Failed starting. ret=%i\n", ret);
241044c821525778c5d2e81da293195d5d589e8ad845Thomas Klein
241121eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	ehea_update_bcmc_registrations();
241221eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	ehea_update_firmware_handles();
241321eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
24147a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return ret;
24157a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
24167a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
2417bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemmingerstatic void port_napi_disable(struct ehea_port *port)
2418bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger{
2419bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger	int i;
2420bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger
2421723f28e49c9f8578b418dfd1ec8c7b9cc13e2b63Anton Blanchard	for (i = 0; i < port->num_def_qps; i++)
2422bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger		napi_disable(&port->port_res[i].napi);
2423bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger}
2424bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger
2425bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemmingerstatic void port_napi_enable(struct ehea_port *port)
2426bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger{
2427bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger	int i;
2428bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger
2429723f28e49c9f8578b418dfd1ec8c7b9cc13e2b63Anton Blanchard	for (i = 0; i < port->num_def_qps; i++)
2430bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger		napi_enable(&port->port_res[i].napi);
2431bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger}
2432bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger
24337a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic int ehea_open(struct net_device *dev)
24347a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
24357a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int ret;
24367a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_port *port = netdev_priv(dev);
24377a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
2438a5af6ad3a0d4f5c6d0a3535d46fc1b26eeff0816Daniel Walker	mutex_lock(&port->port_lock);
24397a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
24408c4877a4128e7931077b024a891a4b284d8756a3Joe Perches	netif_info(port, ifup, dev, "enabling port\n");
24417a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
24427a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ret = ehea_up(dev);
2443bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger	if (!ret) {
2444bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger		port_napi_enable(port);
2445b95644685d530de5e9f9658bd8087e50840b831dAnton Blanchard		netif_tx_start_all_queues(dev);
2446bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger	}
24477a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
2448a5af6ad3a0d4f5c6d0a3535d46fc1b26eeff0816Daniel Walker	mutex_unlock(&port->port_lock);
244967c170a24fc6669f8f7c0864d75caadef0a8e5e6Anton Blanchard	schedule_delayed_work(&port->stats_work,
245067c170a24fc6669f8f7c0864d75caadef0a8e5e6Anton Blanchard			      round_jiffies_relative(msecs_to_jiffies(1000)));
24517a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
24527a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return ret;
24537a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
24547a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
24557a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic int ehea_down(struct net_device *dev)
24567a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
2457bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger	int ret;
24587a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_port *port = netdev_priv(dev);
24597a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
24607a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (port->state == EHEA_PORT_DOWN)
24617a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		return 0;
24627a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
24637a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ehea_drop_multicast_list(dev);
246421eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	ehea_broadcast_reg_helper(port, H_DEREG_BCMC);
246521eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
24667a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ehea_free_interrupts(dev);
24677a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
24687a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	port->state = EHEA_PORT_DOWN;
246944c821525778c5d2e81da293195d5d589e8ad845Thomas Klein
247021eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	ehea_update_bcmc_registrations();
247121eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
247244c821525778c5d2e81da293195d5d589e8ad845Thomas Klein	ret = ehea_clean_all_portres(port);
247344c821525778c5d2e81da293195d5d589e8ad845Thomas Klein	if (ret)
24748c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		netdev_info(dev, "Failed freeing resources. ret=%i\n", ret);
247544c821525778c5d2e81da293195d5d589e8ad845Thomas Klein
247621eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	ehea_update_firmware_handles();
247721eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
24787a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return ret;
24797a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
24807a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
24817a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic int ehea_stop(struct net_device *dev)
24827a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
24837a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int ret;
24847a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_port *port = netdev_priv(dev);
24857a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
24868c4877a4128e7931077b024a891a4b284d8756a3Joe Perches	netif_info(port, ifdown, dev, "disabling port\n");
24877a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
24882f69ae01c83a94af5dc3c20e8135b974687ed004Jan-Bernd Themann	set_bit(__EHEA_DISABLE_PORT_RESET, &port->flags);
24894bb073c0e32a0862bdb5215d11af19f6c0180c98David S. Miller	cancel_work_sync(&port->reset_task);
24902aefcad8666e0c7c1aff51c0dacc164a1b681895brenohl@br.ibm.com	cancel_delayed_work_sync(&port->stats_work);
2491a5af6ad3a0d4f5c6d0a3535d46fc1b26eeff0816Daniel Walker	mutex_lock(&port->port_lock);
2492b95644685d530de5e9f9658bd8087e50840b831dAnton Blanchard	netif_tx_stop_all_queues(dev);
24930173b793ca477aa2ca516ebf0a35e137b678d466Jan-Bernd Themann	port_napi_disable(port);
24947a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ret = ehea_down(dev);
2495a5af6ad3a0d4f5c6d0a3535d46fc1b26eeff0816Daniel Walker	mutex_unlock(&port->port_lock);
24962f69ae01c83a94af5dc3c20e8135b974687ed004Jan-Bernd Themann	clear_bit(__EHEA_DISABLE_PORT_RESET, &port->flags);
24977a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return ret;
24987a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
24997a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
250022559c5d7488fe21f5f46117a4d275fc72066aa6Andrew Mortonstatic void ehea_purge_sq(struct ehea_qp *orig_qp)
25012c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann{
25022c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	struct ehea_qp qp = *orig_qp;
25032c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	struct ehea_qp_init_attr *init_attr = &qp.init_attr;
25042c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	struct ehea_swqe *swqe;
25052c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	int wqe_index;
25062c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	int i;
25072c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann
25082c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	for (i = 0; i < init_attr->act_nr_send_wqes; i++) {
25092c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		swqe = ehea_get_swqe(&qp, &wqe_index);
25102c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		swqe->tx_control |= EHEA_SWQE_PURGE;
25112c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	}
25122c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann}
25132c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann
251422559c5d7488fe21f5f46117a4d275fc72066aa6Andrew Mortonstatic void ehea_flush_sq(struct ehea_port *port)
251544fb3126d7e6fb411775551b4653643f1d28ebe9Thomas Klein{
251644fb3126d7e6fb411775551b4653643f1d28ebe9Thomas Klein	int i;
251744fb3126d7e6fb411775551b4653643f1d28ebe9Thomas Klein
2518723f28e49c9f8578b418dfd1ec8c7b9cc13e2b63Anton Blanchard	for (i = 0; i < port->num_def_qps; i++) {
251944fb3126d7e6fb411775551b4653643f1d28ebe9Thomas Klein		struct ehea_port_res *pr = &port->port_res[i];
252044fb3126d7e6fb411775551b4653643f1d28ebe9Thomas Klein		int swqe_max = pr->sq_skba_size - 2 - pr->swqe_ll_count;
25215b27d42755fa6536a89f32b107fb2a53267696c2Breno Leitao		int ret;
25225b27d42755fa6536a89f32b107fb2a53267696c2Breno Leitao
25235b27d42755fa6536a89f32b107fb2a53267696c2Breno Leitao		ret = wait_event_timeout(port->swqe_avail_wq,
25245b27d42755fa6536a89f32b107fb2a53267696c2Breno Leitao			 atomic_read(&pr->swqe_avail) >= swqe_max,
25255b27d42755fa6536a89f32b107fb2a53267696c2Breno Leitao			 msecs_to_jiffies(100));
25265b27d42755fa6536a89f32b107fb2a53267696c2Breno Leitao
25275b27d42755fa6536a89f32b107fb2a53267696c2Breno Leitao		if (!ret) {
25288c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			pr_err("WARNING: sq not flushed completely\n");
25295b27d42755fa6536a89f32b107fb2a53267696c2Breno Leitao			break;
253044fb3126d7e6fb411775551b4653643f1d28ebe9Thomas Klein		}
253144fb3126d7e6fb411775551b4653643f1d28ebe9Thomas Klein	}
253244fb3126d7e6fb411775551b4653643f1d28ebe9Thomas Klein}
253344fb3126d7e6fb411775551b4653643f1d28ebe9Thomas Klein
25341886e5d2c694e7fb59434c717e704e7fd8475d2eThadeu Lima de Souza Cascardostatic int ehea_stop_qps(struct net_device *dev)
25352c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann{
25362c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	struct ehea_port *port = netdev_priv(dev);
25372c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	struct ehea_adapter *adapter = port->adapter;
2538508d2b5d261abbd7fb728092c5025c5063060c04Doug Maxey	struct hcp_modify_qp_cb0 *cb0;
25392c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	int ret = -EIO;
25402c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	int dret;
25412c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	int i;
25422c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	u64 hret;
25432c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	u64 dummy64 = 0;
25442c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	u16 dummy16 = 0;
25452c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann
25463faf2693bd6800c2521799f6a9ae174d9f080ed2Thomas Klein	cb0 = (void *)get_zeroed_page(GFP_KERNEL);
25472c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	if (!cb0) {
25482c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		ret = -ENOMEM;
25492c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		goto out;
25502c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	}
25512c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann
2552723f28e49c9f8578b418dfd1ec8c7b9cc13e2b63Anton Blanchard	for (i = 0; i < (port->num_def_qps); i++) {
25532c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		struct ehea_port_res *pr =  &port->port_res[i];
25542c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		struct ehea_qp *qp = pr->qp;
25552c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann
25562c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		/* Purge send queue */
25572c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		ehea_purge_sq(qp);
25582c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann
25592c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		/* Disable queue pair */
25602c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		hret = ehea_h_query_ehea_qp(adapter->handle, 0, qp->fw_handle,
25612c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann					    EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF),
25622c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann					    cb0);
25632c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		if (hret != H_SUCCESS) {
25648c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			pr_err("query_ehea_qp failed (1)\n");
25652c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann			goto out;
25662c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		}
25672c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann
25682c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		cb0->qp_ctl_reg = (cb0->qp_ctl_reg & H_QP_CR_RES_STATE) << 8;
25692c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		cb0->qp_ctl_reg &= ~H_QP_CR_ENABLED;
25702c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann
25712c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		hret = ehea_h_modify_ehea_qp(adapter->handle, 0, qp->fw_handle,
25722c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann					     EHEA_BMASK_SET(H_QPCB0_QP_CTL_REG,
25732c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann							    1), cb0, &dummy64,
25742c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann					     &dummy64, &dummy16, &dummy16);
25752c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		if (hret != H_SUCCESS) {
25768c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			pr_err("modify_ehea_qp failed (1)\n");
25772c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann			goto out;
25782c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		}
25792c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann
25802c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		hret = ehea_h_query_ehea_qp(adapter->handle, 0, qp->fw_handle,
25812c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann					    EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF),
25822c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann					    cb0);
25832c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		if (hret != H_SUCCESS) {
25848c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			pr_err("query_ehea_qp failed (2)\n");
25852c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann			goto out;
25862c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		}
25872c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann
25882c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		/* deregister shared memory regions */
25892c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		dret = ehea_rem_smrs(pr);
25902c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		if (dret) {
25918c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			pr_err("unreg shared memory region failed\n");
25922c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann			goto out;
25932c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		}
25942c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	}
25952c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann
25962c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	ret = 0;
25972c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themannout:
25983faf2693bd6800c2521799f6a9ae174d9f080ed2Thomas Klein	free_page((unsigned long)cb0);
25992c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann
26002c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	return ret;
26012c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann}
26022c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann
26031886e5d2c694e7fb59434c717e704e7fd8475d2eThadeu Lima de Souza Cascardostatic void ehea_update_rqs(struct ehea_qp *orig_qp, struct ehea_port_res *pr)
26042c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann{
26052c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	struct ehea_qp qp = *orig_qp;
26062c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	struct ehea_qp_init_attr *init_attr = &qp.init_attr;
26072c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	struct ehea_rwqe *rwqe;
26082c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	struct sk_buff **skba_rq2 = pr->rq2_skba.arr;
26092c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	struct sk_buff **skba_rq3 = pr->rq3_skba.arr;
26102c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	struct sk_buff *skb;
26112c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	u32 lkey = pr->recv_mr.lkey;
26122c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann
26132c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann
26142c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	int i;
26152c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	int index;
26162c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann
26172c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	for (i = 0; i < init_attr->act_nr_rwqes_rq2 + 1; i++) {
26182c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		rwqe = ehea_get_next_rwqe(&qp, 2);
26192c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		rwqe->sg_list[0].l_key = lkey;
26202c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		index = EHEA_BMASK_GET(EHEA_WR_ID_INDEX, rwqe->wr_id);
26212c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		skb = skba_rq2[index];
26222c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		if (skb)
26232c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann			rwqe->sg_list[0].vaddr = ehea_map_vaddr(skb->data);
26242c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	}
26252c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann
26262c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	for (i = 0; i < init_attr->act_nr_rwqes_rq3 + 1; i++) {
26272c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		rwqe = ehea_get_next_rwqe(&qp, 3);
26282c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		rwqe->sg_list[0].l_key = lkey;
26292c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		index = EHEA_BMASK_GET(EHEA_WR_ID_INDEX, rwqe->wr_id);
26302c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		skb = skba_rq3[index];
26312c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		if (skb)
26322c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann			rwqe->sg_list[0].vaddr = ehea_map_vaddr(skb->data);
26332c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	}
26342c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann}
26352c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann
26361886e5d2c694e7fb59434c717e704e7fd8475d2eThadeu Lima de Souza Cascardostatic int ehea_restart_qps(struct net_device *dev)
26372c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann{
26382c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	struct ehea_port *port = netdev_priv(dev);
26392c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	struct ehea_adapter *adapter = port->adapter;
26402c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	int ret = 0;
26412c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	int i;
26422c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann
2643508d2b5d261abbd7fb728092c5025c5063060c04Doug Maxey	struct hcp_modify_qp_cb0 *cb0;
26442c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	u64 hret;
26452c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	u64 dummy64 = 0;
26462c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	u16 dummy16 = 0;
26472c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann
26483faf2693bd6800c2521799f6a9ae174d9f080ed2Thomas Klein	cb0 = (void *)get_zeroed_page(GFP_KERNEL);
26492c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	if (!cb0) {
26502c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		ret = -ENOMEM;
26512c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		goto out;
26522c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	}
26532c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann
2654723f28e49c9f8578b418dfd1ec8c7b9cc13e2b63Anton Blanchard	for (i = 0; i < (port->num_def_qps); i++) {
26552c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		struct ehea_port_res *pr =  &port->port_res[i];
26562c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		struct ehea_qp *qp = pr->qp;
26572c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann
26582c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		ret = ehea_gen_smrs(pr);
26592c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		if (ret) {
26608c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			netdev_err(dev, "creation of shared memory regions failed\n");
26612c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann			goto out;
26622c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		}
26632c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann
26642c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		ehea_update_rqs(qp, pr);
26652c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann
26662c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		/* Enable queue pair */
26672c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		hret = ehea_h_query_ehea_qp(adapter->handle, 0, qp->fw_handle,
26682c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann					    EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF),
26692c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann					    cb0);
26702c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		if (hret != H_SUCCESS) {
26718c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			netdev_err(dev, "query_ehea_qp failed (1)\n");
26722c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann			goto out;
26732c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		}
26742c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann
26752c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		cb0->qp_ctl_reg = (cb0->qp_ctl_reg & H_QP_CR_RES_STATE) << 8;
26762c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		cb0->qp_ctl_reg |= H_QP_CR_ENABLED;
26772c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann
26782c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		hret = ehea_h_modify_ehea_qp(adapter->handle, 0, qp->fw_handle,
26792c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann					     EHEA_BMASK_SET(H_QPCB0_QP_CTL_REG,
26802c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann							    1), cb0, &dummy64,
26812c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann					     &dummy64, &dummy16, &dummy16);
26822c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		if (hret != H_SUCCESS) {
26838c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			netdev_err(dev, "modify_ehea_qp failed (1)\n");
26842c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann			goto out;
26852c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		}
26862c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann
26872c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		hret = ehea_h_query_ehea_qp(adapter->handle, 0, qp->fw_handle,
26882c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann					    EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF),
26892c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann					    cb0);
26902c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		if (hret != H_SUCCESS) {
26918c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			netdev_err(dev, "query_ehea_qp failed (2)\n");
26922c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann			goto out;
26932c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		}
26942c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann
26952c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		/* refill entire queue */
26962c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		ehea_refill_rq1(pr, pr->rq1_skba.index, 0);
26972c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		ehea_refill_rq2(pr, 0);
26982c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann		ehea_refill_rq3(pr, 0);
26992c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	}
27002c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themannout:
27013faf2693bd6800c2521799f6a9ae174d9f080ed2Thomas Klein	free_page((unsigned long)cb0);
27022c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann
27032c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	return ret;
27042c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann}
27052c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann
2706c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howellsstatic void ehea_reset_port(struct work_struct *work)
27077a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
27087a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int ret;
2709c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells	struct ehea_port *port =
2710c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells		container_of(work, struct ehea_port, reset_task);
2711c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells	struct net_device *dev = port->netdev;
27127a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
2713099473c16bac7b936994bc95b5fd96f36397e1adJan-Bernd Themann	mutex_lock(&dlpar_mem_lock);
27147a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	port->resets++;
2715a5af6ad3a0d4f5c6d0a3535d46fc1b26eeff0816Daniel Walker	mutex_lock(&port->port_lock);
2716b95644685d530de5e9f9658bd8087e50840b831dAnton Blanchard	netif_tx_disable(dev);
2717bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger
2718bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger	port_napi_disable(port);
27197a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
272044c821525778c5d2e81da293195d5d589e8ad845Thomas Klein	ehea_down(dev);
27217a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
27227a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ret = ehea_up(dev);
272344c821525778c5d2e81da293195d5d589e8ad845Thomas Klein	if (ret)
27247a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out;
27257a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
27262c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	ehea_set_multicast_list(dev);
27272c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann
27288c4877a4128e7931077b024a891a4b284d8756a3Joe Perches	netif_info(port, timer, dev, "reset successful\n");
27297a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
2730bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger	port_napi_enable(port);
2731bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger
2732b95644685d530de5e9f9658bd8087e50840b831dAnton Blanchard	netif_tx_wake_all_queues(dev);
27337a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannout:
2734a5af6ad3a0d4f5c6d0a3535d46fc1b26eeff0816Daniel Walker	mutex_unlock(&port->port_lock);
2735099473c16bac7b936994bc95b5fd96f36397e1adJan-Bernd Themann	mutex_unlock(&dlpar_mem_lock);
27367a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
27377a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
27383d6b892bcc4c810071e36d8aff25aa171f55f93dTejun Heostatic void ehea_rereg_mrs(void)
273944c821525778c5d2e81da293195d5d589e8ad845Thomas Klein{
274044c821525778c5d2e81da293195d5d589e8ad845Thomas Klein	int ret, i;
274144c821525778c5d2e81da293195d5d589e8ad845Thomas Klein	struct ehea_adapter *adapter;
274244c821525778c5d2e81da293195d5d589e8ad845Thomas Klein
27438c4877a4128e7931077b024a891a4b284d8756a3Joe Perches	pr_info("LPAR memory changed - re-initializing driver\n");
274444c821525778c5d2e81da293195d5d589e8ad845Thomas Klein
274544c821525778c5d2e81da293195d5d589e8ad845Thomas Klein	list_for_each_entry(adapter, &adapter_list, list)
274644c821525778c5d2e81da293195d5d589e8ad845Thomas Klein		if (adapter->active_ports) {
274744c821525778c5d2e81da293195d5d589e8ad845Thomas Klein			/* Shutdown all ports */
274844c821525778c5d2e81da293195d5d589e8ad845Thomas Klein			for (i = 0; i < EHEA_MAX_PORTS; i++) {
274944c821525778c5d2e81da293195d5d589e8ad845Thomas Klein				struct ehea_port *port = adapter->port[i];
2750a5af6ad3a0d4f5c6d0a3535d46fc1b26eeff0816Daniel Walker				struct net_device *dev;
275144c821525778c5d2e81da293195d5d589e8ad845Thomas Klein
2752a5af6ad3a0d4f5c6d0a3535d46fc1b26eeff0816Daniel Walker				if (!port)
2753a5af6ad3a0d4f5c6d0a3535d46fc1b26eeff0816Daniel Walker					continue;
275444c821525778c5d2e81da293195d5d589e8ad845Thomas Klein
2755a5af6ad3a0d4f5c6d0a3535d46fc1b26eeff0816Daniel Walker				dev = port->netdev;
2756a5af6ad3a0d4f5c6d0a3535d46fc1b26eeff0816Daniel Walker
2757a5af6ad3a0d4f5c6d0a3535d46fc1b26eeff0816Daniel Walker				if (dev->flags & IFF_UP) {
2758a5af6ad3a0d4f5c6d0a3535d46fc1b26eeff0816Daniel Walker					mutex_lock(&port->port_lock);
2759b95644685d530de5e9f9658bd8087e50840b831dAnton Blanchard					netif_tx_disable(dev);
2760df39e8ba56a788733d369068c7319e04b1da3cd5David S. Miller					ehea_flush_sq(port);
2761a5af6ad3a0d4f5c6d0a3535d46fc1b26eeff0816Daniel Walker					ret = ehea_stop_qps(dev);
2762a5af6ad3a0d4f5c6d0a3535d46fc1b26eeff0816Daniel Walker					if (ret) {
2763a5af6ad3a0d4f5c6d0a3535d46fc1b26eeff0816Daniel Walker						mutex_unlock(&port->port_lock);
2764a5af6ad3a0d4f5c6d0a3535d46fc1b26eeff0816Daniel Walker						goto out;
276544c821525778c5d2e81da293195d5d589e8ad845Thomas Klein					}
2766a5af6ad3a0d4f5c6d0a3535d46fc1b26eeff0816Daniel Walker					port_napi_disable(port);
2767a5af6ad3a0d4f5c6d0a3535d46fc1b26eeff0816Daniel Walker					mutex_unlock(&port->port_lock);
276844c821525778c5d2e81da293195d5d589e8ad845Thomas Klein				}
27692928db4c3c62552d3caf9ab53ccc6f7ae9865a23Andre Detsch				reset_sq_restart_flag(port);
277044c821525778c5d2e81da293195d5d589e8ad845Thomas Klein			}
277144c821525778c5d2e81da293195d5d589e8ad845Thomas Klein
277244c821525778c5d2e81da293195d5d589e8ad845Thomas Klein			/* Unregister old memory region */
277344c821525778c5d2e81da293195d5d589e8ad845Thomas Klein			ret = ehea_rem_mr(&adapter->mr);
277444c821525778c5d2e81da293195d5d589e8ad845Thomas Klein			if (ret) {
27758c4877a4128e7931077b024a891a4b284d8756a3Joe Perches				pr_err("unregister MR failed - driver inoperable!\n");
277644c821525778c5d2e81da293195d5d589e8ad845Thomas Klein				goto out;
277744c821525778c5d2e81da293195d5d589e8ad845Thomas Klein			}
277844c821525778c5d2e81da293195d5d589e8ad845Thomas Klein		}
277944c821525778c5d2e81da293195d5d589e8ad845Thomas Klein
278044c821525778c5d2e81da293195d5d589e8ad845Thomas Klein	clear_bit(__EHEA_STOP_XFER, &ehea_driver_flags);
278144c821525778c5d2e81da293195d5d589e8ad845Thomas Klein
278244c821525778c5d2e81da293195d5d589e8ad845Thomas Klein	list_for_each_entry(adapter, &adapter_list, list)
278344c821525778c5d2e81da293195d5d589e8ad845Thomas Klein		if (adapter->active_ports) {
278444c821525778c5d2e81da293195d5d589e8ad845Thomas Klein			/* Register new memory region */
278544c821525778c5d2e81da293195d5d589e8ad845Thomas Klein			ret = ehea_reg_kernel_mr(adapter, &adapter->mr);
278644c821525778c5d2e81da293195d5d589e8ad845Thomas Klein			if (ret) {
27878c4877a4128e7931077b024a891a4b284d8756a3Joe Perches				pr_err("register MR failed - driver inoperable!\n");
278844c821525778c5d2e81da293195d5d589e8ad845Thomas Klein				goto out;
278944c821525778c5d2e81da293195d5d589e8ad845Thomas Klein			}
279044c821525778c5d2e81da293195d5d589e8ad845Thomas Klein
279144c821525778c5d2e81da293195d5d589e8ad845Thomas Klein			/* Restart all ports */
279244c821525778c5d2e81da293195d5d589e8ad845Thomas Klein			for (i = 0; i < EHEA_MAX_PORTS; i++) {
279344c821525778c5d2e81da293195d5d589e8ad845Thomas Klein				struct ehea_port *port = adapter->port[i];
279444c821525778c5d2e81da293195d5d589e8ad845Thomas Klein
279544c821525778c5d2e81da293195d5d589e8ad845Thomas Klein				if (port) {
279644c821525778c5d2e81da293195d5d589e8ad845Thomas Klein					struct net_device *dev = port->netdev;
279744c821525778c5d2e81da293195d5d589e8ad845Thomas Klein
279844c821525778c5d2e81da293195d5d589e8ad845Thomas Klein					if (dev->flags & IFF_UP) {
2799a5af6ad3a0d4f5c6d0a3535d46fc1b26eeff0816Daniel Walker						mutex_lock(&port->port_lock);
28002c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann						ret = ehea_restart_qps(dev);
28016f4d6dc167a001267eeff18bdea0ce3e9108c662Breno Leitao						if (!ret) {
28026f4d6dc167a001267eeff18bdea0ce3e9108c662Breno Leitao							check_sqs(port);
28036f4d6dc167a001267eeff18bdea0ce3e9108c662Breno Leitao							port_napi_enable(port);
2804b95644685d530de5e9f9658bd8087e50840b831dAnton Blanchard							netif_tx_wake_all_queues(dev);
28056f4d6dc167a001267eeff18bdea0ce3e9108c662Breno Leitao						} else {
28066f4d6dc167a001267eeff18bdea0ce3e9108c662Breno Leitao							netdev_err(dev, "Unable to restart QPS\n");
28076f4d6dc167a001267eeff18bdea0ce3e9108c662Breno Leitao						}
2808a5af6ad3a0d4f5c6d0a3535d46fc1b26eeff0816Daniel Walker						mutex_unlock(&port->port_lock);
280944c821525778c5d2e81da293195d5d589e8ad845Thomas Klein					}
281044c821525778c5d2e81da293195d5d589e8ad845Thomas Klein				}
281144c821525778c5d2e81da293195d5d589e8ad845Thomas Klein			}
281244c821525778c5d2e81da293195d5d589e8ad845Thomas Klein		}
28138c4877a4128e7931077b024a891a4b284d8756a3Joe Perches	pr_info("re-initializing driver complete\n");
281444c821525778c5d2e81da293195d5d589e8ad845Thomas Kleinout:
281544c821525778c5d2e81da293195d5d589e8ad845Thomas Klein	return;
281644c821525778c5d2e81da293195d5d589e8ad845Thomas Klein}
281744c821525778c5d2e81da293195d5d589e8ad845Thomas Klein
28187a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic void ehea_tx_watchdog(struct net_device *dev)
28197a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
28207a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_port *port = netdev_priv(dev);
28217a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
28222c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	if (netif_carrier_ok(dev) &&
28232c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7Jan-Bernd Themann	    !test_bit(__EHEA_STOP_XFER, &ehea_driver_flags))
28242f69ae01c83a94af5dc3c20e8135b974687ed004Jan-Bernd Themann		ehea_schedule_port_reset(port);
28257a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
28267a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
28271886e5d2c694e7fb59434c717e704e7fd8475d2eThadeu Lima de Souza Cascardostatic int ehea_sense_adapter_attr(struct ehea_adapter *adapter)
28287a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
28297a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct hcp_query_ehea *cb;
28307a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	u64 hret;
28317a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int ret;
28327a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
28333faf2693bd6800c2521799f6a9ae174d9f080ed2Thomas Klein	cb = (void *)get_zeroed_page(GFP_KERNEL);
28347a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (!cb) {
28357a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ret = -ENOMEM;
28367a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out;
28377a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
28387a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
28397a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	hret = ehea_h_query_ehea(adapter->handle, cb);
28407a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
28417a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (hret != H_SUCCESS) {
28427a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ret = -EIO;
28437a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out_herr;
28447a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
28457a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
28467a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	adapter->max_mc_mac = cb->max_mc_mac - 1;
28477a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ret = 0;
28487a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
28497a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannout_herr:
28503faf2693bd6800c2521799f6a9ae174d9f080ed2Thomas Klein	free_page((unsigned long)cb);
28517a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannout:
28527a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return ret;
28537a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
28547a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
28551886e5d2c694e7fb59434c717e704e7fd8475d2eThadeu Lima de Souza Cascardostatic int ehea_get_jumboframe_status(struct ehea_port *port, int *jumbo)
28567a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
28577a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct hcp_ehea_port_cb4 *cb4;
28581acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	u64 hret;
28591acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	int ret = 0;
28607a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
28611acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	*jumbo = 0;
28627a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
28631acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	/* (Try to) enable *jumbo frames */
28643faf2693bd6800c2521799f6a9ae174d9f080ed2Thomas Klein	cb4 = (void *)get_zeroed_page(GFP_KERNEL);
28657a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (!cb4) {
28668c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("no mem for cb4\n");
28671acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann		ret = -ENOMEM;
28681acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann		goto out;
28697a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	} else {
28701acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann		hret = ehea_h_query_ehea_port(port->adapter->handle,
28719c750b7d14301b710c13247f7cc28abd614d9f5cThomas Klein					      port->logical_port_id,
28729c750b7d14301b710c13247f7cc28abd614d9f5cThomas Klein					      H_PORT_CB4,
28739c750b7d14301b710c13247f7cc28abd614d9f5cThomas Klein					      H_PORT_CB4_JUMBO, cb4);
28749c750b7d14301b710c13247f7cc28abd614d9f5cThomas Klein		if (hret == H_SUCCESS) {
28759c750b7d14301b710c13247f7cc28abd614d9f5cThomas Klein			if (cb4->jumbo_frame)
28761acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann				*jumbo = 1;
28779c750b7d14301b710c13247f7cc28abd614d9f5cThomas Klein			else {
28789c750b7d14301b710c13247f7cc28abd614d9f5cThomas Klein				cb4->jumbo_frame = 1;
28791acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann				hret = ehea_h_modify_ehea_port(port->adapter->
28801acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann							       handle,
28819c750b7d14301b710c13247f7cc28abd614d9f5cThomas Klein							       port->
28821acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann							       logical_port_id,
28839c750b7d14301b710c13247f7cc28abd614d9f5cThomas Klein							       H_PORT_CB4,
28849c750b7d14301b710c13247f7cc28abd614d9f5cThomas Klein							       H_PORT_CB4_JUMBO,
28859c750b7d14301b710c13247f7cc28abd614d9f5cThomas Klein							       cb4);
28869c750b7d14301b710c13247f7cc28abd614d9f5cThomas Klein				if (hret == H_SUCCESS)
28871acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann					*jumbo = 1;
28889c750b7d14301b710c13247f7cc28abd614d9f5cThomas Klein			}
28891acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann		} else
28901acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann			ret = -EINVAL;
28911acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
28923faf2693bd6800c2521799f6a9ae174d9f080ed2Thomas Klein		free_page((unsigned long)cb4);
28937a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
28941acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themannout:
28951acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	return ret;
28961acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann}
28971acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
28981acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themannstatic ssize_t ehea_show_port_id(struct device *dev,
28991acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann				 struct device_attribute *attr, char *buf)
29001acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann{
29011acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	struct ehea_port *port = container_of(dev, struct ehea_port, ofdev.dev);
2902a8e34fda798861d0f3f12c2739c1bec258be8bedJan-Bernd Themann	return sprintf(buf, "%d", port->logical_port_id);
29031acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann}
29041acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
29051acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themannstatic DEVICE_ATTR(log_port_id, S_IRUSR | S_IRGRP | S_IROTH, ehea_show_port_id,
29061acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann		   NULL);
29071acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
29081acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themannstatic void __devinit logical_port_release(struct device *dev)
29091acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann{
29101acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	struct ehea_port *port = container_of(dev, struct ehea_port, ofdev.dev);
291161c7a080a5a061c976988fd4b844dfb468dda255Grant Likely	of_node_put(port->ofdev.dev.of_node);
29121acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann}
29131acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
29141acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themannstatic struct device *ehea_register_port(struct ehea_port *port,
29151acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann					 struct device_node *dn)
29161acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann{
29171acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	int ret;
29181acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
291961c7a080a5a061c976988fd4b844dfb468dda255Grant Likely	port->ofdev.dev.of_node = of_node_get(dn);
29206b08f3ae8eec27a9e557468a48540bc64fd4a524Joachim Fenkes	port->ofdev.dev.parent = &port->adapter->ofdev->dev;
2921d1dea38d54311f6b3dd37ce485e794bd133e3593Thomas Klein	port->ofdev.dev.bus = &ibmebus_bus_type;
29221acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
2923db1d7bf70f42124f73675fca62fe32f3ab1111b4Kay Sievers	dev_set_name(&port->ofdev.dev, "port%d", port_name_cnt++);
29241acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	port->ofdev.dev.release = logical_port_release;
29251acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
29261acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	ret = of_device_register(&port->ofdev);
29271acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	if (ret) {
29288c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("failed to register device. ret=%d\n", ret);
29291acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann		goto out;
29301acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	}
29311acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
29321acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	ret = device_create_file(&port->ofdev.dev, &dev_attr_log_port_id);
2933d1d25aaba85fd24ab18b0a4d22f19be02aac65c9Jan-Bernd Themann	if (ret) {
29348c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("failed to register attributes, ret=%d\n", ret);
29351acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann		goto out_unreg_of_dev;
29361acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	}
2937e542aa6bd50ba163253e60ba8e7e51c0d56162a7Jan-Bernd Themann
29381acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	return &port->ofdev.dev;
29391acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
29401acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themannout_unreg_of_dev:
29411acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	of_device_unregister(&port->ofdev);
29421acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themannout:
29431acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	return NULL;
29441acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann}
29451acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
29461acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themannstatic void ehea_unregister_port(struct ehea_port *port)
29471acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann{
29481acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	device_remove_file(&port->ofdev.dev, &dev_attr_log_port_id);
29491acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	of_device_unregister(&port->ofdev);
29501acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann}
29511acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
2952086c1b2c52f03d128d1a6db47f8736c56e915043Thomas Kleinstatic const struct net_device_ops ehea_netdev_ops = {
2953086c1b2c52f03d128d1a6db47f8736c56e915043Thomas Klein	.ndo_open		= ehea_open,
2954086c1b2c52f03d128d1a6db47f8736c56e915043Thomas Klein	.ndo_stop		= ehea_stop,
2955086c1b2c52f03d128d1a6db47f8736c56e915043Thomas Klein	.ndo_start_xmit		= ehea_start_xmit,
2956086c1b2c52f03d128d1a6db47f8736c56e915043Thomas Klein#ifdef CONFIG_NET_POLL_CONTROLLER
2957086c1b2c52f03d128d1a6db47f8736c56e915043Thomas Klein	.ndo_poll_controller	= ehea_netpoll,
2958086c1b2c52f03d128d1a6db47f8736c56e915043Thomas Klein#endif
2959239c562c94dcdd2aeb3d0c0e604627dec043183eAnton Blanchard	.ndo_get_stats64	= ehea_get_stats64,
2960086c1b2c52f03d128d1a6db47f8736c56e915043Thomas Klein	.ndo_set_mac_address	= ehea_set_mac_addr,
2961240c102d9c54fee7fdc87a4ef2fabc7eb539e00aBen Hutchings	.ndo_validate_addr	= eth_validate_addr,
2962afc4b13df143122f99a0eb10bfefb216c2806de0Jiri Pirko	.ndo_set_rx_mode	= ehea_set_multicast_list,
2963086c1b2c52f03d128d1a6db47f8736c56e915043Thomas Klein	.ndo_change_mtu		= ehea_change_mtu,
2964086c1b2c52f03d128d1a6db47f8736c56e915043Thomas Klein	.ndo_vlan_rx_add_vid	= ehea_vlan_rx_add_vid,
296532e8f9a8d9bd52b59b512f8e5177b08e8edfd58bAlexander Beregalov	.ndo_vlan_rx_kill_vid	= ehea_vlan_rx_kill_vid,
296632e8f9a8d9bd52b59b512f8e5177b08e8edfd58bAlexander Beregalov	.ndo_tx_timeout		= ehea_tx_watchdog,
2967086c1b2c52f03d128d1a6db47f8736c56e915043Thomas Klein};
2968086c1b2c52f03d128d1a6db47f8736c56e915043Thomas Klein
29691886e5d2c694e7fb59434c717e704e7fd8475d2eThadeu Lima de Souza Cascardostatic struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
29701acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann					 u32 logical_port_id,
29711acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann					 struct device_node *dn)
29721acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann{
29731acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	int ret;
29741acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	struct net_device *dev;
29751acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	struct ehea_port *port;
29761acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	struct device *port_dev;
29771acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	int jumbo;
29781acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
29791acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	/* allocate memory for the port structures */
2980b95644685d530de5e9f9658bd8087e50840b831dAnton Blanchard	dev = alloc_etherdev_mq(sizeof(struct ehea_port), EHEA_MAX_PORT_RES);
29811acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
29821acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	if (!dev) {
29838c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("no mem for net_device\n");
29841acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann		ret = -ENOMEM;
29851acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann		goto out_err;
29861acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	}
29871acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
29881acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	port = netdev_priv(dev);
29891acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
2990a5af6ad3a0d4f5c6d0a3535d46fc1b26eeff0816Daniel Walker	mutex_init(&port->port_lock);
29911acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	port->state = EHEA_PORT_DOWN;
29921acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	port->sig_comp_iv = sq_entries / 10;
29931acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
29941acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	port->adapter = adapter;
29951acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	port->netdev = dev;
29961acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	port->logical_port_id = logical_port_id;
29971acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
29981acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	port->msg_enable = netif_msg_init(msg_level, EHEA_MSG_DEFAULT);
29991acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
30001acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	port->mc_list = kzalloc(sizeof(struct ehea_mc_list), GFP_KERNEL);
30011acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	if (!port->mc_list) {
30021acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann		ret = -ENOMEM;
30031acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann		goto out_free_ethdev;
30041acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	}
30051acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
30061acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	INIT_LIST_HEAD(&port->mc_list->list);
30071acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
30081acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	ret = ehea_sense_port_attr(port);
30091acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	if (ret)
30101acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann		goto out_free_mc_list;
30111acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
3012b95644685d530de5e9f9658bd8087e50840b831dAnton Blanchard	netif_set_real_num_rx_queues(dev, port->num_def_qps);
3013723f28e49c9f8578b418dfd1ec8c7b9cc13e2b63Anton Blanchard	netif_set_real_num_tx_queues(dev, port->num_def_qps);
3014b95644685d530de5e9f9658bd8087e50840b831dAnton Blanchard
30151acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	port_dev = ehea_register_port(port, dn);
30161acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	if (!port_dev)
30171acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann		goto out_free_mc_list;
30181acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
30191acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	SET_NETDEV_DEV(dev, port_dev);
30207a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
30217a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	/* initialize net_device structure */
30227a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	memcpy(dev->dev_addr, &port->mac_addr, ETH_ALEN);
30237a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
3024086c1b2c52f03d128d1a6db47f8736c56e915043Thomas Klein	dev->netdev_ops = &ehea_netdev_ops;
3025086c1b2c52f03d128d1a6db47f8736c56e915043Thomas Klein	ehea_set_ethtool_ops(dev);
3026086c1b2c52f03d128d1a6db47f8736c56e915043Thomas Klein
3027d695c335f9165cb73f9389479cce755e8207b5f4Anton Blanchard	dev->hw_features = NETIF_F_SG | NETIF_F_TSO
3028f4786a96252b97f6f05cd42ea7fe6e967048bfa3Michał Mirosław		      | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX | NETIF_F_LRO;
30297a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO
3030dc01c447123b489af7b4d0c58a15abcec36a40e6Thomas Klein		      | NETIF_F_HIGHDMA | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX
30317a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		      | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER
30323f7947b9f069c125ffdedc75ac9c4e3101fc2c6aAnton Blanchard		      | NETIF_F_RXCSUM;
3033076f203258c5b8f07226ba41c4643d958785bb07Anton Blanchard	dev->vlan_features = NETIF_F_SG | NETIF_F_TSO | NETIF_F_HIGHDMA |
3034076f203258c5b8f07226ba41c4643d958785bb07Anton Blanchard			NETIF_F_IP_CSUM;
30357a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	dev->watchdog_timeo = EHEA_WATCH_DOG_TIMEOUT;
30367a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
3037c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells	INIT_WORK(&port->reset_task, ehea_reset_port);
30382aefcad8666e0c7c1aff51c0dacc164a1b681895brenohl@br.ibm.com	INIT_DELAYED_WORK(&port->stats_work, ehea_update_stats);
30397a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
304021ccc7936dac5ca9b3e2838bbc112a60f34e18b3Anton Blanchard	init_waitqueue_head(&port->swqe_avail_wq);
304121ccc7936dac5ca9b3e2838bbc112a60f34e18b3Anton Blanchard	init_waitqueue_head(&port->restart_wq);
304221ccc7936dac5ca9b3e2838bbc112a60f34e18b3Anton Blanchard
30432aefcad8666e0c7c1aff51c0dacc164a1b681895brenohl@br.ibm.com	memset(&port->stats, 0, sizeof(struct net_device_stats));
30447a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ret = register_netdev(dev);
30457a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (ret) {
30468c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("register_netdev failed. ret=%d\n", ret);
304721eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein		goto out_unreg_port;
30487a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
30497a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
30501acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	ret = ehea_get_jumboframe_status(port, &jumbo);
3051e542aa6bd50ba163253e60ba8e7e51c0d56162a7Jan-Bernd Themann	if (ret)
30528c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		netdev_err(dev, "failed determining jumbo frame status\n");
30531acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
30548c4877a4128e7931077b024a891a4b284d8756a3Joe Perches	netdev_info(dev, "Jumbo frames are %sabled\n",
30558c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		    jumbo == 1 ? "en" : "dis");
30569c750b7d14301b710c13247f7cc28abd614d9f5cThomas Klein
305744c821525778c5d2e81da293195d5d589e8ad845Thomas Klein	adapter->active_ports++;
305844c821525778c5d2e81da293195d5d589e8ad845Thomas Klein
30591acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	return port;
30607a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
30611acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themannout_unreg_port:
30621acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	ehea_unregister_port(port);
30631acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
30641acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themannout_free_mc_list:
30657a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	kfree(port->mc_list);
30661acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
30671acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themannout_free_ethdev:
30681acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	free_netdev(dev);
30691acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
30701acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themannout_err:
30718c4877a4128e7931077b024a891a4b284d8756a3Joe Perches	pr_err("setting up logical port with id=%d failed, ret=%d\n",
30728c4877a4128e7931077b024a891a4b284d8756a3Joe Perches	       logical_port_id, ret);
30731acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	return NULL;
30741acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann}
30751acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
30761acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themannstatic void ehea_shutdown_single_port(struct ehea_port *port)
30771acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann{
30787fb1c2ac8ecaf0883f2fcb38dfc9ec2d15cee11dBrian King	struct ehea_adapter *adapter = port->adapter;
3079f5c35cc191afd08d660e6db0fecc9f431dc8f273Tejun Heo
3080f5c35cc191afd08d660e6db0fecc9f431dc8f273Tejun Heo	cancel_work_sync(&port->reset_task);
30812aefcad8666e0c7c1aff51c0dacc164a1b681895brenohl@br.ibm.com	cancel_delayed_work_sync(&port->stats_work);
30821acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	unregister_netdev(port->netdev);
30831acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	ehea_unregister_port(port);
30841acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	kfree(port->mc_list);
30851acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	free_netdev(port->netdev);
30867fb1c2ac8ecaf0883f2fcb38dfc9ec2d15cee11dBrian King	adapter->active_ports--;
30877a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
30887a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
30897a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic int ehea_setup_ports(struct ehea_adapter *adapter)
30907a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
30911acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	struct device_node *lhea_dn;
30921acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	struct device_node *eth_dn = NULL;
3093d1d25aaba85fd24ab18b0a4d22f19be02aac65c9Jan-Bernd Themann
30949f9a3b8a06b7965335bfe5162c1a50e4d9c3859bStephen Rothwell	const u32 *dn_log_port_id;
30951acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	int i = 0;
30961acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
309761c7a080a5a061c976988fd4b844dfb468dda255Grant Likely	lhea_dn = adapter->ofdev->dev.of_node;
30981eef4e04c95fb52a1a3885c8f53a822206fc9aa5Jan-Bernd Themann	while ((eth_dn = of_get_next_child(lhea_dn, eth_dn))) {
3099e542aa6bd50ba163253e60ba8e7e51c0d56162a7Jan-Bernd Themann
310040cd3a4564ed6b7bc0279430120ca0e9b83cf486Stephen Rothwell		dn_log_port_id = of_get_property(eth_dn, "ibm,hea-port-no",
3101d1d25aaba85fd24ab18b0a4d22f19be02aac65c9Jan-Bernd Themann						 NULL);
31021acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann		if (!dn_log_port_id) {
31038c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			pr_err("bad device node: eth_dn name=%s\n",
31048c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			       eth_dn->full_name);
31051acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann			continue;
31061acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann		}
31077a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
31081211bb6dcd935c48e864d4eecbf8a684e982419aThomas Klein		if (ehea_add_adapter_mr(adapter)) {
31098c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			pr_err("creating MR failed\n");
31101211bb6dcd935c48e864d4eecbf8a684e982419aThomas Klein			of_node_put(eth_dn);
31111211bb6dcd935c48e864d4eecbf8a684e982419aThomas Klein			return -EIO;
31121211bb6dcd935c48e864d4eecbf8a684e982419aThomas Klein		}
31131211bb6dcd935c48e864d4eecbf8a684e982419aThomas Klein
31141acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann		adapter->port[i] = ehea_setup_single_port(adapter,
31151acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann							  *dn_log_port_id,
31161acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann							  eth_dn);
31177a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		if (adapter->port[i])
31188c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			netdev_info(adapter->port[i]->netdev,
31198c4877a4128e7931077b024a891a4b284d8756a3Joe Perches				    "logical port id #%d\n", *dn_log_port_id);
31201211bb6dcd935c48e864d4eecbf8a684e982419aThomas Klein		else
31211211bb6dcd935c48e864d4eecbf8a684e982419aThomas Klein			ehea_remove_adapter_mr(adapter);
31221211bb6dcd935c48e864d4eecbf8a684e982419aThomas Klein
31231acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann		i++;
3124ee289b6440c3b0ccb9459495783e8c299bec6604Joe Perches	}
31251211bb6dcd935c48e864d4eecbf8a684e982419aThomas Klein	return 0;
31261acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann}
31271acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
3128e542aa6bd50ba163253e60ba8e7e51c0d56162a7Jan-Bernd Themannstatic struct device_node *ehea_get_eth_dn(struct ehea_adapter *adapter,
3129e542aa6bd50ba163253e60ba8e7e51c0d56162a7Jan-Bernd Themann					   u32 logical_port_id)
31301acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann{
31311acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	struct device_node *lhea_dn;
31321acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	struct device_node *eth_dn = NULL;
31339f9a3b8a06b7965335bfe5162c1a50e4d9c3859bStephen Rothwell	const u32 *dn_log_port_id;
31341acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
313561c7a080a5a061c976988fd4b844dfb468dda255Grant Likely	lhea_dn = adapter->ofdev->dev.of_node;
31361eef4e04c95fb52a1a3885c8f53a822206fc9aa5Jan-Bernd Themann	while ((eth_dn = of_get_next_child(lhea_dn, eth_dn))) {
3137e542aa6bd50ba163253e60ba8e7e51c0d56162a7Jan-Bernd Themann
313840cd3a4564ed6b7bc0279430120ca0e9b83cf486Stephen Rothwell		dn_log_port_id = of_get_property(eth_dn, "ibm,hea-port-no",
3139d1d25aaba85fd24ab18b0a4d22f19be02aac65c9Jan-Bernd Themann						 NULL);
31401acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann		if (dn_log_port_id)
31411acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann			if (*dn_log_port_id == logical_port_id)
31421acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann				return eth_dn;
3143ee289b6440c3b0ccb9459495783e8c299bec6604Joe Perches	}
31441acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
31451acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	return NULL;
31461acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann}
31471acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
31481acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themannstatic ssize_t ehea_probe_port(struct device *dev,
31491acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann			       struct device_attribute *attr,
31501acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann			       const char *buf, size_t count)
31511acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann{
3152c7ae011dc8306d982c25fb4f679752e790a08dc4Greg Kroah-Hartman	struct ehea_adapter *adapter = dev_get_drvdata(dev);
31531acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	struct ehea_port *port;
31541acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	struct device_node *eth_dn = NULL;
31551acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	int i;
31561acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
31571acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	u32 logical_port_id;
31581acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
3159a8e34fda798861d0f3f12c2739c1bec258be8bedJan-Bernd Themann	sscanf(buf, "%d", &logical_port_id);
31601acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
31611acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	port = ehea_get_port(adapter, logical_port_id);
31621acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
31631acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	if (port) {
31648c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		netdev_info(port->netdev, "adding port with logical port id=%d failed: port already configured\n",
31658c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			    logical_port_id);
31661acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann		return -EINVAL;
31677a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
3168e542aa6bd50ba163253e60ba8e7e51c0d56162a7Jan-Bernd Themann
31691acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	eth_dn = ehea_get_eth_dn(adapter, logical_port_id);
31707a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
31711acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	if (!eth_dn) {
31728c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_info("no logical port with id %d found\n", logical_port_id);
31731acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann		return -EINVAL;
31741acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	}
3175e542aa6bd50ba163253e60ba8e7e51c0d56162a7Jan-Bernd Themann
31761211bb6dcd935c48e864d4eecbf8a684e982419aThomas Klein	if (ehea_add_adapter_mr(adapter)) {
31778c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("creating MR failed\n");
31781211bb6dcd935c48e864d4eecbf8a684e982419aThomas Klein		return -EIO;
31791211bb6dcd935c48e864d4eecbf8a684e982419aThomas Klein	}
31801211bb6dcd935c48e864d4eecbf8a684e982419aThomas Klein
31811acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	port = ehea_setup_single_port(adapter, logical_port_id, eth_dn);
31827a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
31831eef4e04c95fb52a1a3885c8f53a822206fc9aa5Jan-Bernd Themann	of_node_put(eth_dn);
31841eef4e04c95fb52a1a3885c8f53a822206fc9aa5Jan-Bernd Themann
31851acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	if (port) {
3186508d2b5d261abbd7fb728092c5025c5063060c04Doug Maxey		for (i = 0; i < EHEA_MAX_PORTS; i++)
31871acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann			if (!adapter->port[i]) {
31881acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann				adapter->port[i] = port;
31891acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann				break;
31901acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann			}
31917a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
31928c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		netdev_info(port->netdev, "added: (logical port id=%d)\n",
31938c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			    logical_port_id);
31941211bb6dcd935c48e864d4eecbf8a684e982419aThomas Klein	} else {
31951211bb6dcd935c48e864d4eecbf8a684e982419aThomas Klein		ehea_remove_adapter_mr(adapter);
3196e542aa6bd50ba163253e60ba8e7e51c0d56162a7Jan-Bernd Themann		return -EIO;
31971211bb6dcd935c48e864d4eecbf8a684e982419aThomas Klein	}
31987a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
31991acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	return (ssize_t) count;
32001acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann}
32011acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
32021acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themannstatic ssize_t ehea_remove_port(struct device *dev,
32031acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann				struct device_attribute *attr,
32041acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann				const char *buf, size_t count)
32051acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann{
3206c7ae011dc8306d982c25fb4f679752e790a08dc4Greg Kroah-Hartman	struct ehea_adapter *adapter = dev_get_drvdata(dev);
32071acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	struct ehea_port *port;
32081acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	int i;
32091acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	u32 logical_port_id;
32101acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
3211a8e34fda798861d0f3f12c2739c1bec258be8bedJan-Bernd Themann	sscanf(buf, "%d", &logical_port_id);
32121acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
32131acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	port = ehea_get_port(adapter, logical_port_id);
32141acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
32151acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	if (port) {
32168c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		netdev_info(port->netdev, "removed: (logical port id=%d)\n",
32178c4877a4128e7931077b024a891a4b284d8756a3Joe Perches			    logical_port_id);
32181acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
32191acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann		ehea_shutdown_single_port(port);
32201acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
3221508d2b5d261abbd7fb728092c5025c5063060c04Doug Maxey		for (i = 0; i < EHEA_MAX_PORTS; i++)
32221acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann			if (adapter->port[i] == port) {
32231acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann				adapter->port[i] = NULL;
32241acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann				break;
32251acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann			}
32261acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	} else {
32278c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("removing port with logical port id=%d failed. port not configured.\n",
32288c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		       logical_port_id);
32291acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann		return -EINVAL;
32301acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	}
32311acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
32321211bb6dcd935c48e864d4eecbf8a684e982419aThomas Klein	ehea_remove_adapter_mr(adapter);
32331211bb6dcd935c48e864d4eecbf8a684e982419aThomas Klein
32341acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	return (ssize_t) count;
32351acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann}
32361acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
32371acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themannstatic DEVICE_ATTR(probe_port, S_IWUSR, NULL, ehea_probe_port);
32381acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themannstatic DEVICE_ATTR(remove_port, S_IWUSR, NULL, ehea_remove_port);
32391acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
32401886e5d2c694e7fb59434c717e704e7fd8475d2eThadeu Lima de Souza Cascardostatic int ehea_create_device_sysfs(struct platform_device *dev)
32411acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann{
32426b08f3ae8eec27a9e557468a48540bc64fd4a524Joachim Fenkes	int ret = device_create_file(&dev->dev, &dev_attr_probe_port);
32431acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	if (ret)
32441acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann		goto out;
32451acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
32466b08f3ae8eec27a9e557468a48540bc64fd4a524Joachim Fenkes	ret = device_create_file(&dev->dev, &dev_attr_remove_port);
32471acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themannout:
32487a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return ret;
32497a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
32507a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
32511886e5d2c694e7fb59434c717e704e7fd8475d2eThadeu Lima de Souza Cascardostatic void ehea_remove_device_sysfs(struct platform_device *dev)
32521acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann{
32536b08f3ae8eec27a9e557468a48540bc64fd4a524Joachim Fenkes	device_remove_file(&dev->dev, &dev_attr_probe_port);
32546b08f3ae8eec27a9e557468a48540bc64fd4a524Joachim Fenkes	device_remove_file(&dev->dev, &dev_attr_remove_port);
32551acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann}
32561acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
32572dc11581376829303b98eadb2de253bee065a56aGrant Likelystatic int __devinit ehea_probe_adapter(struct platform_device *dev,
32581acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann					const struct of_device_id *id)
32597a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
32607a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	struct ehea_adapter *adapter;
32619f9a3b8a06b7965335bfe5162c1a50e4d9c3859bStephen Rothwell	const u64 *adapter_handle;
32627a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int ret;
32637a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
326461c7a080a5a061c976988fd4b844dfb468dda255Grant Likely	if (!dev || !dev->dev.of_node) {
32658c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("Invalid ibmebus device probed\n");
32661eef4e04c95fb52a1a3885c8f53a822206fc9aa5Jan-Bernd Themann		return -EINVAL;
32671eef4e04c95fb52a1a3885c8f53a822206fc9aa5Jan-Bernd Themann	}
32681eef4e04c95fb52a1a3885c8f53a822206fc9aa5Jan-Bernd Themann
32697a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	adapter = kzalloc(sizeof(*adapter), GFP_KERNEL);
32707a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (!adapter) {
32717a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ret = -ENOMEM;
32726b08f3ae8eec27a9e557468a48540bc64fd4a524Joachim Fenkes		dev_err(&dev->dev, "no mem for ehea_adapter\n");
32737a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out;
32747a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
32757a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
327644c821525778c5d2e81da293195d5d589e8ad845Thomas Klein	list_add(&adapter->list, &adapter_list);
327744c821525778c5d2e81da293195d5d589e8ad845Thomas Klein
32786b08f3ae8eec27a9e557468a48540bc64fd4a524Joachim Fenkes	adapter->ofdev = dev;
32791acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
328061c7a080a5a061c976988fd4b844dfb468dda255Grant Likely	adapter_handle = of_get_property(dev->dev.of_node, "ibm,hea-handle",
3281d1d25aaba85fd24ab18b0a4d22f19be02aac65c9Jan-Bernd Themann					 NULL);
3282061bf3cdba753ae7b52fba8cc324d81adac77696Thomas Klein	if (adapter_handle)
3283061bf3cdba753ae7b52fba8cc324d81adac77696Thomas Klein		adapter->handle = *adapter_handle;
3284061bf3cdba753ae7b52fba8cc324d81adac77696Thomas Klein
3285061bf3cdba753ae7b52fba8cc324d81adac77696Thomas Klein	if (!adapter->handle) {
32866b08f3ae8eec27a9e557468a48540bc64fd4a524Joachim Fenkes		dev_err(&dev->dev, "failed getting handle for adapter"
328761c7a080a5a061c976988fd4b844dfb468dda255Grant Likely			" '%s'\n", dev->dev.of_node->full_name);
32887a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ret = -ENODEV;
32897a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out_free_ad;
32907a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
32917a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
32927a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	adapter->pd = EHEA_PD_ID;
32937a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
3294c7ae011dc8306d982c25fb4f679752e790a08dc4Greg Kroah-Hartman	dev_set_drvdata(&dev->dev, adapter);
32957a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
32967a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
32977a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	/* initialize adapter and ports */
32987a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	/* get adapter properties */
32997a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ret = ehea_sense_adapter_attr(adapter);
33007a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (ret) {
3301898eb71cb17644964c5895fb190e79e3d0c49679Joe Perches		dev_err(&dev->dev, "sense_adapter_attr failed: %d\n", ret);
33021211bb6dcd935c48e864d4eecbf8a684e982419aThomas Klein		goto out_free_ad;
33037a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
33047a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
33057a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	adapter->neq = ehea_create_eq(adapter,
33067a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				      EHEA_NEQ, EHEA_MAX_ENTRIES_EQ, 1);
33077a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (!adapter->neq) {
33081eef4e04c95fb52a1a3885c8f53a822206fc9aa5Jan-Bernd Themann		ret = -EIO;
3309898eb71cb17644964c5895fb190e79e3d0c49679Joe Perches		dev_err(&dev->dev, "NEQ creation failed\n");
33101211bb6dcd935c48e864d4eecbf8a684e982419aThomas Klein		goto out_free_ad;
33117a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
33127a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
33137a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	tasklet_init(&adapter->neq_tasklet, ehea_neq_tasklet,
33147a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		     (unsigned long)adapter);
33157a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
33166b08f3ae8eec27a9e557468a48540bc64fd4a524Joachim Fenkes	ret = ibmebus_request_irq(adapter->neq->attr.ist1,
331738515e908ba3a9c467ad3bf347b9bce69216df94Thomas Gleixner				  ehea_interrupt_neq, IRQF_DISABLED,
33187a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann				  "ehea_neq", adapter);
33197a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (ret) {
3320898eb71cb17644964c5895fb190e79e3d0c49679Joe Perches		dev_err(&dev->dev, "requesting NEQ IRQ failed\n");
33217a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out_kill_eq;
33227a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
33237a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
33241eef4e04c95fb52a1a3885c8f53a822206fc9aa5Jan-Bernd Themann	ret = ehea_create_device_sysfs(dev);
33251eef4e04c95fb52a1a3885c8f53a822206fc9aa5Jan-Bernd Themann	if (ret)
33263bf76b81608479a10077bd6b55972d40db782067Jan-Bernd Themann		goto out_free_irq;
33271acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
33287a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ret = ehea_setup_ports(adapter);
33297a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (ret) {
3330898eb71cb17644964c5895fb190e79e3d0c49679Joe Perches		dev_err(&dev->dev, "setup_ports failed\n");
33311acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann		goto out_rem_dev_sysfs;
33327a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
33337a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
33347a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ret = 0;
33357a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	goto out;
33367a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
33371acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themannout_rem_dev_sysfs:
33381acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	ehea_remove_device_sysfs(dev);
33391acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
33407a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannout_free_irq:
33416b08f3ae8eec27a9e557468a48540bc64fd4a524Joachim Fenkes	ibmebus_free_irq(adapter->neq->attr.ist1, adapter);
33427a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
33437a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannout_kill_eq:
33447a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ehea_destroy_eq(adapter->neq);
33457a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
33467a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannout_free_ad:
334751621fbdb1ea8709ab67170b54e71be6d9fa29adHannes Hering	list_del(&adapter->list);
33487a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	kfree(adapter);
334921eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
33507a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannout:
335121eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	ehea_update_firmware_handles();
335252e21b1bd96444c452f6eab7dc438a8a898aa14aJan-Bernd Themann
33537a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return ret;
33547a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
33557a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
33562dc11581376829303b98eadb2de253bee065a56aGrant Likelystatic int __devexit ehea_remove(struct platform_device *dev)
33577a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
3358c7ae011dc8306d982c25fb4f679752e790a08dc4Greg Kroah-Hartman	struct ehea_adapter *adapter = dev_get_drvdata(&dev->dev);
33597a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int i;
33607a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
33611acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	for (i = 0; i < EHEA_MAX_PORTS; i++)
33627a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		if (adapter->port[i]) {
33637a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			ehea_shutdown_single_port(adapter->port[i]);
33647a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann			adapter->port[i] = NULL;
33657a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		}
33661acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
33671acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann	ehea_remove_device_sysfs(dev);
33681acf2318dd136edfbfa30f1f33b43f69f2e2ec6cJan-Bernd Themann
33696b08f3ae8eec27a9e557468a48540bc64fd4a524Joachim Fenkes	ibmebus_free_irq(adapter->neq->attr.ist1, adapter);
3370d4150a2731615de5cd4527a23435aaa7396c63c6Thomas Klein	tasklet_kill(&adapter->neq_tasklet);
33717a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
33727a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ehea_destroy_eq(adapter->neq);
33731211bb6dcd935c48e864d4eecbf8a684e982419aThomas Klein	ehea_remove_adapter_mr(adapter);
337444c821525778c5d2e81da293195d5d589e8ad845Thomas Klein	list_del(&adapter->list);
33757a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	kfree(adapter);
337644c821525778c5d2e81da293195d5d589e8ad845Thomas Klein
337721eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	ehea_update_firmware_handles();
337821eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
33797a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return 0;
33807a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
33817a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
33821886e5d2c694e7fb59434c717e704e7fd8475d2eThadeu Lima de Souza Cascardostatic void ehea_crash_handler(void)
338321eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein{
338421eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	int i;
338521eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
338621eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	if (ehea_fw_handles.arr)
338721eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein		for (i = 0; i < ehea_fw_handles.num_entries; i++)
338821eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein			ehea_h_free_resource(ehea_fw_handles.arr[i].adh,
338921eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein					     ehea_fw_handles.arr[i].fwh,
339021eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein					     FORCE_FREE);
339121eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
339221eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	if (ehea_bcmc_regs.arr)
339321eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein		for (i = 0; i < ehea_bcmc_regs.num_entries; i++)
339421eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein			ehea_h_reg_dereg_bcmc(ehea_bcmc_regs.arr[i].adh,
339521eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein					      ehea_bcmc_regs.arr[i].port_id,
339621eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein					      ehea_bcmc_regs.arr[i].reg_type,
339721eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein					      ehea_bcmc_regs.arr[i].macaddr,
339821eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein					      0, H_DEREG_BCMC);
339921eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein}
340021eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
340148cfb14f8b89d4d5b3df6c16f08b258686fb12adHannes Heringstatic int ehea_mem_notifier(struct notifier_block *nb,
340248cfb14f8b89d4d5b3df6c16f08b258686fb12adHannes Hering                             unsigned long action, void *data)
340348cfb14f8b89d4d5b3df6c16f08b258686fb12adHannes Hering{
3404a7c561f2e32f98b477f5fe670b3f294be6b1eae2Thomas Klein	int ret = NOTIFY_BAD;
3405d4f12daf7ba4efc506c377a9591ecdb692641fe5Hannes Hering	struct memory_notify *arg = data;
3406a7c561f2e32f98b477f5fe670b3f294be6b1eae2Thomas Klein
3407099473c16bac7b936994bc95b5fd96f36397e1adJan-Bernd Themann	mutex_lock(&dlpar_mem_lock);
3408a7c561f2e32f98b477f5fe670b3f294be6b1eae2Thomas Klein
340948cfb14f8b89d4d5b3df6c16f08b258686fb12adHannes Hering	switch (action) {
3410d4f12daf7ba4efc506c377a9591ecdb692641fe5Hannes Hering	case MEM_CANCEL_OFFLINE:
34118c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_info("memory offlining canceled");
3412d4f12daf7ba4efc506c377a9591ecdb692641fe5Hannes Hering		/* Readd canceled memory block */
3413d4f12daf7ba4efc506c377a9591ecdb692641fe5Hannes Hering	case MEM_ONLINE:
34148c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_info("memory is going online");
34153876732c12cd2b9896e8c3e86fad142112e93569Thomas Klein		set_bit(__EHEA_STOP_XFER, &ehea_driver_flags);
3416d4f12daf7ba4efc506c377a9591ecdb692641fe5Hannes Hering		if (ehea_add_sect_bmap(arg->start_pfn, arg->nr_pages))
3417a7c561f2e32f98b477f5fe670b3f294be6b1eae2Thomas Klein			goto out_unlock;
34183d6b892bcc4c810071e36d8aff25aa171f55f93dTejun Heo		ehea_rereg_mrs();
3419d4f12daf7ba4efc506c377a9591ecdb692641fe5Hannes Hering		break;
3420d4f12daf7ba4efc506c377a9591ecdb692641fe5Hannes Hering	case MEM_GOING_OFFLINE:
34218c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_info("memory is going offline");
34223876732c12cd2b9896e8c3e86fad142112e93569Thomas Klein		set_bit(__EHEA_STOP_XFER, &ehea_driver_flags);
3423d4f12daf7ba4efc506c377a9591ecdb692641fe5Hannes Hering		if (ehea_rem_sect_bmap(arg->start_pfn, arg->nr_pages))
3424a7c561f2e32f98b477f5fe670b3f294be6b1eae2Thomas Klein			goto out_unlock;
34253d6b892bcc4c810071e36d8aff25aa171f55f93dTejun Heo		ehea_rereg_mrs();
342648cfb14f8b89d4d5b3df6c16f08b258686fb12adHannes Hering		break;
342748cfb14f8b89d4d5b3df6c16f08b258686fb12adHannes Hering	default:
342848cfb14f8b89d4d5b3df6c16f08b258686fb12adHannes Hering		break;
342948cfb14f8b89d4d5b3df6c16f08b258686fb12adHannes Hering	}
343052e21b1bd96444c452f6eab7dc438a8a898aa14aJan-Bernd Themann
343152e21b1bd96444c452f6eab7dc438a8a898aa14aJan-Bernd Themann	ehea_update_firmware_handles();
3432a7c561f2e32f98b477f5fe670b3f294be6b1eae2Thomas Klein	ret = NOTIFY_OK;
343352e21b1bd96444c452f6eab7dc438a8a898aa14aJan-Bernd Themann
3434a7c561f2e32f98b477f5fe670b3f294be6b1eae2Thomas Kleinout_unlock:
3435a7c561f2e32f98b477f5fe670b3f294be6b1eae2Thomas Klein	mutex_unlock(&dlpar_mem_lock);
3436a7c561f2e32f98b477f5fe670b3f294be6b1eae2Thomas Klein	return ret;
343748cfb14f8b89d4d5b3df6c16f08b258686fb12adHannes Hering}
343848cfb14f8b89d4d5b3df6c16f08b258686fb12adHannes Hering
343948cfb14f8b89d4d5b3df6c16f08b258686fb12adHannes Heringstatic struct notifier_block ehea_mem_nb = {
344048cfb14f8b89d4d5b3df6c16f08b258686fb12adHannes Hering	.notifier_call = ehea_mem_notifier,
344148cfb14f8b89d4d5b3df6c16f08b258686fb12adHannes Hering};
344248cfb14f8b89d4d5b3df6c16f08b258686fb12adHannes Hering
34432a6f4e4983918b18fe5d3fb364afe33db7139870Jan-Bernd Themannstatic int ehea_reboot_notifier(struct notifier_block *nb,
34442a6f4e4983918b18fe5d3fb364afe33db7139870Jan-Bernd Themann				unsigned long action, void *unused)
34452a6f4e4983918b18fe5d3fb364afe33db7139870Jan-Bernd Themann{
34462a6f4e4983918b18fe5d3fb364afe33db7139870Jan-Bernd Themann	if (action == SYS_RESTART) {
34478c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_info("Reboot: freeing all eHEA resources\n");
34482a6f4e4983918b18fe5d3fb364afe33db7139870Jan-Bernd Themann		ibmebus_unregister_driver(&ehea_driver);
34492a6f4e4983918b18fe5d3fb364afe33db7139870Jan-Bernd Themann	}
34502a6f4e4983918b18fe5d3fb364afe33db7139870Jan-Bernd Themann	return NOTIFY_DONE;
34512a6f4e4983918b18fe5d3fb364afe33db7139870Jan-Bernd Themann}
34522a6f4e4983918b18fe5d3fb364afe33db7139870Jan-Bernd Themann
34532a6f4e4983918b18fe5d3fb364afe33db7139870Jan-Bernd Themannstatic struct notifier_block ehea_reboot_nb = {
3454508d2b5d261abbd7fb728092c5025c5063060c04Doug Maxey	.notifier_call = ehea_reboot_notifier,
34552a6f4e4983918b18fe5d3fb364afe33db7139870Jan-Bernd Themann};
34562a6f4e4983918b18fe5d3fb364afe33db7139870Jan-Bernd Themann
34577a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic int check_module_parm(void)
34587a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
34597a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int ret = 0;
34607a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
34617a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if ((rq1_entries < EHEA_MIN_ENTRIES_QP) ||
34627a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	    (rq1_entries > EHEA_MAX_ENTRIES_RQ1)) {
34638c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_info("Bad parameter: rq1_entries\n");
34647a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ret = -EINVAL;
34657a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
34667a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if ((rq2_entries < EHEA_MIN_ENTRIES_QP) ||
34677a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	    (rq2_entries > EHEA_MAX_ENTRIES_RQ2)) {
34688c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_info("Bad parameter: rq2_entries\n");
34697a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ret = -EINVAL;
34707a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
34717a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if ((rq3_entries < EHEA_MIN_ENTRIES_QP) ||
34727a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	    (rq3_entries > EHEA_MAX_ENTRIES_RQ3)) {
34738c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_info("Bad parameter: rq3_entries\n");
34747a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ret = -EINVAL;
34757a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
34767a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if ((sq_entries < EHEA_MIN_ENTRIES_QP) ||
34777a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	    (sq_entries > EHEA_MAX_ENTRIES_SQ)) {
34788c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_info("Bad parameter: sq_entries\n");
34797a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		ret = -EINVAL;
34807a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	}
34817a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
34827a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return ret;
34837a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
34847a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
34854c3ca4da8086c3c9fcc81dccc387c34bee6b755eJan-Bernd Themannstatic ssize_t ehea_show_capabilities(struct device_driver *drv,
34864c3ca4da8086c3c9fcc81dccc387c34bee6b755eJan-Bernd Themann				      char *buf)
34874c3ca4da8086c3c9fcc81dccc387c34bee6b755eJan-Bernd Themann{
34884c3ca4da8086c3c9fcc81dccc387c34bee6b755eJan-Bernd Themann	return sprintf(buf, "%d", EHEA_CAPABILITIES);
34894c3ca4da8086c3c9fcc81dccc387c34bee6b755eJan-Bernd Themann}
34904c3ca4da8086c3c9fcc81dccc387c34bee6b755eJan-Bernd Themann
34914c3ca4da8086c3c9fcc81dccc387c34bee6b755eJan-Bernd Themannstatic DRIVER_ATTR(capabilities, S_IRUSR | S_IRGRP | S_IROTH,
34924c3ca4da8086c3c9fcc81dccc387c34bee6b755eJan-Bernd Themann		   ehea_show_capabilities, NULL);
34934c3ca4da8086c3c9fcc81dccc387c34bee6b755eJan-Bernd Themann
34941886e5d2c694e7fb59434c717e704e7fd8475d2eThadeu Lima de Souza Cascardostatic int __init ehea_module_init(void)
34957a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
34967a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	int ret;
34977a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
34988c4877a4128e7931077b024a891a4b284d8756a3Joe Perches	pr_info("IBM eHEA ethernet device driver (Release %s)\n", DRV_VERSION);
34997a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
350021eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	memset(&ehea_fw_handles, 0, sizeof(ehea_fw_handles));
350121eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	memset(&ehea_bcmc_regs, 0, sizeof(ehea_bcmc_regs));
350221eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
35039f71a568f5f1d6c9fb3ca89b6b973475e6475192Daniel Walker	mutex_init(&ehea_fw_handles.lock);
35045c2cec143ac54c1960e54bc320fa7d13ac8e0f4aJan-Bernd Themann	spin_lock_init(&ehea_bcmc_regs.lock);
350544c821525778c5d2e81da293195d5d589e8ad845Thomas Klein
35067a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ret = check_module_parm();
35077a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	if (ret)
35087a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann		goto out;
350944c821525778c5d2e81da293195d5d589e8ad845Thomas Klein
351044c821525778c5d2e81da293195d5d589e8ad845Thomas Klein	ret = ehea_create_busmap();
351144c821525778c5d2e81da293195d5d589e8ad845Thomas Klein	if (ret)
351244c821525778c5d2e81da293195d5d589e8ad845Thomas Klein		goto out;
351344c821525778c5d2e81da293195d5d589e8ad845Thomas Klein
351421eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	ret = register_reboot_notifier(&ehea_reboot_nb);
351521eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	if (ret)
35168c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_info("failed registering reboot notifier\n");
351721eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
351848cfb14f8b89d4d5b3df6c16f08b258686fb12adHannes Hering	ret = register_memory_notifier(&ehea_mem_nb);
351948cfb14f8b89d4d5b3df6c16f08b258686fb12adHannes Hering	if (ret)
35208c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_info("failed registering memory remove notifier\n");
352148cfb14f8b89d4d5b3df6c16f08b258686fb12adHannes Hering
3522c061b18df0f1fe3f50fe451dbbdc9ede3c19701aJoe Perches	ret = crash_shutdown_register(ehea_crash_handler);
352321eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	if (ret)
35248c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_info("failed registering crash handler\n");
35252a6f4e4983918b18fe5d3fb364afe33db7139870Jan-Bernd Themann
35267a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ret = ibmebus_register_driver(&ehea_driver);
35274c3ca4da8086c3c9fcc81dccc387c34bee6b755eJan-Bernd Themann	if (ret) {
35288c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("failed registering eHEA device driver on ebus\n");
352921eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein		goto out2;
35304c3ca4da8086c3c9fcc81dccc387c34bee6b755eJan-Bernd Themann	}
35314c3ca4da8086c3c9fcc81dccc387c34bee6b755eJan-Bernd Themann
35324c3ca4da8086c3c9fcc81dccc387c34bee6b755eJan-Bernd Themann	ret = driver_create_file(&ehea_driver.driver,
35334c3ca4da8086c3c9fcc81dccc387c34bee6b755eJan-Bernd Themann				 &driver_attr_capabilities);
35344c3ca4da8086c3c9fcc81dccc387c34bee6b755eJan-Bernd Themann	if (ret) {
35358c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_err("failed to register capabilities attribute, ret=%d\n",
35368c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		       ret);
353721eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein		goto out3;
35384c3ca4da8086c3c9fcc81dccc387c34bee6b755eJan-Bernd Themann	}
35397a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
354021eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	return ret;
354121eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
354221eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Kleinout3:
354321eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	ibmebus_unregister_driver(&ehea_driver);
354421eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Kleinout2:
354548cfb14f8b89d4d5b3df6c16f08b258686fb12adHannes Hering	unregister_memory_notifier(&ehea_mem_nb);
354621eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	unregister_reboot_notifier(&ehea_reboot_nb);
3547c061b18df0f1fe3f50fe451dbbdc9ede3c19701aJoe Perches	crash_shutdown_unregister(ehea_crash_handler);
35487a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannout:
35497a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	return ret;
35507a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
35517a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
35527a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannstatic void __exit ehea_module_exit(void)
35537a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann{
355421eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	int ret;
355521eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein
35564c3ca4da8086c3c9fcc81dccc387c34bee6b755eJan-Bernd Themann	driver_remove_file(&ehea_driver.driver, &driver_attr_capabilities);
35577a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann	ibmebus_unregister_driver(&ehea_driver);
35582a6f4e4983918b18fe5d3fb364afe33db7139870Jan-Bernd Themann	unregister_reboot_notifier(&ehea_reboot_nb);
3559c061b18df0f1fe3f50fe451dbbdc9ede3c19701aJoe Perches	ret = crash_shutdown_unregister(ehea_crash_handler);
356021eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	if (ret)
35618c4877a4128e7931077b024a891a4b284d8756a3Joe Perches		pr_info("failed unregistering crash handler\n");
356248cfb14f8b89d4d5b3df6c16f08b258686fb12adHannes Hering	unregister_memory_notifier(&ehea_mem_nb);
356321eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	kfree(ehea_fw_handles.arr);
356421eee2dd1b5702f15924f18f923b2a281f0e72e8Thomas Klein	kfree(ehea_bcmc_regs.arr);
356544c821525778c5d2e81da293195d5d589e8ad845Thomas Klein	ehea_destroy_busmap();
35667a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann}
35677a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themann
35687a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannmodule_init(ehea_module_init);
35697a291083225af6e22ffaa46b3d91cfc1a1ccaab4Jan-Bernd Themannmodule_exit(ehea_module_exit);
3570