xref: /openbmc/linux/drivers/net/fjes/fjes_main.c (revision fa2aee653663114a101e0af10848141fd57bdeca)
1dcc4086dSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2658d439bSTaku Izumi /*
3658d439bSTaku Izumi  *  FUJITSU Extended Socket Network Device driver
4658d439bSTaku Izumi  *  Copyright (c) 2015 FUJITSU LIMITED
5658d439bSTaku Izumi  */
6658d439bSTaku Izumi 
7658d439bSTaku Izumi #include <linux/module.h>
8658d439bSTaku Izumi #include <linux/types.h>
9658d439bSTaku Izumi #include <linux/nls.h>
10658d439bSTaku Izumi #include <linux/platform_device.h>
112fcbca68STaku Izumi #include <linux/netdevice.h>
12e5d486dcSTaku Izumi #include <linux/interrupt.h>
13658d439bSTaku Izumi 
14658d439bSTaku Izumi #include "fjes.h"
1582f6aea8STaku Izumi #include "fjes_trace.h"
16658d439bSTaku Izumi 
17658d439bSTaku Izumi #define MAJ 1
188f87d775STaku Izumi #define MIN 2
19658d439bSTaku Izumi #define DRV_VERSION __stringify(MAJ) "." __stringify(MIN)
20658d439bSTaku Izumi #define DRV_NAME	"fjes"
21658d439bSTaku Izumi char fjes_driver_name[] = DRV_NAME;
22658d439bSTaku Izumi char fjes_driver_version[] = DRV_VERSION;
23658d439bSTaku Izumi static const char fjes_driver_string[] =
24658d439bSTaku Izumi 		"FUJITSU Extended Socket Network Device Driver";
25658d439bSTaku Izumi static const char fjes_copyright[] =
26658d439bSTaku Izumi 		"Copyright (c) 2015 FUJITSU LIMITED";
27658d439bSTaku Izumi 
28658d439bSTaku Izumi MODULE_AUTHOR("Taku Izumi <izumi.taku@jp.fujitsu.com>");
29658d439bSTaku Izumi MODULE_DESCRIPTION("FUJITSU Extended Socket Network Device Driver");
30658d439bSTaku Izumi MODULE_LICENSE("GPL");
31658d439bSTaku Izumi MODULE_VERSION(DRV_VERSION);
32658d439bSTaku Izumi 
33ac23d3caSYasuaki Ishimatsu #define ACPI_MOTHERBOARD_RESOURCE_HID "PNP0C02"
34ac23d3caSYasuaki Ishimatsu 
35658d439bSTaku Izumi static const struct acpi_device_id fjes_acpi_ids[] = {
36ac23d3caSYasuaki Ishimatsu 	{ACPI_MOTHERBOARD_RESOURCE_HID, 0},
37658d439bSTaku Izumi 	{"", 0},
38658d439bSTaku Izumi };
39658d439bSTaku Izumi MODULE_DEVICE_TABLE(acpi, fjes_acpi_ids);
40658d439bSTaku Izumi 
41ac23d3caSYasuaki Ishimatsu static bool is_extended_socket_device(struct acpi_device *device)
42658d439bSTaku Izumi {
43658d439bSTaku Izumi 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL};
44658d439bSTaku Izumi 	char str_buf[sizeof(FJES_ACPI_SYMBOL) + 1];
45658d439bSTaku Izumi 	union acpi_object *str;
46658d439bSTaku Izumi 	acpi_status status;
47658d439bSTaku Izumi 	int result;
48658d439bSTaku Izumi 
49658d439bSTaku Izumi 	status = acpi_evaluate_object(device->handle, "_STR", NULL, &buffer);
50658d439bSTaku Izumi 	if (ACPI_FAILURE(status))
51ac23d3caSYasuaki Ishimatsu 		return false;
52658d439bSTaku Izumi 
53658d439bSTaku Izumi 	str = buffer.pointer;
54658d439bSTaku Izumi 	result = utf16s_to_utf8s((wchar_t *)str->string.pointer,
55658d439bSTaku Izumi 				 str->string.length, UTF16_LITTLE_ENDIAN,
56658d439bSTaku Izumi 				 str_buf, sizeof(str_buf) - 1);
57658d439bSTaku Izumi 	str_buf[result] = 0;
58658d439bSTaku Izumi 
59658d439bSTaku Izumi 	if (strncmp(FJES_ACPI_SYMBOL, str_buf, strlen(FJES_ACPI_SYMBOL)) != 0) {
60658d439bSTaku Izumi 		kfree(buffer.pointer);
61ac23d3caSYasuaki Ishimatsu 		return false;
62658d439bSTaku Izumi 	}
63658d439bSTaku Izumi 	kfree(buffer.pointer);
64658d439bSTaku Izumi 
65ac23d3caSYasuaki Ishimatsu 	return true;
66ac23d3caSYasuaki Ishimatsu }
67ac23d3caSYasuaki Ishimatsu 
682b396d30SYasuaki Ishimatsu static int acpi_check_extended_socket_status(struct acpi_device *device)
692b396d30SYasuaki Ishimatsu {
702b396d30SYasuaki Ishimatsu 	unsigned long long sta;
712b396d30SYasuaki Ishimatsu 	acpi_status status;
722b396d30SYasuaki Ishimatsu 
732b396d30SYasuaki Ishimatsu 	status = acpi_evaluate_integer(device->handle, "_STA", NULL, &sta);
742b396d30SYasuaki Ishimatsu 	if (ACPI_FAILURE(status))
752b396d30SYasuaki Ishimatsu 		return -ENODEV;
762b396d30SYasuaki Ishimatsu 
772b396d30SYasuaki Ishimatsu 	if (!((sta & ACPI_STA_DEVICE_PRESENT) &&
782b396d30SYasuaki Ishimatsu 	      (sta & ACPI_STA_DEVICE_ENABLED) &&
792b396d30SYasuaki Ishimatsu 	      (sta & ACPI_STA_DEVICE_UI) &&
802b396d30SYasuaki Ishimatsu 	      (sta & ACPI_STA_DEVICE_FUNCTIONING)))
812b396d30SYasuaki Ishimatsu 		return -ENODEV;
822b396d30SYasuaki Ishimatsu 
832b396d30SYasuaki Ishimatsu 	return 0;
842b396d30SYasuaki Ishimatsu }
852b396d30SYasuaki Ishimatsu 
86*fa2aee65SUwe Kleine-König static acpi_status
87*fa2aee65SUwe Kleine-König fjes_get_acpi_resource(struct acpi_resource *acpi_res, void *data)
88*fa2aee65SUwe Kleine-König {
89*fa2aee65SUwe Kleine-König 	struct acpi_resource_address32 *addr;
90*fa2aee65SUwe Kleine-König 	struct acpi_resource_irq *irq;
91*fa2aee65SUwe Kleine-König 	struct resource *res = data;
92*fa2aee65SUwe Kleine-König 
93*fa2aee65SUwe Kleine-König 	switch (acpi_res->type) {
94*fa2aee65SUwe Kleine-König 	case ACPI_RESOURCE_TYPE_ADDRESS32:
95*fa2aee65SUwe Kleine-König 		addr = &acpi_res->data.address32;
96*fa2aee65SUwe Kleine-König 		res[0].start = addr->address.minimum;
97*fa2aee65SUwe Kleine-König 		res[0].end = addr->address.minimum +
98*fa2aee65SUwe Kleine-König 			addr->address.address_length - 1;
99*fa2aee65SUwe Kleine-König 		break;
100*fa2aee65SUwe Kleine-König 
101*fa2aee65SUwe Kleine-König 	case ACPI_RESOURCE_TYPE_IRQ:
102*fa2aee65SUwe Kleine-König 		irq = &acpi_res->data.irq;
103*fa2aee65SUwe Kleine-König 		if (irq->interrupt_count != 1)
104*fa2aee65SUwe Kleine-König 			return AE_ERROR;
105*fa2aee65SUwe Kleine-König 		res[1].start = irq->interrupts[0];
106*fa2aee65SUwe Kleine-König 		res[1].end = irq->interrupts[0];
107*fa2aee65SUwe Kleine-König 		break;
108*fa2aee65SUwe Kleine-König 
109*fa2aee65SUwe Kleine-König 	default:
110*fa2aee65SUwe Kleine-König 		break;
111*fa2aee65SUwe Kleine-König 	}
112*fa2aee65SUwe Kleine-König 
113*fa2aee65SUwe Kleine-König 	return AE_OK;
114*fa2aee65SUwe Kleine-König }
115*fa2aee65SUwe Kleine-König 
116*fa2aee65SUwe Kleine-König static struct resource fjes_resource[] = {
117*fa2aee65SUwe Kleine-König 	DEFINE_RES_MEM(0, 1),
118*fa2aee65SUwe Kleine-König 	DEFINE_RES_IRQ(0)
119*fa2aee65SUwe Kleine-König };
120*fa2aee65SUwe Kleine-König 
121ac23d3caSYasuaki Ishimatsu static int fjes_acpi_add(struct acpi_device *device)
122ac23d3caSYasuaki Ishimatsu {
123ac23d3caSYasuaki Ishimatsu 	struct platform_device *plat_dev;
124ac23d3caSYasuaki Ishimatsu 	acpi_status status;
125ac23d3caSYasuaki Ishimatsu 
126ac23d3caSYasuaki Ishimatsu 	if (!is_extended_socket_device(device))
127ac23d3caSYasuaki Ishimatsu 		return -ENODEV;
128ac23d3caSYasuaki Ishimatsu 
1292b396d30SYasuaki Ishimatsu 	if (acpi_check_extended_socket_status(device))
1302b396d30SYasuaki Ishimatsu 		return -ENODEV;
1312b396d30SYasuaki Ishimatsu 
132658d439bSTaku Izumi 	status = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
133658d439bSTaku Izumi 				     fjes_get_acpi_resource, fjes_resource);
134658d439bSTaku Izumi 	if (ACPI_FAILURE(status))
135658d439bSTaku Izumi 		return -ENODEV;
136658d439bSTaku Izumi 
137658d439bSTaku Izumi 	/* create platform_device */
138658d439bSTaku Izumi 	plat_dev = platform_device_register_simple(DRV_NAME, 0, fjes_resource,
139658d439bSTaku Izumi 						   ARRAY_SIZE(fjes_resource));
140a288f105SChuhong Yuan 	if (IS_ERR(plat_dev))
141a288f105SChuhong Yuan 		return PTR_ERR(plat_dev);
142a288f105SChuhong Yuan 
143658d439bSTaku Izumi 	device->driver_data = plat_dev;
144658d439bSTaku Izumi 
145658d439bSTaku Izumi 	return 0;
146658d439bSTaku Izumi }
147658d439bSTaku Izumi 
148658d439bSTaku Izumi static int fjes_acpi_remove(struct acpi_device *device)
149658d439bSTaku Izumi {
150658d439bSTaku Izumi 	struct platform_device *plat_dev;
151658d439bSTaku Izumi 
152658d439bSTaku Izumi 	plat_dev = (struct platform_device *)acpi_driver_data(device);
153658d439bSTaku Izumi 	platform_device_unregister(plat_dev);
154658d439bSTaku Izumi 
155658d439bSTaku Izumi 	return 0;
156658d439bSTaku Izumi }
157658d439bSTaku Izumi 
158*fa2aee65SUwe Kleine-König static struct acpi_driver fjes_acpi_driver = {
159*fa2aee65SUwe Kleine-König 	.name = DRV_NAME,
160*fa2aee65SUwe Kleine-König 	.class = DRV_NAME,
161*fa2aee65SUwe Kleine-König 	.owner = THIS_MODULE,
162*fa2aee65SUwe Kleine-König 	.ids = fjes_acpi_ids,
163*fa2aee65SUwe Kleine-König 	.ops = {
164*fa2aee65SUwe Kleine-König 		.add = fjes_acpi_add,
165*fa2aee65SUwe Kleine-König 		.remove = fjes_acpi_remove,
166*fa2aee65SUwe Kleine-König 	},
167*fa2aee65SUwe Kleine-König };
168*fa2aee65SUwe Kleine-König 
169*fa2aee65SUwe Kleine-König static int fjes_setup_resources(struct fjes_adapter *adapter)
170658d439bSTaku Izumi {
171*fa2aee65SUwe Kleine-König 	struct net_device *netdev = adapter->netdev;
172*fa2aee65SUwe Kleine-König 	struct ep_share_mem_info *buf_pair;
173*fa2aee65SUwe Kleine-König 	struct fjes_hw *hw = &adapter->hw;
174*fa2aee65SUwe Kleine-König 	unsigned long flags;
175*fa2aee65SUwe Kleine-König 	int result;
176*fa2aee65SUwe Kleine-König 	int epidx;
177658d439bSTaku Izumi 
178*fa2aee65SUwe Kleine-König 	mutex_lock(&hw->hw_info.lock);
179*fa2aee65SUwe Kleine-König 	result = fjes_hw_request_info(hw);
180*fa2aee65SUwe Kleine-König 	switch (result) {
181*fa2aee65SUwe Kleine-König 	case 0:
182*fa2aee65SUwe Kleine-König 		for (epidx = 0; epidx < hw->max_epid; epidx++) {
183*fa2aee65SUwe Kleine-König 			hw->ep_shm_info[epidx].es_status =
184*fa2aee65SUwe Kleine-König 			    hw->hw_info.res_buf->info.info[epidx].es_status;
185*fa2aee65SUwe Kleine-König 			hw->ep_shm_info[epidx].zone =
186*fa2aee65SUwe Kleine-König 			    hw->hw_info.res_buf->info.info[epidx].zone;
187*fa2aee65SUwe Kleine-König 		}
188658d439bSTaku Izumi 		break;
189658d439bSTaku Izumi 	default:
190*fa2aee65SUwe Kleine-König 	case -ENOMSG:
191*fa2aee65SUwe Kleine-König 	case -EBUSY:
192*fa2aee65SUwe Kleine-König 		adapter->force_reset = true;
193*fa2aee65SUwe Kleine-König 
194*fa2aee65SUwe Kleine-König 		mutex_unlock(&hw->hw_info.lock);
195*fa2aee65SUwe Kleine-König 		return result;
196*fa2aee65SUwe Kleine-König 	}
197*fa2aee65SUwe Kleine-König 	mutex_unlock(&hw->hw_info.lock);
198*fa2aee65SUwe Kleine-König 
199*fa2aee65SUwe Kleine-König 	for (epidx = 0; epidx < (hw->max_epid); epidx++) {
200*fa2aee65SUwe Kleine-König 		if ((epidx != hw->my_epid) &&
201*fa2aee65SUwe Kleine-König 		    (hw->ep_shm_info[epidx].es_status ==
202*fa2aee65SUwe Kleine-König 		     FJES_ZONING_STATUS_ENABLE)) {
203*fa2aee65SUwe Kleine-König 			fjes_hw_raise_interrupt(hw, epidx,
204*fa2aee65SUwe Kleine-König 						REG_ICTL_MASK_INFO_UPDATE);
205*fa2aee65SUwe Kleine-König 			hw->ep_shm_info[epidx].ep_stats
206*fa2aee65SUwe Kleine-König 				.send_intr_zoneupdate += 1;
207*fa2aee65SUwe Kleine-König 		}
208658d439bSTaku Izumi 	}
209658d439bSTaku Izumi 
210*fa2aee65SUwe Kleine-König 	msleep(FJES_OPEN_ZONE_UPDATE_WAIT * hw->max_epid);
211*fa2aee65SUwe Kleine-König 
212*fa2aee65SUwe Kleine-König 	for (epidx = 0; epidx < (hw->max_epid); epidx++) {
213*fa2aee65SUwe Kleine-König 		if (epidx == hw->my_epid)
214*fa2aee65SUwe Kleine-König 			continue;
215*fa2aee65SUwe Kleine-König 
216*fa2aee65SUwe Kleine-König 		buf_pair = &hw->ep_shm_info[epidx];
217*fa2aee65SUwe Kleine-König 
218*fa2aee65SUwe Kleine-König 		spin_lock_irqsave(&hw->rx_status_lock, flags);
219*fa2aee65SUwe Kleine-König 		fjes_hw_setup_epbuf(&buf_pair->tx, netdev->dev_addr,
220*fa2aee65SUwe Kleine-König 				    netdev->mtu);
221*fa2aee65SUwe Kleine-König 		spin_unlock_irqrestore(&hw->rx_status_lock, flags);
222*fa2aee65SUwe Kleine-König 
223*fa2aee65SUwe Kleine-König 		if (fjes_hw_epid_is_same_zone(hw, epidx)) {
224*fa2aee65SUwe Kleine-König 			mutex_lock(&hw->hw_info.lock);
225*fa2aee65SUwe Kleine-König 			result =
226*fa2aee65SUwe Kleine-König 			fjes_hw_register_buff_addr(hw, epidx, buf_pair);
227*fa2aee65SUwe Kleine-König 			mutex_unlock(&hw->hw_info.lock);
228*fa2aee65SUwe Kleine-König 
229*fa2aee65SUwe Kleine-König 			switch (result) {
230*fa2aee65SUwe Kleine-König 			case 0:
231*fa2aee65SUwe Kleine-König 				break;
232*fa2aee65SUwe Kleine-König 			case -ENOMSG:
233*fa2aee65SUwe Kleine-König 			case -EBUSY:
234*fa2aee65SUwe Kleine-König 			default:
235*fa2aee65SUwe Kleine-König 				adapter->force_reset = true;
236*fa2aee65SUwe Kleine-König 				return result;
237*fa2aee65SUwe Kleine-König 			}
238*fa2aee65SUwe Kleine-König 
239*fa2aee65SUwe Kleine-König 			hw->ep_shm_info[epidx].ep_stats
240*fa2aee65SUwe Kleine-König 				.com_regist_buf_exec += 1;
241*fa2aee65SUwe Kleine-König 		}
242*fa2aee65SUwe Kleine-König 	}
243*fa2aee65SUwe Kleine-König 
244*fa2aee65SUwe Kleine-König 	return 0;
245*fa2aee65SUwe Kleine-König }
246*fa2aee65SUwe Kleine-König 
247*fa2aee65SUwe Kleine-König static void fjes_rx_irq(struct fjes_adapter *adapter, int src_epid)
248*fa2aee65SUwe Kleine-König {
249*fa2aee65SUwe Kleine-König 	struct fjes_hw *hw = &adapter->hw;
250*fa2aee65SUwe Kleine-König 
251*fa2aee65SUwe Kleine-König 	fjes_hw_set_irqmask(hw, REG_ICTL_MASK_RX_DATA, true);
252*fa2aee65SUwe Kleine-König 
253*fa2aee65SUwe Kleine-König 	adapter->unset_rx_last = true;
254*fa2aee65SUwe Kleine-König 	napi_schedule(&adapter->napi);
255*fa2aee65SUwe Kleine-König }
256*fa2aee65SUwe Kleine-König 
257*fa2aee65SUwe Kleine-König static void fjes_stop_req_irq(struct fjes_adapter *adapter, int src_epid)
258*fa2aee65SUwe Kleine-König {
259*fa2aee65SUwe Kleine-König 	struct fjes_hw *hw = &adapter->hw;
260*fa2aee65SUwe Kleine-König 	enum ep_partner_status status;
261*fa2aee65SUwe Kleine-König 	unsigned long flags;
262*fa2aee65SUwe Kleine-König 
263*fa2aee65SUwe Kleine-König 	set_bit(src_epid, &hw->hw_info.buffer_unshare_reserve_bit);
264*fa2aee65SUwe Kleine-König 
265*fa2aee65SUwe Kleine-König 	status = fjes_hw_get_partner_ep_status(hw, src_epid);
266*fa2aee65SUwe Kleine-König 	trace_fjes_stop_req_irq_pre(hw, src_epid, status);
267*fa2aee65SUwe Kleine-König 	switch (status) {
268*fa2aee65SUwe Kleine-König 	case EP_PARTNER_WAITING:
269*fa2aee65SUwe Kleine-König 		spin_lock_irqsave(&hw->rx_status_lock, flags);
270*fa2aee65SUwe Kleine-König 		hw->ep_shm_info[src_epid].tx.info->v1i.rx_status |=
271*fa2aee65SUwe Kleine-König 				FJES_RX_STOP_REQ_DONE;
272*fa2aee65SUwe Kleine-König 		spin_unlock_irqrestore(&hw->rx_status_lock, flags);
273*fa2aee65SUwe Kleine-König 		clear_bit(src_epid, &hw->txrx_stop_req_bit);
274*fa2aee65SUwe Kleine-König 		fallthrough;
275*fa2aee65SUwe Kleine-König 	case EP_PARTNER_UNSHARE:
276*fa2aee65SUwe Kleine-König 	case EP_PARTNER_COMPLETE:
277*fa2aee65SUwe Kleine-König 	default:
278*fa2aee65SUwe Kleine-König 		set_bit(src_epid, &adapter->unshare_watch_bitmask);
279*fa2aee65SUwe Kleine-König 		if (!work_pending(&adapter->unshare_watch_task))
280*fa2aee65SUwe Kleine-König 			queue_work(adapter->control_wq,
281*fa2aee65SUwe Kleine-König 				   &adapter->unshare_watch_task);
282*fa2aee65SUwe Kleine-König 		break;
283*fa2aee65SUwe Kleine-König 	case EP_PARTNER_SHARED:
284*fa2aee65SUwe Kleine-König 		set_bit(src_epid, &hw->epstop_req_bit);
285*fa2aee65SUwe Kleine-König 
286*fa2aee65SUwe Kleine-König 		if (!work_pending(&hw->epstop_task))
287*fa2aee65SUwe Kleine-König 			queue_work(adapter->control_wq, &hw->epstop_task);
288*fa2aee65SUwe Kleine-König 		break;
289*fa2aee65SUwe Kleine-König 	}
290*fa2aee65SUwe Kleine-König 	trace_fjes_stop_req_irq_post(hw, src_epid);
291*fa2aee65SUwe Kleine-König }
292*fa2aee65SUwe Kleine-König 
293*fa2aee65SUwe Kleine-König static void fjes_txrx_stop_req_irq(struct fjes_adapter *adapter,
294*fa2aee65SUwe Kleine-König 				   int src_epid)
295*fa2aee65SUwe Kleine-König {
296*fa2aee65SUwe Kleine-König 	struct fjes_hw *hw = &adapter->hw;
297*fa2aee65SUwe Kleine-König 	enum ep_partner_status status;
298*fa2aee65SUwe Kleine-König 	unsigned long flags;
299*fa2aee65SUwe Kleine-König 
300*fa2aee65SUwe Kleine-König 	status = fjes_hw_get_partner_ep_status(hw, src_epid);
301*fa2aee65SUwe Kleine-König 	trace_fjes_txrx_stop_req_irq_pre(hw, src_epid, status);
302*fa2aee65SUwe Kleine-König 	switch (status) {
303*fa2aee65SUwe Kleine-König 	case EP_PARTNER_UNSHARE:
304*fa2aee65SUwe Kleine-König 	case EP_PARTNER_COMPLETE:
305*fa2aee65SUwe Kleine-König 	default:
306*fa2aee65SUwe Kleine-König 		break;
307*fa2aee65SUwe Kleine-König 	case EP_PARTNER_WAITING:
308*fa2aee65SUwe Kleine-König 		if (src_epid < hw->my_epid) {
309*fa2aee65SUwe Kleine-König 			spin_lock_irqsave(&hw->rx_status_lock, flags);
310*fa2aee65SUwe Kleine-König 			hw->ep_shm_info[src_epid].tx.info->v1i.rx_status |=
311*fa2aee65SUwe Kleine-König 				FJES_RX_STOP_REQ_DONE;
312*fa2aee65SUwe Kleine-König 			spin_unlock_irqrestore(&hw->rx_status_lock, flags);
313*fa2aee65SUwe Kleine-König 
314*fa2aee65SUwe Kleine-König 			clear_bit(src_epid, &hw->txrx_stop_req_bit);
315*fa2aee65SUwe Kleine-König 			set_bit(src_epid, &adapter->unshare_watch_bitmask);
316*fa2aee65SUwe Kleine-König 
317*fa2aee65SUwe Kleine-König 			if (!work_pending(&adapter->unshare_watch_task))
318*fa2aee65SUwe Kleine-König 				queue_work(adapter->control_wq,
319*fa2aee65SUwe Kleine-König 					   &adapter->unshare_watch_task);
320*fa2aee65SUwe Kleine-König 		}
321*fa2aee65SUwe Kleine-König 		break;
322*fa2aee65SUwe Kleine-König 	case EP_PARTNER_SHARED:
323*fa2aee65SUwe Kleine-König 		if (hw->ep_shm_info[src_epid].rx.info->v1i.rx_status &
324*fa2aee65SUwe Kleine-König 		    FJES_RX_STOP_REQ_REQUEST) {
325*fa2aee65SUwe Kleine-König 			set_bit(src_epid, &hw->epstop_req_bit);
326*fa2aee65SUwe Kleine-König 			if (!work_pending(&hw->epstop_task))
327*fa2aee65SUwe Kleine-König 				queue_work(adapter->control_wq,
328*fa2aee65SUwe Kleine-König 					   &hw->epstop_task);
329*fa2aee65SUwe Kleine-König 		}
330*fa2aee65SUwe Kleine-König 		break;
331*fa2aee65SUwe Kleine-König 	}
332*fa2aee65SUwe Kleine-König 	trace_fjes_txrx_stop_req_irq_post(hw, src_epid);
333*fa2aee65SUwe Kleine-König }
334*fa2aee65SUwe Kleine-König 
335*fa2aee65SUwe Kleine-König static void fjes_update_zone_irq(struct fjes_adapter *adapter,
336*fa2aee65SUwe Kleine-König 				 int src_epid)
337*fa2aee65SUwe Kleine-König {
338*fa2aee65SUwe Kleine-König 	struct fjes_hw *hw = &adapter->hw;
339*fa2aee65SUwe Kleine-König 
340*fa2aee65SUwe Kleine-König 	if (!work_pending(&hw->update_zone_task))
341*fa2aee65SUwe Kleine-König 		queue_work(adapter->control_wq, &hw->update_zone_task);
342*fa2aee65SUwe Kleine-König }
343*fa2aee65SUwe Kleine-König 
344*fa2aee65SUwe Kleine-König static irqreturn_t fjes_intr(int irq, void *data)
345*fa2aee65SUwe Kleine-König {
346*fa2aee65SUwe Kleine-König 	struct fjes_adapter *adapter = data;
347*fa2aee65SUwe Kleine-König 	struct fjes_hw *hw = &adapter->hw;
348*fa2aee65SUwe Kleine-König 	irqreturn_t ret;
349*fa2aee65SUwe Kleine-König 	u32 icr;
350*fa2aee65SUwe Kleine-König 
351*fa2aee65SUwe Kleine-König 	icr = fjes_hw_capture_interrupt_status(hw);
352*fa2aee65SUwe Kleine-König 
353*fa2aee65SUwe Kleine-König 	if (icr & REG_IS_MASK_IS_ASSERT) {
354*fa2aee65SUwe Kleine-König 		if (icr & REG_ICTL_MASK_RX_DATA) {
355*fa2aee65SUwe Kleine-König 			fjes_rx_irq(adapter, icr & REG_IS_MASK_EPID);
356*fa2aee65SUwe Kleine-König 			hw->ep_shm_info[icr & REG_IS_MASK_EPID].ep_stats
357*fa2aee65SUwe Kleine-König 				.recv_intr_rx += 1;
358*fa2aee65SUwe Kleine-König 		}
359*fa2aee65SUwe Kleine-König 
360*fa2aee65SUwe Kleine-König 		if (icr & REG_ICTL_MASK_DEV_STOP_REQ) {
361*fa2aee65SUwe Kleine-König 			fjes_stop_req_irq(adapter, icr & REG_IS_MASK_EPID);
362*fa2aee65SUwe Kleine-König 			hw->ep_shm_info[icr & REG_IS_MASK_EPID].ep_stats
363*fa2aee65SUwe Kleine-König 				.recv_intr_stop += 1;
364*fa2aee65SUwe Kleine-König 		}
365*fa2aee65SUwe Kleine-König 
366*fa2aee65SUwe Kleine-König 		if (icr & REG_ICTL_MASK_TXRX_STOP_REQ) {
367*fa2aee65SUwe Kleine-König 			fjes_txrx_stop_req_irq(adapter, icr & REG_IS_MASK_EPID);
368*fa2aee65SUwe Kleine-König 			hw->ep_shm_info[icr & REG_IS_MASK_EPID].ep_stats
369*fa2aee65SUwe Kleine-König 				.recv_intr_unshare += 1;
370*fa2aee65SUwe Kleine-König 		}
371*fa2aee65SUwe Kleine-König 
372*fa2aee65SUwe Kleine-König 		if (icr & REG_ICTL_MASK_TXRX_STOP_DONE)
373*fa2aee65SUwe Kleine-König 			fjes_hw_set_irqmask(hw,
374*fa2aee65SUwe Kleine-König 					    REG_ICTL_MASK_TXRX_STOP_DONE, true);
375*fa2aee65SUwe Kleine-König 
376*fa2aee65SUwe Kleine-König 		if (icr & REG_ICTL_MASK_INFO_UPDATE) {
377*fa2aee65SUwe Kleine-König 			fjes_update_zone_irq(adapter, icr & REG_IS_MASK_EPID);
378*fa2aee65SUwe Kleine-König 			hw->ep_shm_info[icr & REG_IS_MASK_EPID].ep_stats
379*fa2aee65SUwe Kleine-König 				.recv_intr_zoneupdate += 1;
380*fa2aee65SUwe Kleine-König 		}
381*fa2aee65SUwe Kleine-König 
382*fa2aee65SUwe Kleine-König 		ret = IRQ_HANDLED;
383*fa2aee65SUwe Kleine-König 	} else {
384*fa2aee65SUwe Kleine-König 		ret = IRQ_NONE;
385*fa2aee65SUwe Kleine-König 	}
386*fa2aee65SUwe Kleine-König 
387*fa2aee65SUwe Kleine-König 	return ret;
388658d439bSTaku Izumi }
389658d439bSTaku Izumi 
390e5d486dcSTaku Izumi static int fjes_request_irq(struct fjes_adapter *adapter)
391e5d486dcSTaku Izumi {
392e5d486dcSTaku Izumi 	struct net_device *netdev = adapter->netdev;
393e5d486dcSTaku Izumi 	int result = -1;
394e5d486dcSTaku Izumi 
3958edb62a8STaku Izumi 	adapter->interrupt_watch_enable = true;
3968edb62a8STaku Izumi 	if (!delayed_work_pending(&adapter->interrupt_watch_task)) {
3978edb62a8STaku Izumi 		queue_delayed_work(adapter->control_wq,
3988edb62a8STaku Izumi 				   &adapter->interrupt_watch_task,
3998edb62a8STaku Izumi 				   FJES_IRQ_WATCH_DELAY);
4008edb62a8STaku Izumi 	}
4018edb62a8STaku Izumi 
402e5d486dcSTaku Izumi 	if (!adapter->irq_registered) {
403e5d486dcSTaku Izumi 		result = request_irq(adapter->hw.hw_res.irq, fjes_intr,
404e5d486dcSTaku Izumi 				     IRQF_SHARED, netdev->name, adapter);
405e5d486dcSTaku Izumi 		if (result)
406e5d486dcSTaku Izumi 			adapter->irq_registered = false;
407e5d486dcSTaku Izumi 		else
408e5d486dcSTaku Izumi 			adapter->irq_registered = true;
409e5d486dcSTaku Izumi 	}
410e5d486dcSTaku Izumi 
411e5d486dcSTaku Izumi 	return result;
412e5d486dcSTaku Izumi }
413e5d486dcSTaku Izumi 
414e5d486dcSTaku Izumi static void fjes_free_irq(struct fjes_adapter *adapter)
415e5d486dcSTaku Izumi {
416e5d486dcSTaku Izumi 	struct fjes_hw *hw = &adapter->hw;
417e5d486dcSTaku Izumi 
4188edb62a8STaku Izumi 	adapter->interrupt_watch_enable = false;
4198edb62a8STaku Izumi 	cancel_delayed_work_sync(&adapter->interrupt_watch_task);
4208edb62a8STaku Izumi 
421e5d486dcSTaku Izumi 	fjes_hw_set_irqmask(hw, REG_ICTL_MASK_ALL, true);
422e5d486dcSTaku Izumi 
423e5d486dcSTaku Izumi 	if (adapter->irq_registered) {
424e5d486dcSTaku Izumi 		free_irq(adapter->hw.hw_res.irq, adapter);
425e5d486dcSTaku Izumi 		adapter->irq_registered = false;
426e5d486dcSTaku Izumi 	}
427e5d486dcSTaku Izumi }
428e5d486dcSTaku Izumi 
429*fa2aee65SUwe Kleine-König static void fjes_free_resources(struct fjes_adapter *adapter)
430*fa2aee65SUwe Kleine-König {
431*fa2aee65SUwe Kleine-König 	struct net_device *netdev = adapter->netdev;
432*fa2aee65SUwe Kleine-König 	struct fjes_device_command_param param;
433*fa2aee65SUwe Kleine-König 	struct ep_share_mem_info *buf_pair;
434*fa2aee65SUwe Kleine-König 	struct fjes_hw *hw = &adapter->hw;
435*fa2aee65SUwe Kleine-König 	bool reset_flag = false;
436*fa2aee65SUwe Kleine-König 	unsigned long flags;
437*fa2aee65SUwe Kleine-König 	int result;
438*fa2aee65SUwe Kleine-König 	int epidx;
439*fa2aee65SUwe Kleine-König 
440*fa2aee65SUwe Kleine-König 	for (epidx = 0; epidx < hw->max_epid; epidx++) {
441*fa2aee65SUwe Kleine-König 		if (epidx == hw->my_epid)
442*fa2aee65SUwe Kleine-König 			continue;
443*fa2aee65SUwe Kleine-König 
444*fa2aee65SUwe Kleine-König 		mutex_lock(&hw->hw_info.lock);
445*fa2aee65SUwe Kleine-König 		result = fjes_hw_unregister_buff_addr(hw, epidx);
446*fa2aee65SUwe Kleine-König 		mutex_unlock(&hw->hw_info.lock);
447*fa2aee65SUwe Kleine-König 
448*fa2aee65SUwe Kleine-König 		hw->ep_shm_info[epidx].ep_stats.com_unregist_buf_exec += 1;
449*fa2aee65SUwe Kleine-König 
450*fa2aee65SUwe Kleine-König 		if (result)
451*fa2aee65SUwe Kleine-König 			reset_flag = true;
452*fa2aee65SUwe Kleine-König 
453*fa2aee65SUwe Kleine-König 		buf_pair = &hw->ep_shm_info[epidx];
454*fa2aee65SUwe Kleine-König 
455*fa2aee65SUwe Kleine-König 		spin_lock_irqsave(&hw->rx_status_lock, flags);
456*fa2aee65SUwe Kleine-König 		fjes_hw_setup_epbuf(&buf_pair->tx,
457*fa2aee65SUwe Kleine-König 				    netdev->dev_addr, netdev->mtu);
458*fa2aee65SUwe Kleine-König 		spin_unlock_irqrestore(&hw->rx_status_lock, flags);
459*fa2aee65SUwe Kleine-König 
460*fa2aee65SUwe Kleine-König 		clear_bit(epidx, &hw->txrx_stop_req_bit);
461*fa2aee65SUwe Kleine-König 	}
462*fa2aee65SUwe Kleine-König 
463*fa2aee65SUwe Kleine-König 	if (reset_flag || adapter->force_reset) {
464*fa2aee65SUwe Kleine-König 		result = fjes_hw_reset(hw);
465*fa2aee65SUwe Kleine-König 
466*fa2aee65SUwe Kleine-König 		adapter->force_reset = false;
467*fa2aee65SUwe Kleine-König 
468*fa2aee65SUwe Kleine-König 		if (result)
469*fa2aee65SUwe Kleine-König 			adapter->open_guard = true;
470*fa2aee65SUwe Kleine-König 
471*fa2aee65SUwe Kleine-König 		hw->hw_info.buffer_share_bit = 0;
472*fa2aee65SUwe Kleine-König 
473*fa2aee65SUwe Kleine-König 		memset((void *)&param, 0, sizeof(param));
474*fa2aee65SUwe Kleine-König 
475*fa2aee65SUwe Kleine-König 		param.req_len = hw->hw_info.req_buf_size;
476*fa2aee65SUwe Kleine-König 		param.req_start = __pa(hw->hw_info.req_buf);
477*fa2aee65SUwe Kleine-König 		param.res_len = hw->hw_info.res_buf_size;
478*fa2aee65SUwe Kleine-König 		param.res_start = __pa(hw->hw_info.res_buf);
479*fa2aee65SUwe Kleine-König 		param.share_start = __pa(hw->hw_info.share->ep_status);
480*fa2aee65SUwe Kleine-König 
481*fa2aee65SUwe Kleine-König 		fjes_hw_init_command_registers(hw, &param);
482*fa2aee65SUwe Kleine-König 	}
483*fa2aee65SUwe Kleine-König }
4842fcbca68STaku Izumi 
485e5d486dcSTaku Izumi /* fjes_open - Called when a network interface is made active */
486e5d486dcSTaku Izumi static int fjes_open(struct net_device *netdev)
487e5d486dcSTaku Izumi {
488e5d486dcSTaku Izumi 	struct fjes_adapter *adapter = netdev_priv(netdev);
489e5d486dcSTaku Izumi 	struct fjes_hw *hw = &adapter->hw;
490e5d486dcSTaku Izumi 	int result;
491e5d486dcSTaku Izumi 
492e5d486dcSTaku Izumi 	if (adapter->open_guard)
493e5d486dcSTaku Izumi 		return -ENXIO;
494e5d486dcSTaku Izumi 
495e5d486dcSTaku Izumi 	result = fjes_setup_resources(adapter);
496e5d486dcSTaku Izumi 	if (result)
497e5d486dcSTaku Izumi 		goto err_setup_res;
498e5d486dcSTaku Izumi 
499e5d486dcSTaku Izumi 	hw->txrx_stop_req_bit = 0;
500e5d486dcSTaku Izumi 	hw->epstop_req_bit = 0;
501e5d486dcSTaku Izumi 
50226585930STaku Izumi 	napi_enable(&adapter->napi);
50326585930STaku Izumi 
504e5d486dcSTaku Izumi 	fjes_hw_capture_interrupt_status(hw);
505e5d486dcSTaku Izumi 
506e5d486dcSTaku Izumi 	result = fjes_request_irq(adapter);
507e5d486dcSTaku Izumi 	if (result)
508e5d486dcSTaku Izumi 		goto err_req_irq;
509e5d486dcSTaku Izumi 
510e5d486dcSTaku Izumi 	fjes_hw_set_irqmask(hw, REG_ICTL_MASK_ALL, false);
511e5d486dcSTaku Izumi 
512e5d486dcSTaku Izumi 	netif_tx_start_all_queues(netdev);
513e5d486dcSTaku Izumi 	netif_carrier_on(netdev);
514e5d486dcSTaku Izumi 
515e5d486dcSTaku Izumi 	return 0;
516e5d486dcSTaku Izumi 
517e5d486dcSTaku Izumi err_req_irq:
518e5d486dcSTaku Izumi 	fjes_free_irq(adapter);
51926585930STaku Izumi 	napi_disable(&adapter->napi);
520e5d486dcSTaku Izumi 
521e5d486dcSTaku Izumi err_setup_res:
522e5d486dcSTaku Izumi 	fjes_free_resources(adapter);
523e5d486dcSTaku Izumi 	return result;
524e5d486dcSTaku Izumi }
525e5d486dcSTaku Izumi 
526e5d486dcSTaku Izumi /* fjes_close - Disables a network interface */
527e5d486dcSTaku Izumi static int fjes_close(struct net_device *netdev)
528e5d486dcSTaku Izumi {
529e5d486dcSTaku Izumi 	struct fjes_adapter *adapter = netdev_priv(netdev);
530e5d486dcSTaku Izumi 	struct fjes_hw *hw = &adapter->hw;
531bd5a2569STaku Izumi 	unsigned long flags;
532e5d486dcSTaku Izumi 	int epidx;
533e5d486dcSTaku Izumi 
534e5d486dcSTaku Izumi 	netif_tx_stop_all_queues(netdev);
535e5d486dcSTaku Izumi 	netif_carrier_off(netdev);
536e5d486dcSTaku Izumi 
537e5d486dcSTaku Izumi 	fjes_hw_raise_epstop(hw);
538e5d486dcSTaku Izumi 
53926585930STaku Izumi 	napi_disable(&adapter->napi);
54026585930STaku Izumi 
541bd5a2569STaku Izumi 	spin_lock_irqsave(&hw->rx_status_lock, flags);
542e5d486dcSTaku Izumi 	for (epidx = 0; epidx < hw->max_epid; epidx++) {
543e5d486dcSTaku Izumi 		if (epidx == hw->my_epid)
544e5d486dcSTaku Izumi 			continue;
545e5d486dcSTaku Izumi 
546bd5a2569STaku Izumi 		if (fjes_hw_get_partner_ep_status(hw, epidx) ==
547bd5a2569STaku Izumi 		    EP_PARTNER_SHARED)
548bd5a2569STaku Izumi 			adapter->hw.ep_shm_info[epidx]
549bd5a2569STaku Izumi 				   .tx.info->v1i.rx_status &=
550e5d486dcSTaku Izumi 				~FJES_RX_POLL_WORK;
551e5d486dcSTaku Izumi 	}
552bd5a2569STaku Izumi 	spin_unlock_irqrestore(&hw->rx_status_lock, flags);
553e5d486dcSTaku Izumi 
554e5d486dcSTaku Izumi 	fjes_free_irq(adapter);
555e5d486dcSTaku Izumi 
5568edb62a8STaku Izumi 	cancel_delayed_work_sync(&adapter->interrupt_watch_task);
5578fc4cadbSTaku Izumi 	cancel_work_sync(&adapter->unshare_watch_task);
5588fc4cadbSTaku Izumi 	adapter->unshare_watch_bitmask = 0;
559b772b9dcSTaku Izumi 	cancel_work_sync(&adapter->raise_intr_rxdata_task);
560ac63b947STaku Izumi 	cancel_work_sync(&adapter->tx_stall_task);
561b772b9dcSTaku Izumi 
562785f28e0STaku Izumi 	cancel_work_sync(&hw->update_zone_task);
563b5a9152dSTaku Izumi 	cancel_work_sync(&hw->epstop_task);
564785f28e0STaku Izumi 
565e5d486dcSTaku Izumi 	fjes_hw_wait_epstop(hw);
566e5d486dcSTaku Izumi 
567e5d486dcSTaku Izumi 	fjes_free_resources(adapter);
568e5d486dcSTaku Izumi 
569e5d486dcSTaku Izumi 	return 0;
570e5d486dcSTaku Izumi }
571e5d486dcSTaku Izumi 
5729acf51cbSTaku Izumi static int fjes_tx_send(struct fjes_adapter *adapter, int dest,
5739acf51cbSTaku Izumi 			void *data, size_t len)
5749acf51cbSTaku Izumi {
5759acf51cbSTaku Izumi 	int retval;
5769acf51cbSTaku Izumi 
5779acf51cbSTaku Izumi 	retval = fjes_hw_epbuf_tx_pkt_send(&adapter->hw.ep_shm_info[dest].tx,
5789acf51cbSTaku Izumi 					   data, len);
5799acf51cbSTaku Izumi 	if (retval)
5809acf51cbSTaku Izumi 		return retval;
5819acf51cbSTaku Izumi 
5829acf51cbSTaku Izumi 	adapter->hw.ep_shm_info[dest].tx.info->v1i.tx_status =
5839acf51cbSTaku Izumi 		FJES_TX_DELAY_SEND_PENDING;
584b772b9dcSTaku Izumi 	if (!work_pending(&adapter->raise_intr_rxdata_task))
585b772b9dcSTaku Izumi 		queue_work(adapter->txrx_wq,
586b772b9dcSTaku Izumi 			   &adapter->raise_intr_rxdata_task);
5879acf51cbSTaku Izumi 
5889acf51cbSTaku Izumi 	retval = 0;
5899acf51cbSTaku Izumi 	return retval;
5909acf51cbSTaku Izumi }
5919acf51cbSTaku Izumi 
5929acf51cbSTaku Izumi static netdev_tx_t
5939acf51cbSTaku Izumi fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
5949acf51cbSTaku Izumi {
5959acf51cbSTaku Izumi 	struct fjes_adapter *adapter = netdev_priv(netdev);
5969acf51cbSTaku Izumi 	struct fjes_hw *hw = &adapter->hw;
5979acf51cbSTaku Izumi 
5989acf51cbSTaku Izumi 	int max_epid, my_epid, dest_epid;
5999acf51cbSTaku Izumi 	enum ep_partner_status pstatus;
6009acf51cbSTaku Izumi 	struct netdev_queue *cur_queue;
6019acf51cbSTaku Izumi 	char shortpkt[VLAN_ETH_HLEN];
6029acf51cbSTaku Izumi 	bool is_multi, vlan;
6039acf51cbSTaku Izumi 	struct ethhdr *eth;
6049acf51cbSTaku Izumi 	u16 queue_no = 0;
6059acf51cbSTaku Izumi 	u16 vlan_id = 0;
6069acf51cbSTaku Izumi 	netdev_tx_t ret;
6079acf51cbSTaku Izumi 	char *data;
6089acf51cbSTaku Izumi 	int len;
6099acf51cbSTaku Izumi 
6109acf51cbSTaku Izumi 	ret = NETDEV_TX_OK;
6119acf51cbSTaku Izumi 	is_multi = false;
6129acf51cbSTaku Izumi 	cur_queue = netdev_get_tx_queue(netdev, queue_no);
6139acf51cbSTaku Izumi 
6149acf51cbSTaku Izumi 	eth = (struct ethhdr *)skb->data;
6159acf51cbSTaku Izumi 	my_epid = hw->my_epid;
6169acf51cbSTaku Izumi 
6179acf51cbSTaku Izumi 	vlan = (vlan_get_tag(skb, &vlan_id) == 0) ? true : false;
6189acf51cbSTaku Izumi 
6199acf51cbSTaku Izumi 	data = skb->data;
6209acf51cbSTaku Izumi 	len = skb->len;
6219acf51cbSTaku Izumi 
6229acf51cbSTaku Izumi 	if (is_multicast_ether_addr(eth->h_dest)) {
6239acf51cbSTaku Izumi 		dest_epid = 0;
6249acf51cbSTaku Izumi 		max_epid = hw->max_epid;
6259acf51cbSTaku Izumi 		is_multi = true;
6269acf51cbSTaku Izumi 	} else if (is_local_ether_addr(eth->h_dest)) {
6279acf51cbSTaku Izumi 		dest_epid = eth->h_dest[ETH_ALEN - 1];
6289acf51cbSTaku Izumi 		max_epid = dest_epid + 1;
6299acf51cbSTaku Izumi 
6309acf51cbSTaku Izumi 		if ((eth->h_dest[0] == 0x02) &&
6319acf51cbSTaku Izumi 		    (0x00 == (eth->h_dest[1] | eth->h_dest[2] |
6329acf51cbSTaku Izumi 			      eth->h_dest[3] | eth->h_dest[4])) &&
6339acf51cbSTaku Izumi 		    (dest_epid < hw->max_epid)) {
6349acf51cbSTaku Izumi 			;
6359acf51cbSTaku Izumi 		} else {
6369acf51cbSTaku Izumi 			dest_epid = 0;
6379acf51cbSTaku Izumi 			max_epid = 0;
6389acf51cbSTaku Izumi 			ret = NETDEV_TX_OK;
6399acf51cbSTaku Izumi 
6409acf51cbSTaku Izumi 			adapter->stats64.tx_packets += 1;
6419acf51cbSTaku Izumi 			hw->ep_shm_info[my_epid].net_stats.tx_packets += 1;
6429acf51cbSTaku Izumi 			adapter->stats64.tx_bytes += len;
6439acf51cbSTaku Izumi 			hw->ep_shm_info[my_epid].net_stats.tx_bytes += len;
6449acf51cbSTaku Izumi 		}
6459acf51cbSTaku Izumi 	} else {
6469acf51cbSTaku Izumi 		dest_epid = 0;
6479acf51cbSTaku Izumi 		max_epid = 0;
6489acf51cbSTaku Izumi 		ret = NETDEV_TX_OK;
6499acf51cbSTaku Izumi 
6509acf51cbSTaku Izumi 		adapter->stats64.tx_packets += 1;
6519acf51cbSTaku Izumi 		hw->ep_shm_info[my_epid].net_stats.tx_packets += 1;
6529acf51cbSTaku Izumi 		adapter->stats64.tx_bytes += len;
6539acf51cbSTaku Izumi 		hw->ep_shm_info[my_epid].net_stats.tx_bytes += len;
6549acf51cbSTaku Izumi 	}
6559acf51cbSTaku Izumi 
6569acf51cbSTaku Izumi 	for (; dest_epid < max_epid; dest_epid++) {
6579acf51cbSTaku Izumi 		if (my_epid == dest_epid)
6589acf51cbSTaku Izumi 			continue;
6599acf51cbSTaku Izumi 
6609acf51cbSTaku Izumi 		pstatus = fjes_hw_get_partner_ep_status(hw, dest_epid);
6619acf51cbSTaku Izumi 		if (pstatus != EP_PARTNER_SHARED) {
66221b7efbcSTaku Izumi 			if (!is_multi)
66321b7efbcSTaku Izumi 				hw->ep_shm_info[dest_epid].ep_stats
66421b7efbcSTaku Izumi 					.tx_dropped_not_shared += 1;
6659acf51cbSTaku Izumi 			ret = NETDEV_TX_OK;
6669acf51cbSTaku Izumi 		} else if (!fjes_hw_check_epbuf_version(
6679acf51cbSTaku Izumi 				&adapter->hw.ep_shm_info[dest_epid].rx, 0)) {
6689acf51cbSTaku Izumi 			/* version is NOT 0 */
6699acf51cbSTaku Izumi 			adapter->stats64.tx_carrier_errors += 1;
6703c3bd4a9STaku Izumi 			hw->ep_shm_info[dest_epid].net_stats
6719acf51cbSTaku Izumi 						.tx_carrier_errors += 1;
67221b7efbcSTaku Izumi 			hw->ep_shm_info[dest_epid].ep_stats
67321b7efbcSTaku Izumi 					.tx_dropped_ver_mismatch += 1;
6749acf51cbSTaku Izumi 
6759acf51cbSTaku Izumi 			ret = NETDEV_TX_OK;
6769acf51cbSTaku Izumi 		} else if (!fjes_hw_check_mtu(
6779acf51cbSTaku Izumi 				&adapter->hw.ep_shm_info[dest_epid].rx,
6789acf51cbSTaku Izumi 				netdev->mtu)) {
6799acf51cbSTaku Izumi 			adapter->stats64.tx_dropped += 1;
6803c3bd4a9STaku Izumi 			hw->ep_shm_info[dest_epid].net_stats.tx_dropped += 1;
6819acf51cbSTaku Izumi 			adapter->stats64.tx_errors += 1;
6823c3bd4a9STaku Izumi 			hw->ep_shm_info[dest_epid].net_stats.tx_errors += 1;
68321b7efbcSTaku Izumi 			hw->ep_shm_info[dest_epid].ep_stats
68421b7efbcSTaku Izumi 					.tx_dropped_buf_size_mismatch += 1;
6859acf51cbSTaku Izumi 
6869acf51cbSTaku Izumi 			ret = NETDEV_TX_OK;
6879acf51cbSTaku Izumi 		} else if (vlan &&
6889acf51cbSTaku Izumi 			   !fjes_hw_check_vlan_id(
6899acf51cbSTaku Izumi 				&adapter->hw.ep_shm_info[dest_epid].rx,
6909acf51cbSTaku Izumi 				vlan_id)) {
69121b7efbcSTaku Izumi 			hw->ep_shm_info[dest_epid].ep_stats
69221b7efbcSTaku Izumi 				.tx_dropped_vlanid_mismatch += 1;
6939acf51cbSTaku Izumi 			ret = NETDEV_TX_OK;
6949acf51cbSTaku Izumi 		} else {
6959acf51cbSTaku Izumi 			if (len < VLAN_ETH_HLEN) {
6969acf51cbSTaku Izumi 				memset(shortpkt, 0, VLAN_ETH_HLEN);
6979acf51cbSTaku Izumi 				memcpy(shortpkt, skb->data, skb->len);
6989acf51cbSTaku Izumi 				len = VLAN_ETH_HLEN;
6999acf51cbSTaku Izumi 				data = shortpkt;
7009acf51cbSTaku Izumi 			}
7019acf51cbSTaku Izumi 
7029acf51cbSTaku Izumi 			if (adapter->tx_retry_count == 0) {
7039acf51cbSTaku Izumi 				adapter->tx_start_jiffies = jiffies;
7049acf51cbSTaku Izumi 				adapter->tx_retry_count = 1;
7059acf51cbSTaku Izumi 			} else {
7069acf51cbSTaku Izumi 				adapter->tx_retry_count++;
7079acf51cbSTaku Izumi 			}
7089acf51cbSTaku Izumi 
7099acf51cbSTaku Izumi 			if (fjes_tx_send(adapter, dest_epid, data, len)) {
7109acf51cbSTaku Izumi 				if (is_multi) {
7119acf51cbSTaku Izumi 					ret = NETDEV_TX_OK;
7129acf51cbSTaku Izumi 				} else if (
7139acf51cbSTaku Izumi 					   ((long)jiffies -
7149acf51cbSTaku Izumi 					    (long)adapter->tx_start_jiffies) >=
7159acf51cbSTaku Izumi 					    FJES_TX_RETRY_TIMEOUT) {
7169acf51cbSTaku Izumi 					adapter->stats64.tx_fifo_errors += 1;
7173c3bd4a9STaku Izumi 					hw->ep_shm_info[dest_epid].net_stats
7189acf51cbSTaku Izumi 								.tx_fifo_errors += 1;
7199acf51cbSTaku Izumi 					adapter->stats64.tx_errors += 1;
7203c3bd4a9STaku Izumi 					hw->ep_shm_info[dest_epid].net_stats
7219acf51cbSTaku Izumi 								.tx_errors += 1;
7229acf51cbSTaku Izumi 
7239acf51cbSTaku Izumi 					ret = NETDEV_TX_OK;
7249acf51cbSTaku Izumi 				} else {
725860e9538SFlorian Westphal 					netif_trans_update(netdev);
72621b7efbcSTaku Izumi 					hw->ep_shm_info[dest_epid].ep_stats
72721b7efbcSTaku Izumi 						.tx_buffer_full += 1;
7289acf51cbSTaku Izumi 					netif_tx_stop_queue(cur_queue);
7299acf51cbSTaku Izumi 
730ac63b947STaku Izumi 					if (!work_pending(&adapter->tx_stall_task))
731ac63b947STaku Izumi 						queue_work(adapter->txrx_wq,
732ac63b947STaku Izumi 							   &adapter->tx_stall_task);
733ac63b947STaku Izumi 
7349acf51cbSTaku Izumi 					ret = NETDEV_TX_BUSY;
7359acf51cbSTaku Izumi 				}
7369acf51cbSTaku Izumi 			} else {
7379acf51cbSTaku Izumi 				if (!is_multi) {
7389acf51cbSTaku Izumi 					adapter->stats64.tx_packets += 1;
7393c3bd4a9STaku Izumi 					hw->ep_shm_info[dest_epid].net_stats
7409acf51cbSTaku Izumi 								.tx_packets += 1;
7419acf51cbSTaku Izumi 					adapter->stats64.tx_bytes += len;
7423c3bd4a9STaku Izumi 					hw->ep_shm_info[dest_epid].net_stats
7439acf51cbSTaku Izumi 								.tx_bytes += len;
7449acf51cbSTaku Izumi 				}
7459acf51cbSTaku Izumi 
7469acf51cbSTaku Izumi 				adapter->tx_retry_count = 0;
7479acf51cbSTaku Izumi 				ret = NETDEV_TX_OK;
7489acf51cbSTaku Izumi 			}
7499acf51cbSTaku Izumi 		}
7509acf51cbSTaku Izumi 	}
7519acf51cbSTaku Izumi 
7529acf51cbSTaku Izumi 	if (ret == NETDEV_TX_OK) {
7539acf51cbSTaku Izumi 		dev_kfree_skb(skb);
7549acf51cbSTaku Izumi 		if (is_multi) {
7559acf51cbSTaku Izumi 			adapter->stats64.tx_packets += 1;
7569acf51cbSTaku Izumi 			hw->ep_shm_info[my_epid].net_stats.tx_packets += 1;
7579acf51cbSTaku Izumi 			adapter->stats64.tx_bytes += 1;
7589acf51cbSTaku Izumi 			hw->ep_shm_info[my_epid].net_stats.tx_bytes += len;
7599acf51cbSTaku Izumi 		}
7609acf51cbSTaku Izumi 	}
7619acf51cbSTaku Izumi 
7629acf51cbSTaku Izumi 	return ret;
7639acf51cbSTaku Izumi }
7649acf51cbSTaku Izumi 
765bc1f4470Sstephen hemminger static void
766879bc9a3STaku Izumi fjes_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats)
767879bc9a3STaku Izumi {
768879bc9a3STaku Izumi 	struct fjes_adapter *adapter = netdev_priv(netdev);
769879bc9a3STaku Izumi 
770879bc9a3STaku Izumi 	memcpy(stats, &adapter->stats64, sizeof(struct rtnl_link_stats64));
771879bc9a3STaku Izumi }
772879bc9a3STaku Izumi 
773b9e23a67STaku Izumi static int fjes_change_mtu(struct net_device *netdev, int new_mtu)
774b9e23a67STaku Izumi {
77516bbec3aSTaku Izumi 	struct fjes_adapter *adapter = netdev_priv(netdev);
776b9e23a67STaku Izumi 	bool running = netif_running(netdev);
77716bbec3aSTaku Izumi 	struct fjes_hw *hw = &adapter->hw;
778bd5a2569STaku Izumi 	unsigned long flags;
77916bbec3aSTaku Izumi 	int ret = -EINVAL;
78016bbec3aSTaku Izumi 	int idx, epidx;
781b9e23a67STaku Izumi 
782b9e23a67STaku Izumi 	for (idx = 0; fjes_support_mtu[idx] != 0; idx++) {
783b9e23a67STaku Izumi 		if (new_mtu <= fjes_support_mtu[idx]) {
784b9e23a67STaku Izumi 			new_mtu = fjes_support_mtu[idx];
785b9e23a67STaku Izumi 			if (new_mtu == netdev->mtu)
786b9e23a67STaku Izumi 				return 0;
787b9e23a67STaku Izumi 
78816bbec3aSTaku Izumi 			ret = 0;
78916bbec3aSTaku Izumi 			break;
79016bbec3aSTaku Izumi 		}
79116bbec3aSTaku Izumi 	}
79216bbec3aSTaku Izumi 
79316bbec3aSTaku Izumi 	if (ret)
79416bbec3aSTaku Izumi 		return ret;
79516bbec3aSTaku Izumi 
79616bbec3aSTaku Izumi 	if (running) {
797bd5a2569STaku Izumi 		spin_lock_irqsave(&hw->rx_status_lock, flags);
79816bbec3aSTaku Izumi 		for (epidx = 0; epidx < hw->max_epid; epidx++) {
79916bbec3aSTaku Izumi 			if (epidx == hw->my_epid)
80016bbec3aSTaku Izumi 				continue;
80116bbec3aSTaku Izumi 			hw->ep_shm_info[epidx].tx.info->v1i.rx_status &=
80216bbec3aSTaku Izumi 				~FJES_RX_MTU_CHANGING_DONE;
80316bbec3aSTaku Izumi 		}
804bd5a2569STaku Izumi 		spin_unlock_irqrestore(&hw->rx_status_lock, flags);
805bd5a2569STaku Izumi 
80616bbec3aSTaku Izumi 		netif_tx_stop_all_queues(netdev);
80716bbec3aSTaku Izumi 		netif_carrier_off(netdev);
80816bbec3aSTaku Izumi 		cancel_work_sync(&adapter->tx_stall_task);
80916bbec3aSTaku Izumi 		napi_disable(&adapter->napi);
81016bbec3aSTaku Izumi 
81116bbec3aSTaku Izumi 		msleep(1000);
81216bbec3aSTaku Izumi 
81316bbec3aSTaku Izumi 		netif_tx_stop_all_queues(netdev);
81416bbec3aSTaku Izumi 	}
815b9e23a67STaku Izumi 
816b9e23a67STaku Izumi 	netdev->mtu = new_mtu;
817b9e23a67STaku Izumi 
81816bbec3aSTaku Izumi 	if (running) {
81916bbec3aSTaku Izumi 		for (epidx = 0; epidx < hw->max_epid; epidx++) {
82016bbec3aSTaku Izumi 			if (epidx == hw->my_epid)
82116bbec3aSTaku Izumi 				continue;
82216bbec3aSTaku Izumi 
823bd5a2569STaku Izumi 			spin_lock_irqsave(&hw->rx_status_lock, flags);
82416bbec3aSTaku Izumi 			fjes_hw_setup_epbuf(&hw->ep_shm_info[epidx].tx,
82516bbec3aSTaku Izumi 					    netdev->dev_addr,
82616bbec3aSTaku Izumi 					    netdev->mtu);
82716bbec3aSTaku Izumi 
82816bbec3aSTaku Izumi 			hw->ep_shm_info[epidx].tx.info->v1i.rx_status |=
82916bbec3aSTaku Izumi 				FJES_RX_MTU_CHANGING_DONE;
830bd5a2569STaku Izumi 			spin_unlock_irqrestore(&hw->rx_status_lock, flags);
83116bbec3aSTaku Izumi 		}
83216bbec3aSTaku Izumi 
83316bbec3aSTaku Izumi 		netif_tx_wake_all_queues(netdev);
83416bbec3aSTaku Izumi 		netif_carrier_on(netdev);
83516bbec3aSTaku Izumi 		napi_enable(&adapter->napi);
836bd5a2569STaku Izumi 		napi_schedule(&adapter->napi);
83716bbec3aSTaku Izumi 	}
838b9e23a67STaku Izumi 
839b9e23a67STaku Izumi 	return ret;
840b9e23a67STaku Izumi }
841b9e23a67STaku Izumi 
842*fa2aee65SUwe Kleine-König static void fjes_tx_retry(struct net_device *netdev, unsigned int txqueue)
843*fa2aee65SUwe Kleine-König {
844*fa2aee65SUwe Kleine-König 	struct netdev_queue *queue = netdev_get_tx_queue(netdev, 0);
845*fa2aee65SUwe Kleine-König 
846*fa2aee65SUwe Kleine-König 	netif_tx_wake_queue(queue);
847*fa2aee65SUwe Kleine-König }
848*fa2aee65SUwe Kleine-König 
8493e3feddaSTaku Izumi static int fjes_vlan_rx_add_vid(struct net_device *netdev,
8503e3feddaSTaku Izumi 				__be16 proto, u16 vid)
8513e3feddaSTaku Izumi {
8523e3feddaSTaku Izumi 	struct fjes_adapter *adapter = netdev_priv(netdev);
8533e3feddaSTaku Izumi 	bool ret = true;
8543e3feddaSTaku Izumi 	int epid;
8553e3feddaSTaku Izumi 
8563e3feddaSTaku Izumi 	for (epid = 0; epid < adapter->hw.max_epid; epid++) {
8573e3feddaSTaku Izumi 		if (epid == adapter->hw.my_epid)
8583e3feddaSTaku Izumi 			continue;
8593e3feddaSTaku Izumi 
8603e3feddaSTaku Izumi 		if (!fjes_hw_check_vlan_id(
8613e3feddaSTaku Izumi 			&adapter->hw.ep_shm_info[epid].tx, vid))
8623e3feddaSTaku Izumi 			ret = fjes_hw_set_vlan_id(
8633e3feddaSTaku Izumi 				&adapter->hw.ep_shm_info[epid].tx, vid);
8643e3feddaSTaku Izumi 	}
8653e3feddaSTaku Izumi 
8663e3feddaSTaku Izumi 	return ret ? 0 : -ENOSPC;
8673e3feddaSTaku Izumi }
8683e3feddaSTaku Izumi 
8693e3feddaSTaku Izumi static int fjes_vlan_rx_kill_vid(struct net_device *netdev,
8703e3feddaSTaku Izumi 				 __be16 proto, u16 vid)
8713e3feddaSTaku Izumi {
8723e3feddaSTaku Izumi 	struct fjes_adapter *adapter = netdev_priv(netdev);
8733e3feddaSTaku Izumi 	int epid;
8743e3feddaSTaku Izumi 
8753e3feddaSTaku Izumi 	for (epid = 0; epid < adapter->hw.max_epid; epid++) {
8763e3feddaSTaku Izumi 		if (epid == adapter->hw.my_epid)
8773e3feddaSTaku Izumi 			continue;
8783e3feddaSTaku Izumi 
8793e3feddaSTaku Izumi 		fjes_hw_del_vlan_id(&adapter->hw.ep_shm_info[epid].tx, vid);
8803e3feddaSTaku Izumi 	}
8813e3feddaSTaku Izumi 
8823e3feddaSTaku Izumi 	return 0;
8833e3feddaSTaku Izumi }
8843e3feddaSTaku Izumi 
885*fa2aee65SUwe Kleine-König static const struct net_device_ops fjes_netdev_ops = {
886*fa2aee65SUwe Kleine-König 	.ndo_open		= fjes_open,
887*fa2aee65SUwe Kleine-König 	.ndo_stop		= fjes_close,
888*fa2aee65SUwe Kleine-König 	.ndo_start_xmit		= fjes_xmit_frame,
889*fa2aee65SUwe Kleine-König 	.ndo_get_stats64	= fjes_get_stats64,
890*fa2aee65SUwe Kleine-König 	.ndo_change_mtu		= fjes_change_mtu,
891*fa2aee65SUwe Kleine-König 	.ndo_tx_timeout		= fjes_tx_retry,
892*fa2aee65SUwe Kleine-König 	.ndo_vlan_rx_add_vid	= fjes_vlan_rx_add_vid,
893*fa2aee65SUwe Kleine-König 	.ndo_vlan_rx_kill_vid = fjes_vlan_rx_kill_vid,
894*fa2aee65SUwe Kleine-König };
895*fa2aee65SUwe Kleine-König 
896*fa2aee65SUwe Kleine-König /* fjes_netdev_setup - netdevice initialization routine */
897*fa2aee65SUwe Kleine-König static void fjes_netdev_setup(struct net_device *netdev)
898cb79eaaeSTaku Izumi {
899*fa2aee65SUwe Kleine-König 	ether_setup(netdev);
900cb79eaaeSTaku Izumi 
901*fa2aee65SUwe Kleine-König 	netdev->watchdog_timeo = FJES_TX_RETRY_INTERVAL;
902*fa2aee65SUwe Kleine-König 	netdev->netdev_ops = &fjes_netdev_ops;
903*fa2aee65SUwe Kleine-König 	fjes_set_ethtool_ops(netdev);
904*fa2aee65SUwe Kleine-König 	netdev->mtu = fjes_support_mtu[3];
905*fa2aee65SUwe Kleine-König 	netdev->min_mtu = fjes_support_mtu[0];
906*fa2aee65SUwe Kleine-König 	netdev->max_mtu = fjes_support_mtu[3];
907*fa2aee65SUwe Kleine-König 	netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
908e5d486dcSTaku Izumi }
909e5d486dcSTaku Izumi 
91026585930STaku Izumi static int fjes_rxframe_search_exist(struct fjes_adapter *adapter,
91126585930STaku Izumi 				     int start_epid)
91226585930STaku Izumi {
91326585930STaku Izumi 	struct fjes_hw *hw = &adapter->hw;
91426585930STaku Izumi 	enum ep_partner_status pstatus;
91526585930STaku Izumi 	int max_epid, cur_epid;
91626585930STaku Izumi 	int i;
91726585930STaku Izumi 
91826585930STaku Izumi 	max_epid = hw->max_epid;
91926585930STaku Izumi 	start_epid = (start_epid + 1 + max_epid) % max_epid;
92026585930STaku Izumi 
92126585930STaku Izumi 	for (i = 0; i < max_epid; i++) {
92226585930STaku Izumi 		cur_epid = (start_epid + i) % max_epid;
92326585930STaku Izumi 		if (cur_epid == hw->my_epid)
92426585930STaku Izumi 			continue;
92526585930STaku Izumi 
92626585930STaku Izumi 		pstatus = fjes_hw_get_partner_ep_status(hw, cur_epid);
92726585930STaku Izumi 		if (pstatus == EP_PARTNER_SHARED) {
92826585930STaku Izumi 			if (!fjes_hw_epbuf_rx_is_empty(
92926585930STaku Izumi 				&hw->ep_shm_info[cur_epid].rx))
93026585930STaku Izumi 				return cur_epid;
93126585930STaku Izumi 		}
93226585930STaku Izumi 	}
93326585930STaku Izumi 	return -1;
93426585930STaku Izumi }
93526585930STaku Izumi 
93626585930STaku Izumi static void *fjes_rxframe_get(struct fjes_adapter *adapter, size_t *psize,
93726585930STaku Izumi 			      int *cur_epid)
93826585930STaku Izumi {
93926585930STaku Izumi 	void *frame;
94026585930STaku Izumi 
94126585930STaku Izumi 	*cur_epid = fjes_rxframe_search_exist(adapter, *cur_epid);
94226585930STaku Izumi 	if (*cur_epid < 0)
94326585930STaku Izumi 		return NULL;
94426585930STaku Izumi 
94526585930STaku Izumi 	frame =
94626585930STaku Izumi 	fjes_hw_epbuf_rx_curpkt_get_addr(
94726585930STaku Izumi 		&adapter->hw.ep_shm_info[*cur_epid].rx, psize);
94826585930STaku Izumi 
94926585930STaku Izumi 	return frame;
95026585930STaku Izumi }
95126585930STaku Izumi 
95226585930STaku Izumi static void fjes_rxframe_release(struct fjes_adapter *adapter, int cur_epid)
95326585930STaku Izumi {
95426585930STaku Izumi 	fjes_hw_epbuf_rx_curpkt_drop(&adapter->hw.ep_shm_info[cur_epid].rx);
95526585930STaku Izumi }
95626585930STaku Izumi 
95726585930STaku Izumi static int fjes_poll(struct napi_struct *napi, int budget)
95826585930STaku Izumi {
95926585930STaku Izumi 	struct fjes_adapter *adapter =
96026585930STaku Izumi 			container_of(napi, struct fjes_adapter, napi);
96126585930STaku Izumi 	struct net_device *netdev = napi->dev;
96226585930STaku Izumi 	struct fjes_hw *hw = &adapter->hw;
96326585930STaku Izumi 	struct sk_buff *skb;
96426585930STaku Izumi 	int work_done = 0;
96526585930STaku Izumi 	int cur_epid = 0;
96626585930STaku Izumi 	int epidx;
96726585930STaku Izumi 	size_t frame_len;
96826585930STaku Izumi 	void *frame;
96926585930STaku Izumi 
970bd5a2569STaku Izumi 	spin_lock(&hw->rx_status_lock);
97126585930STaku Izumi 	for (epidx = 0; epidx < hw->max_epid; epidx++) {
97226585930STaku Izumi 		if (epidx == hw->my_epid)
97326585930STaku Izumi 			continue;
97426585930STaku Izumi 
975bd5a2569STaku Izumi 		if (fjes_hw_get_partner_ep_status(hw, epidx) ==
976bd5a2569STaku Izumi 		    EP_PARTNER_SHARED)
977bd5a2569STaku Izumi 			adapter->hw.ep_shm_info[epidx]
978bd5a2569STaku Izumi 				   .tx.info->v1i.rx_status |= FJES_RX_POLL_WORK;
97926585930STaku Izumi 	}
980bd5a2569STaku Izumi 	spin_unlock(&hw->rx_status_lock);
98126585930STaku Izumi 
98226585930STaku Izumi 	while (work_done < budget) {
98326585930STaku Izumi 		prefetch(&adapter->hw);
98426585930STaku Izumi 		frame = fjes_rxframe_get(adapter, &frame_len, &cur_epid);
98526585930STaku Izumi 
98626585930STaku Izumi 		if (frame) {
98726585930STaku Izumi 			skb = napi_alloc_skb(napi, frame_len);
98826585930STaku Izumi 			if (!skb) {
98926585930STaku Izumi 				adapter->stats64.rx_dropped += 1;
99026585930STaku Izumi 				hw->ep_shm_info[cur_epid].net_stats
99126585930STaku Izumi 							 .rx_dropped += 1;
99226585930STaku Izumi 				adapter->stats64.rx_errors += 1;
99326585930STaku Izumi 				hw->ep_shm_info[cur_epid].net_stats
99426585930STaku Izumi 							 .rx_errors += 1;
99526585930STaku Izumi 			} else {
99659ae1d12SJohannes Berg 				skb_put_data(skb, frame, frame_len);
99726585930STaku Izumi 				skb->protocol = eth_type_trans(skb, netdev);
99826585930STaku Izumi 				skb->ip_summed = CHECKSUM_UNNECESSARY;
99926585930STaku Izumi 
100026585930STaku Izumi 				netif_receive_skb(skb);
100126585930STaku Izumi 
100226585930STaku Izumi 				work_done++;
100326585930STaku Izumi 
100426585930STaku Izumi 				adapter->stats64.rx_packets += 1;
100526585930STaku Izumi 				hw->ep_shm_info[cur_epid].net_stats
100626585930STaku Izumi 							 .rx_packets += 1;
100726585930STaku Izumi 				adapter->stats64.rx_bytes += frame_len;
100826585930STaku Izumi 				hw->ep_shm_info[cur_epid].net_stats
100926585930STaku Izumi 							 .rx_bytes += frame_len;
101026585930STaku Izumi 
101126585930STaku Izumi 				if (is_multicast_ether_addr(
101226585930STaku Izumi 					((struct ethhdr *)frame)->h_dest)) {
101326585930STaku Izumi 					adapter->stats64.multicast += 1;
101426585930STaku Izumi 					hw->ep_shm_info[cur_epid].net_stats
101526585930STaku Izumi 								 .multicast += 1;
101626585930STaku Izumi 				}
101726585930STaku Izumi 			}
101826585930STaku Izumi 
101926585930STaku Izumi 			fjes_rxframe_release(adapter, cur_epid);
102026585930STaku Izumi 			adapter->unset_rx_last = true;
102126585930STaku Izumi 		} else {
102226585930STaku Izumi 			break;
102326585930STaku Izumi 		}
102426585930STaku Izumi 	}
102526585930STaku Izumi 
102626585930STaku Izumi 	if (work_done < budget) {
10276ad20165SEric Dumazet 		napi_complete_done(napi, work_done);
102826585930STaku Izumi 
102926585930STaku Izumi 		if (adapter->unset_rx_last) {
103026585930STaku Izumi 			adapter->rx_last_jiffies = jiffies;
103126585930STaku Izumi 			adapter->unset_rx_last = false;
103226585930STaku Izumi 		}
103326585930STaku Izumi 
103426585930STaku Izumi 		if (((long)jiffies - (long)adapter->rx_last_jiffies) < 3) {
103526585930STaku Izumi 			napi_reschedule(napi);
103626585930STaku Izumi 		} else {
1037bd5a2569STaku Izumi 			spin_lock(&hw->rx_status_lock);
103826585930STaku Izumi 			for (epidx = 0; epidx < hw->max_epid; epidx++) {
103926585930STaku Izumi 				if (epidx == hw->my_epid)
104026585930STaku Izumi 					continue;
1041bd5a2569STaku Izumi 				if (fjes_hw_get_partner_ep_status(hw, epidx) ==
1042bd5a2569STaku Izumi 				    EP_PARTNER_SHARED)
1043bd5a2569STaku Izumi 					adapter->hw.ep_shm_info[epidx].tx
1044bd5a2569STaku Izumi 						   .info->v1i.rx_status &=
104526585930STaku Izumi 						~FJES_RX_POLL_WORK;
104626585930STaku Izumi 			}
1047bd5a2569STaku Izumi 			spin_unlock(&hw->rx_status_lock);
104826585930STaku Izumi 
104926585930STaku Izumi 			fjes_hw_set_irqmask(hw, REG_ICTL_MASK_RX_DATA, false);
105026585930STaku Izumi 		}
105126585930STaku Izumi 	}
105226585930STaku Izumi 
105326585930STaku Izumi 	return work_done;
105426585930STaku Izumi }
105526585930STaku Izumi 
1056*fa2aee65SUwe Kleine-König static int fjes_sw_init(struct fjes_adapter *adapter)
1057*fa2aee65SUwe Kleine-König {
1058*fa2aee65SUwe Kleine-König 	struct net_device *netdev = adapter->netdev;
1059*fa2aee65SUwe Kleine-König 
1060*fa2aee65SUwe Kleine-König 	netif_napi_add(netdev, &adapter->napi, fjes_poll, 64);
1061*fa2aee65SUwe Kleine-König 
1062*fa2aee65SUwe Kleine-König 	return 0;
1063*fa2aee65SUwe Kleine-König }
1064*fa2aee65SUwe Kleine-König 
1065*fa2aee65SUwe Kleine-König static void fjes_force_close_task(struct work_struct *work)
1066*fa2aee65SUwe Kleine-König {
1067*fa2aee65SUwe Kleine-König 	struct fjes_adapter *adapter = container_of(work,
1068*fa2aee65SUwe Kleine-König 			struct fjes_adapter, force_close_task);
1069*fa2aee65SUwe Kleine-König 	struct net_device *netdev = adapter->netdev;
1070*fa2aee65SUwe Kleine-König 
1071*fa2aee65SUwe Kleine-König 	rtnl_lock();
1072*fa2aee65SUwe Kleine-König 	dev_close(netdev);
1073*fa2aee65SUwe Kleine-König 	rtnl_unlock();
1074*fa2aee65SUwe Kleine-König }
1075*fa2aee65SUwe Kleine-König 
1076*fa2aee65SUwe Kleine-König static void fjes_tx_stall_task(struct work_struct *work)
1077*fa2aee65SUwe Kleine-König {
1078*fa2aee65SUwe Kleine-König 	struct fjes_adapter *adapter = container_of(work,
1079*fa2aee65SUwe Kleine-König 			struct fjes_adapter, tx_stall_task);
1080*fa2aee65SUwe Kleine-König 	struct net_device *netdev = adapter->netdev;
1081*fa2aee65SUwe Kleine-König 	struct fjes_hw *hw = &adapter->hw;
1082*fa2aee65SUwe Kleine-König 	int all_queue_available, sendable;
1083*fa2aee65SUwe Kleine-König 	enum ep_partner_status pstatus;
1084*fa2aee65SUwe Kleine-König 	int max_epid, my_epid, epid;
1085*fa2aee65SUwe Kleine-König 	union ep_buffer_info *info;
1086*fa2aee65SUwe Kleine-König 	int i;
1087*fa2aee65SUwe Kleine-König 
1088*fa2aee65SUwe Kleine-König 	if (((long)jiffies -
1089*fa2aee65SUwe Kleine-König 		dev_trans_start(netdev)) > FJES_TX_TX_STALL_TIMEOUT) {
1090*fa2aee65SUwe Kleine-König 		netif_wake_queue(netdev);
1091*fa2aee65SUwe Kleine-König 		return;
1092*fa2aee65SUwe Kleine-König 	}
1093*fa2aee65SUwe Kleine-König 
1094*fa2aee65SUwe Kleine-König 	my_epid = hw->my_epid;
1095*fa2aee65SUwe Kleine-König 	max_epid = hw->max_epid;
1096*fa2aee65SUwe Kleine-König 
1097*fa2aee65SUwe Kleine-König 	for (i = 0; i < 5; i++) {
1098*fa2aee65SUwe Kleine-König 		all_queue_available = 1;
1099*fa2aee65SUwe Kleine-König 
1100*fa2aee65SUwe Kleine-König 		for (epid = 0; epid < max_epid; epid++) {
1101*fa2aee65SUwe Kleine-König 			if (my_epid == epid)
1102*fa2aee65SUwe Kleine-König 				continue;
1103*fa2aee65SUwe Kleine-König 
1104*fa2aee65SUwe Kleine-König 			pstatus = fjes_hw_get_partner_ep_status(hw, epid);
1105*fa2aee65SUwe Kleine-König 			sendable = (pstatus == EP_PARTNER_SHARED);
1106*fa2aee65SUwe Kleine-König 			if (!sendable)
1107*fa2aee65SUwe Kleine-König 				continue;
1108*fa2aee65SUwe Kleine-König 
1109*fa2aee65SUwe Kleine-König 			info = adapter->hw.ep_shm_info[epid].tx.info;
1110*fa2aee65SUwe Kleine-König 
1111*fa2aee65SUwe Kleine-König 			if (!(info->v1i.rx_status & FJES_RX_MTU_CHANGING_DONE))
1112*fa2aee65SUwe Kleine-König 				return;
1113*fa2aee65SUwe Kleine-König 
1114*fa2aee65SUwe Kleine-König 			if (EP_RING_FULL(info->v1i.head, info->v1i.tail,
1115*fa2aee65SUwe Kleine-König 					 info->v1i.count_max)) {
1116*fa2aee65SUwe Kleine-König 				all_queue_available = 0;
1117*fa2aee65SUwe Kleine-König 				break;
1118*fa2aee65SUwe Kleine-König 			}
1119*fa2aee65SUwe Kleine-König 		}
1120*fa2aee65SUwe Kleine-König 
1121*fa2aee65SUwe Kleine-König 		if (all_queue_available) {
1122*fa2aee65SUwe Kleine-König 			netif_wake_queue(netdev);
1123*fa2aee65SUwe Kleine-König 			return;
1124*fa2aee65SUwe Kleine-König 		}
1125*fa2aee65SUwe Kleine-König 	}
1126*fa2aee65SUwe Kleine-König 
1127*fa2aee65SUwe Kleine-König 	usleep_range(50, 100);
1128*fa2aee65SUwe Kleine-König 
1129*fa2aee65SUwe Kleine-König 	queue_work(adapter->txrx_wq, &adapter->tx_stall_task);
1130*fa2aee65SUwe Kleine-König }
1131*fa2aee65SUwe Kleine-König 
1132*fa2aee65SUwe Kleine-König static void fjes_raise_intr_rxdata_task(struct work_struct *work)
1133*fa2aee65SUwe Kleine-König {
1134*fa2aee65SUwe Kleine-König 	struct fjes_adapter *adapter = container_of(work,
1135*fa2aee65SUwe Kleine-König 			struct fjes_adapter, raise_intr_rxdata_task);
1136*fa2aee65SUwe Kleine-König 	struct fjes_hw *hw = &adapter->hw;
1137*fa2aee65SUwe Kleine-König 	enum ep_partner_status pstatus;
1138*fa2aee65SUwe Kleine-König 	int max_epid, my_epid, epid;
1139*fa2aee65SUwe Kleine-König 
1140*fa2aee65SUwe Kleine-König 	my_epid = hw->my_epid;
1141*fa2aee65SUwe Kleine-König 	max_epid = hw->max_epid;
1142*fa2aee65SUwe Kleine-König 
1143*fa2aee65SUwe Kleine-König 	for (epid = 0; epid < max_epid; epid++)
1144*fa2aee65SUwe Kleine-König 		hw->ep_shm_info[epid].tx_status_work = 0;
1145*fa2aee65SUwe Kleine-König 
1146*fa2aee65SUwe Kleine-König 	for (epid = 0; epid < max_epid; epid++) {
1147*fa2aee65SUwe Kleine-König 		if (epid == my_epid)
1148*fa2aee65SUwe Kleine-König 			continue;
1149*fa2aee65SUwe Kleine-König 
1150*fa2aee65SUwe Kleine-König 		pstatus = fjes_hw_get_partner_ep_status(hw, epid);
1151*fa2aee65SUwe Kleine-König 		if (pstatus == EP_PARTNER_SHARED) {
1152*fa2aee65SUwe Kleine-König 			hw->ep_shm_info[epid].tx_status_work =
1153*fa2aee65SUwe Kleine-König 				hw->ep_shm_info[epid].tx.info->v1i.tx_status;
1154*fa2aee65SUwe Kleine-König 
1155*fa2aee65SUwe Kleine-König 			if (hw->ep_shm_info[epid].tx_status_work ==
1156*fa2aee65SUwe Kleine-König 				FJES_TX_DELAY_SEND_PENDING) {
1157*fa2aee65SUwe Kleine-König 				hw->ep_shm_info[epid].tx.info->v1i.tx_status =
1158*fa2aee65SUwe Kleine-König 					FJES_TX_DELAY_SEND_NONE;
1159*fa2aee65SUwe Kleine-König 			}
1160*fa2aee65SUwe Kleine-König 		}
1161*fa2aee65SUwe Kleine-König 	}
1162*fa2aee65SUwe Kleine-König 
1163*fa2aee65SUwe Kleine-König 	for (epid = 0; epid < max_epid; epid++) {
1164*fa2aee65SUwe Kleine-König 		if (epid == my_epid)
1165*fa2aee65SUwe Kleine-König 			continue;
1166*fa2aee65SUwe Kleine-König 
1167*fa2aee65SUwe Kleine-König 		pstatus = fjes_hw_get_partner_ep_status(hw, epid);
1168*fa2aee65SUwe Kleine-König 		if ((hw->ep_shm_info[epid].tx_status_work ==
1169*fa2aee65SUwe Kleine-König 		     FJES_TX_DELAY_SEND_PENDING) &&
1170*fa2aee65SUwe Kleine-König 		    (pstatus == EP_PARTNER_SHARED) &&
1171*fa2aee65SUwe Kleine-König 		    !(hw->ep_shm_info[epid].rx.info->v1i.rx_status &
1172*fa2aee65SUwe Kleine-König 		      FJES_RX_POLL_WORK)) {
1173*fa2aee65SUwe Kleine-König 			fjes_hw_raise_interrupt(hw, epid,
1174*fa2aee65SUwe Kleine-König 						REG_ICTL_MASK_RX_DATA);
1175*fa2aee65SUwe Kleine-König 			hw->ep_shm_info[epid].ep_stats.send_intr_rx += 1;
1176*fa2aee65SUwe Kleine-König 		}
1177*fa2aee65SUwe Kleine-König 	}
1178*fa2aee65SUwe Kleine-König 
1179*fa2aee65SUwe Kleine-König 	usleep_range(500, 1000);
1180*fa2aee65SUwe Kleine-König }
1181*fa2aee65SUwe Kleine-König 
1182*fa2aee65SUwe Kleine-König static void fjes_watch_unshare_task(struct work_struct *work)
1183*fa2aee65SUwe Kleine-König {
1184*fa2aee65SUwe Kleine-König 	struct fjes_adapter *adapter =
1185*fa2aee65SUwe Kleine-König 	container_of(work, struct fjes_adapter, unshare_watch_task);
1186*fa2aee65SUwe Kleine-König 
1187*fa2aee65SUwe Kleine-König 	struct net_device *netdev = adapter->netdev;
1188*fa2aee65SUwe Kleine-König 	struct fjes_hw *hw = &adapter->hw;
1189*fa2aee65SUwe Kleine-König 
1190*fa2aee65SUwe Kleine-König 	int unshare_watch, unshare_reserve;
1191*fa2aee65SUwe Kleine-König 	int max_epid, my_epid, epidx;
1192*fa2aee65SUwe Kleine-König 	int stop_req, stop_req_done;
1193*fa2aee65SUwe Kleine-König 	ulong unshare_watch_bitmask;
1194*fa2aee65SUwe Kleine-König 	unsigned long flags;
1195*fa2aee65SUwe Kleine-König 	int wait_time = 0;
1196*fa2aee65SUwe Kleine-König 	int is_shared;
1197*fa2aee65SUwe Kleine-König 	int ret;
1198*fa2aee65SUwe Kleine-König 
1199*fa2aee65SUwe Kleine-König 	my_epid = hw->my_epid;
1200*fa2aee65SUwe Kleine-König 	max_epid = hw->max_epid;
1201*fa2aee65SUwe Kleine-König 
1202*fa2aee65SUwe Kleine-König 	unshare_watch_bitmask = adapter->unshare_watch_bitmask;
1203*fa2aee65SUwe Kleine-König 	adapter->unshare_watch_bitmask = 0;
1204*fa2aee65SUwe Kleine-König 
1205*fa2aee65SUwe Kleine-König 	while ((unshare_watch_bitmask || hw->txrx_stop_req_bit) &&
1206*fa2aee65SUwe Kleine-König 	       (wait_time < 3000)) {
1207*fa2aee65SUwe Kleine-König 		for (epidx = 0; epidx < max_epid; epidx++) {
1208*fa2aee65SUwe Kleine-König 			if (epidx == my_epid)
1209*fa2aee65SUwe Kleine-König 				continue;
1210*fa2aee65SUwe Kleine-König 
1211*fa2aee65SUwe Kleine-König 			is_shared = fjes_hw_epid_is_shared(hw->hw_info.share,
1212*fa2aee65SUwe Kleine-König 							   epidx);
1213*fa2aee65SUwe Kleine-König 
1214*fa2aee65SUwe Kleine-König 			stop_req = test_bit(epidx, &hw->txrx_stop_req_bit);
1215*fa2aee65SUwe Kleine-König 
1216*fa2aee65SUwe Kleine-König 			stop_req_done = hw->ep_shm_info[epidx].rx.info->v1i.rx_status &
1217*fa2aee65SUwe Kleine-König 					FJES_RX_STOP_REQ_DONE;
1218*fa2aee65SUwe Kleine-König 
1219*fa2aee65SUwe Kleine-König 			unshare_watch = test_bit(epidx, &unshare_watch_bitmask);
1220*fa2aee65SUwe Kleine-König 
1221*fa2aee65SUwe Kleine-König 			unshare_reserve = test_bit(epidx,
1222*fa2aee65SUwe Kleine-König 						   &hw->hw_info.buffer_unshare_reserve_bit);
1223*fa2aee65SUwe Kleine-König 
1224*fa2aee65SUwe Kleine-König 			if ((!stop_req ||
1225*fa2aee65SUwe Kleine-König 			     (is_shared && (!is_shared || !stop_req_done))) &&
1226*fa2aee65SUwe Kleine-König 			    (is_shared || !unshare_watch || !unshare_reserve))
1227*fa2aee65SUwe Kleine-König 				continue;
1228*fa2aee65SUwe Kleine-König 
1229*fa2aee65SUwe Kleine-König 			mutex_lock(&hw->hw_info.lock);
1230*fa2aee65SUwe Kleine-König 			ret = fjes_hw_unregister_buff_addr(hw, epidx);
1231*fa2aee65SUwe Kleine-König 			switch (ret) {
1232*fa2aee65SUwe Kleine-König 			case 0:
1233*fa2aee65SUwe Kleine-König 				break;
1234*fa2aee65SUwe Kleine-König 			case -ENOMSG:
1235*fa2aee65SUwe Kleine-König 			case -EBUSY:
1236*fa2aee65SUwe Kleine-König 			default:
1237*fa2aee65SUwe Kleine-König 				if (!work_pending(
1238*fa2aee65SUwe Kleine-König 					&adapter->force_close_task)) {
1239*fa2aee65SUwe Kleine-König 					adapter->force_reset = true;
1240*fa2aee65SUwe Kleine-König 					schedule_work(
1241*fa2aee65SUwe Kleine-König 						&adapter->force_close_task);
1242*fa2aee65SUwe Kleine-König 				}
1243*fa2aee65SUwe Kleine-König 				break;
1244*fa2aee65SUwe Kleine-König 			}
1245*fa2aee65SUwe Kleine-König 			mutex_unlock(&hw->hw_info.lock);
1246*fa2aee65SUwe Kleine-König 			hw->ep_shm_info[epidx].ep_stats
1247*fa2aee65SUwe Kleine-König 					.com_unregist_buf_exec += 1;
1248*fa2aee65SUwe Kleine-König 
1249*fa2aee65SUwe Kleine-König 			spin_lock_irqsave(&hw->rx_status_lock, flags);
1250*fa2aee65SUwe Kleine-König 			fjes_hw_setup_epbuf(&hw->ep_shm_info[epidx].tx,
1251*fa2aee65SUwe Kleine-König 					    netdev->dev_addr, netdev->mtu);
1252*fa2aee65SUwe Kleine-König 			spin_unlock_irqrestore(&hw->rx_status_lock, flags);
1253*fa2aee65SUwe Kleine-König 
1254*fa2aee65SUwe Kleine-König 			clear_bit(epidx, &hw->txrx_stop_req_bit);
1255*fa2aee65SUwe Kleine-König 			clear_bit(epidx, &unshare_watch_bitmask);
1256*fa2aee65SUwe Kleine-König 			clear_bit(epidx,
1257*fa2aee65SUwe Kleine-König 				  &hw->hw_info.buffer_unshare_reserve_bit);
1258*fa2aee65SUwe Kleine-König 		}
1259*fa2aee65SUwe Kleine-König 
1260*fa2aee65SUwe Kleine-König 		msleep(100);
1261*fa2aee65SUwe Kleine-König 		wait_time += 100;
1262*fa2aee65SUwe Kleine-König 	}
1263*fa2aee65SUwe Kleine-König 
1264*fa2aee65SUwe Kleine-König 	if (hw->hw_info.buffer_unshare_reserve_bit) {
1265*fa2aee65SUwe Kleine-König 		for (epidx = 0; epidx < max_epid; epidx++) {
1266*fa2aee65SUwe Kleine-König 			if (epidx == my_epid)
1267*fa2aee65SUwe Kleine-König 				continue;
1268*fa2aee65SUwe Kleine-König 
1269*fa2aee65SUwe Kleine-König 			if (test_bit(epidx,
1270*fa2aee65SUwe Kleine-König 				     &hw->hw_info.buffer_unshare_reserve_bit)) {
1271*fa2aee65SUwe Kleine-König 				mutex_lock(&hw->hw_info.lock);
1272*fa2aee65SUwe Kleine-König 
1273*fa2aee65SUwe Kleine-König 				ret = fjes_hw_unregister_buff_addr(hw, epidx);
1274*fa2aee65SUwe Kleine-König 				switch (ret) {
1275*fa2aee65SUwe Kleine-König 				case 0:
1276*fa2aee65SUwe Kleine-König 					break;
1277*fa2aee65SUwe Kleine-König 				case -ENOMSG:
1278*fa2aee65SUwe Kleine-König 				case -EBUSY:
1279*fa2aee65SUwe Kleine-König 				default:
1280*fa2aee65SUwe Kleine-König 					if (!work_pending(
1281*fa2aee65SUwe Kleine-König 						&adapter->force_close_task)) {
1282*fa2aee65SUwe Kleine-König 						adapter->force_reset = true;
1283*fa2aee65SUwe Kleine-König 						schedule_work(
1284*fa2aee65SUwe Kleine-König 							&adapter->force_close_task);
1285*fa2aee65SUwe Kleine-König 					}
1286*fa2aee65SUwe Kleine-König 					break;
1287*fa2aee65SUwe Kleine-König 				}
1288*fa2aee65SUwe Kleine-König 				mutex_unlock(&hw->hw_info.lock);
1289*fa2aee65SUwe Kleine-König 
1290*fa2aee65SUwe Kleine-König 				hw->ep_shm_info[epidx].ep_stats
1291*fa2aee65SUwe Kleine-König 					.com_unregist_buf_exec += 1;
1292*fa2aee65SUwe Kleine-König 
1293*fa2aee65SUwe Kleine-König 				spin_lock_irqsave(&hw->rx_status_lock, flags);
1294*fa2aee65SUwe Kleine-König 				fjes_hw_setup_epbuf(
1295*fa2aee65SUwe Kleine-König 					&hw->ep_shm_info[epidx].tx,
1296*fa2aee65SUwe Kleine-König 					netdev->dev_addr, netdev->mtu);
1297*fa2aee65SUwe Kleine-König 				spin_unlock_irqrestore(&hw->rx_status_lock,
1298*fa2aee65SUwe Kleine-König 						       flags);
1299*fa2aee65SUwe Kleine-König 
1300*fa2aee65SUwe Kleine-König 				clear_bit(epidx, &hw->txrx_stop_req_bit);
1301*fa2aee65SUwe Kleine-König 				clear_bit(epidx, &unshare_watch_bitmask);
1302*fa2aee65SUwe Kleine-König 				clear_bit(epidx, &hw->hw_info.buffer_unshare_reserve_bit);
1303*fa2aee65SUwe Kleine-König 			}
1304*fa2aee65SUwe Kleine-König 
1305*fa2aee65SUwe Kleine-König 			if (test_bit(epidx, &unshare_watch_bitmask)) {
1306*fa2aee65SUwe Kleine-König 				spin_lock_irqsave(&hw->rx_status_lock, flags);
1307*fa2aee65SUwe Kleine-König 				hw->ep_shm_info[epidx].tx.info->v1i.rx_status &=
1308*fa2aee65SUwe Kleine-König 						~FJES_RX_STOP_REQ_DONE;
1309*fa2aee65SUwe Kleine-König 				spin_unlock_irqrestore(&hw->rx_status_lock,
1310*fa2aee65SUwe Kleine-König 						       flags);
1311*fa2aee65SUwe Kleine-König 			}
1312*fa2aee65SUwe Kleine-König 		}
1313*fa2aee65SUwe Kleine-König 	}
1314*fa2aee65SUwe Kleine-König }
1315*fa2aee65SUwe Kleine-König 
1316*fa2aee65SUwe Kleine-König static void fjes_irq_watch_task(struct work_struct *work)
1317*fa2aee65SUwe Kleine-König {
1318*fa2aee65SUwe Kleine-König 	struct fjes_adapter *adapter = container_of(to_delayed_work(work),
1319*fa2aee65SUwe Kleine-König 			struct fjes_adapter, interrupt_watch_task);
1320*fa2aee65SUwe Kleine-König 
1321*fa2aee65SUwe Kleine-König 	local_irq_disable();
1322*fa2aee65SUwe Kleine-König 	fjes_intr(adapter->hw.hw_res.irq, adapter);
1323*fa2aee65SUwe Kleine-König 	local_irq_enable();
1324*fa2aee65SUwe Kleine-König 
1325*fa2aee65SUwe Kleine-König 	if (fjes_rxframe_search_exist(adapter, 0) >= 0)
1326*fa2aee65SUwe Kleine-König 		napi_schedule(&adapter->napi);
1327*fa2aee65SUwe Kleine-König 
1328*fa2aee65SUwe Kleine-König 	if (adapter->interrupt_watch_enable) {
1329*fa2aee65SUwe Kleine-König 		if (!delayed_work_pending(&adapter->interrupt_watch_task))
1330*fa2aee65SUwe Kleine-König 			queue_delayed_work(adapter->control_wq,
1331*fa2aee65SUwe Kleine-König 					   &adapter->interrupt_watch_task,
1332*fa2aee65SUwe Kleine-König 					   FJES_IRQ_WATCH_DELAY);
1333*fa2aee65SUwe Kleine-König 	}
1334*fa2aee65SUwe Kleine-König }
1335*fa2aee65SUwe Kleine-König 
1336658d439bSTaku Izumi /* fjes_probe - Device Initialization Routine */
1337658d439bSTaku Izumi static int fjes_probe(struct platform_device *plat_dev)
1338658d439bSTaku Izumi {
13392fcbca68STaku Izumi 	struct fjes_adapter *adapter;
13402fcbca68STaku Izumi 	struct net_device *netdev;
13412fcbca68STaku Izumi 	struct resource *res;
13422fcbca68STaku Izumi 	struct fjes_hw *hw;
1343ed088907SJakub Kicinski 	u8 addr[ETH_ALEN];
13442fcbca68STaku Izumi 	int err;
13452fcbca68STaku Izumi 
13462fcbca68STaku Izumi 	err = -ENOMEM;
13472fcbca68STaku Izumi 	netdev = alloc_netdev_mq(sizeof(struct fjes_adapter), "es%d",
13482fcbca68STaku Izumi 				 NET_NAME_UNKNOWN, fjes_netdev_setup,
13492fcbca68STaku Izumi 				 FJES_MAX_QUEUES);
13502fcbca68STaku Izumi 
13512fcbca68STaku Izumi 	if (!netdev)
13522fcbca68STaku Izumi 		goto err_out;
13532fcbca68STaku Izumi 
13542fcbca68STaku Izumi 	SET_NETDEV_DEV(netdev, &plat_dev->dev);
13552fcbca68STaku Izumi 
13562fcbca68STaku Izumi 	dev_set_drvdata(&plat_dev->dev, netdev);
13572fcbca68STaku Izumi 	adapter = netdev_priv(netdev);
13582fcbca68STaku Izumi 	adapter->netdev = netdev;
13592fcbca68STaku Izumi 	adapter->plat_dev = plat_dev;
13602fcbca68STaku Izumi 	hw = &adapter->hw;
13612fcbca68STaku Izumi 	hw->back = adapter;
13622fcbca68STaku Izumi 
13632fcbca68STaku Izumi 	/* setup the private structure */
13642fcbca68STaku Izumi 	err = fjes_sw_init(adapter);
13652fcbca68STaku Izumi 	if (err)
13662fcbca68STaku Izumi 		goto err_free_netdev;
13672fcbca68STaku Izumi 
1368ff5b4210STaku Izumi 	INIT_WORK(&adapter->force_close_task, fjes_force_close_task);
13692fcbca68STaku Izumi 	adapter->force_reset = false;
13702fcbca68STaku Izumi 	adapter->open_guard = false;
13712fcbca68STaku Izumi 
1372f2edc4e1SBhaktipriya Shridhar 	adapter->txrx_wq = alloc_workqueue(DRV_NAME "/txrx", WQ_MEM_RECLAIM, 0);
137385ac30faSWill Deacon 	if (unlikely(!adapter->txrx_wq)) {
137485ac30faSWill Deacon 		err = -ENOMEM;
137585ac30faSWill Deacon 		goto err_free_netdev;
137685ac30faSWill Deacon 	}
137785ac30faSWill Deacon 
1378f2edc4e1SBhaktipriya Shridhar 	adapter->control_wq = alloc_workqueue(DRV_NAME "/control",
1379f2edc4e1SBhaktipriya Shridhar 					      WQ_MEM_RECLAIM, 0);
138085ac30faSWill Deacon 	if (unlikely(!adapter->control_wq)) {
138185ac30faSWill Deacon 		err = -ENOMEM;
138285ac30faSWill Deacon 		goto err_free_txrx_wq;
138385ac30faSWill Deacon 	}
1384b772b9dcSTaku Izumi 
1385ac63b947STaku Izumi 	INIT_WORK(&adapter->tx_stall_task, fjes_tx_stall_task);
1386b772b9dcSTaku Izumi 	INIT_WORK(&adapter->raise_intr_rxdata_task,
1387b772b9dcSTaku Izumi 		  fjes_raise_intr_rxdata_task);
13888fc4cadbSTaku Izumi 	INIT_WORK(&adapter->unshare_watch_task, fjes_watch_unshare_task);
13898fc4cadbSTaku Izumi 	adapter->unshare_watch_bitmask = 0;
1390b772b9dcSTaku Izumi 
13918edb62a8STaku Izumi 	INIT_DELAYED_WORK(&adapter->interrupt_watch_task, fjes_irq_watch_task);
13928edb62a8STaku Izumi 	adapter->interrupt_watch_enable = false;
13938edb62a8STaku Izumi 
13942fcbca68STaku Izumi 	res = platform_get_resource(plat_dev, IORESOURCE_MEM, 0);
1395f18c1181SYang Yingliang 	if (!res) {
1396f18c1181SYang Yingliang 		err = -EINVAL;
1397f18c1181SYang Yingliang 		goto err_free_control_wq;
1398f18c1181SYang Yingliang 	}
13992fcbca68STaku Izumi 	hw->hw_res.start = res->start;
1400e0897ae3SVaishali Thakkar 	hw->hw_res.size = resource_size(res);
14012fcbca68STaku Izumi 	hw->hw_res.irq = platform_get_irq(plat_dev, 0);
1402db6d6afeSJiasheng Jiang 	if (hw->hw_res.irq < 0) {
1403db6d6afeSJiasheng Jiang 		err = hw->hw_res.irq;
1404db6d6afeSJiasheng Jiang 		goto err_free_control_wq;
1405db6d6afeSJiasheng Jiang 	}
1406db6d6afeSJiasheng Jiang 
14072fcbca68STaku Izumi 	err = fjes_hw_init(&adapter->hw);
14082fcbca68STaku Izumi 	if (err)
140985ac30faSWill Deacon 		goto err_free_control_wq;
14102fcbca68STaku Izumi 
14112fcbca68STaku Izumi 	/* setup MAC address (02:00:00:00:00:[epid])*/
1412ed088907SJakub Kicinski 	addr[0] = 2;
1413ed088907SJakub Kicinski 	addr[1] = 0;
1414ed088907SJakub Kicinski 	addr[2] = 0;
1415ed088907SJakub Kicinski 	addr[3] = 0;
1416ed088907SJakub Kicinski 	addr[4] = 0;
1417ed088907SJakub Kicinski 	addr[5] = hw->my_epid; /* EPID */
1418ed088907SJakub Kicinski 	eth_hw_addr_set(netdev, addr);
14192fcbca68STaku Izumi 
14202fcbca68STaku Izumi 	err = register_netdev(netdev);
14212fcbca68STaku Izumi 	if (err)
14222fcbca68STaku Izumi 		goto err_hw_exit;
14232fcbca68STaku Izumi 
14242fcbca68STaku Izumi 	netif_carrier_off(netdev);
14252fcbca68STaku Izumi 
1426c753119eSTaku Izumi 	fjes_dbg_adapter_init(adapter);
1427c753119eSTaku Izumi 
1428658d439bSTaku Izumi 	return 0;
14292fcbca68STaku Izumi 
14302fcbca68STaku Izumi err_hw_exit:
14312fcbca68STaku Izumi 	fjes_hw_exit(&adapter->hw);
143285ac30faSWill Deacon err_free_control_wq:
143385ac30faSWill Deacon 	destroy_workqueue(adapter->control_wq);
143485ac30faSWill Deacon err_free_txrx_wq:
143585ac30faSWill Deacon 	destroy_workqueue(adapter->txrx_wq);
14362fcbca68STaku Izumi err_free_netdev:
14372fcbca68STaku Izumi 	free_netdev(netdev);
14382fcbca68STaku Izumi err_out:
14392fcbca68STaku Izumi 	return err;
1440658d439bSTaku Izumi }
1441658d439bSTaku Izumi 
1442658d439bSTaku Izumi /* fjes_remove - Device Removal Routine */
1443658d439bSTaku Izumi static int fjes_remove(struct platform_device *plat_dev)
1444658d439bSTaku Izumi {
14452fcbca68STaku Izumi 	struct net_device *netdev = dev_get_drvdata(&plat_dev->dev);
14462fcbca68STaku Izumi 	struct fjes_adapter *adapter = netdev_priv(netdev);
14472fcbca68STaku Izumi 	struct fjes_hw *hw = &adapter->hw;
14482fcbca68STaku Izumi 
1449c753119eSTaku Izumi 	fjes_dbg_adapter_exit(adapter);
1450c753119eSTaku Izumi 
14518edb62a8STaku Izumi 	cancel_delayed_work_sync(&adapter->interrupt_watch_task);
14528fc4cadbSTaku Izumi 	cancel_work_sync(&adapter->unshare_watch_task);
1453b772b9dcSTaku Izumi 	cancel_work_sync(&adapter->raise_intr_rxdata_task);
1454ac63b947STaku Izumi 	cancel_work_sync(&adapter->tx_stall_task);
14558edb62a8STaku Izumi 	if (adapter->control_wq)
14568edb62a8STaku Izumi 		destroy_workqueue(adapter->control_wq);
1457b772b9dcSTaku Izumi 	if (adapter->txrx_wq)
1458b772b9dcSTaku Izumi 		destroy_workqueue(adapter->txrx_wq);
1459b772b9dcSTaku Izumi 
14602fcbca68STaku Izumi 	unregister_netdev(netdev);
14612fcbca68STaku Izumi 
14622fcbca68STaku Izumi 	fjes_hw_exit(hw);
14632fcbca68STaku Izumi 
146426585930STaku Izumi 	netif_napi_del(&adapter->napi);
146526585930STaku Izumi 
14662fcbca68STaku Izumi 	free_netdev(netdev);
14672fcbca68STaku Izumi 
1468658d439bSTaku Izumi 	return 0;
1469658d439bSTaku Izumi }
1470658d439bSTaku Izumi 
1471*fa2aee65SUwe Kleine-König static struct platform_driver fjes_driver = {
1472*fa2aee65SUwe Kleine-König 	.driver = {
1473*fa2aee65SUwe Kleine-König 		.name = DRV_NAME,
1474*fa2aee65SUwe Kleine-König 	},
1475*fa2aee65SUwe Kleine-König 	.probe = fjes_probe,
1476*fa2aee65SUwe Kleine-König 	.remove = fjes_remove,
1477*fa2aee65SUwe Kleine-König };
14788fc4cadbSTaku Izumi 
1479ac23d3caSYasuaki Ishimatsu static acpi_status
1480ac23d3caSYasuaki Ishimatsu acpi_find_extended_socket_device(acpi_handle obj_handle, u32 level,
1481ac23d3caSYasuaki Ishimatsu 				 void *context, void **return_value)
1482ac23d3caSYasuaki Ishimatsu {
1483ac23d3caSYasuaki Ishimatsu 	struct acpi_device *device;
1484ac23d3caSYasuaki Ishimatsu 	bool *found = context;
1485ac23d3caSYasuaki Ishimatsu 
148652dae93fSRafael J. Wysocki 	device = acpi_fetch_acpi_dev(obj_handle);
148752dae93fSRafael J. Wysocki 	if (!device)
1488ac23d3caSYasuaki Ishimatsu 		return AE_OK;
1489ac23d3caSYasuaki Ishimatsu 
1490ac23d3caSYasuaki Ishimatsu 	if (strcmp(acpi_device_hid(device), ACPI_MOTHERBOARD_RESOURCE_HID))
1491ac23d3caSYasuaki Ishimatsu 		return AE_OK;
1492ac23d3caSYasuaki Ishimatsu 
1493ac23d3caSYasuaki Ishimatsu 	if (!is_extended_socket_device(device))
1494ac23d3caSYasuaki Ishimatsu 		return AE_OK;
1495ac23d3caSYasuaki Ishimatsu 
14962b396d30SYasuaki Ishimatsu 	if (acpi_check_extended_socket_status(device))
14972b396d30SYasuaki Ishimatsu 		return AE_OK;
14982b396d30SYasuaki Ishimatsu 
1499ac23d3caSYasuaki Ishimatsu 	*found = true;
1500ac23d3caSYasuaki Ishimatsu 	return AE_CTRL_TERMINATE;
1501ac23d3caSYasuaki Ishimatsu }
1502ac23d3caSYasuaki Ishimatsu 
1503658d439bSTaku Izumi /* fjes_init_module - Driver Registration Routine */
1504658d439bSTaku Izumi static int __init fjes_init_module(void)
1505658d439bSTaku Izumi {
1506ac23d3caSYasuaki Ishimatsu 	bool found = false;
1507658d439bSTaku Izumi 	int result;
1508658d439bSTaku Izumi 
1509ac23d3caSYasuaki Ishimatsu 	acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
1510ac23d3caSYasuaki Ishimatsu 			    acpi_find_extended_socket_device, NULL, &found,
1511ac23d3caSYasuaki Ishimatsu 			    NULL);
1512ac23d3caSYasuaki Ishimatsu 
1513ac23d3caSYasuaki Ishimatsu 	if (!found)
1514ac23d3caSYasuaki Ishimatsu 		return -ENODEV;
1515ac23d3caSYasuaki Ishimatsu 
1516658d439bSTaku Izumi 	pr_info("%s - version %s - %s\n",
1517658d439bSTaku Izumi 		fjes_driver_string, fjes_driver_version, fjes_copyright);
1518658d439bSTaku Izumi 
1519c753119eSTaku Izumi 	fjes_dbg_init();
1520c753119eSTaku Izumi 
1521658d439bSTaku Izumi 	result = platform_driver_register(&fjes_driver);
1522c753119eSTaku Izumi 	if (result < 0) {
1523c753119eSTaku Izumi 		fjes_dbg_exit();
1524658d439bSTaku Izumi 		return result;
1525c753119eSTaku Izumi 	}
1526658d439bSTaku Izumi 
1527658d439bSTaku Izumi 	result = acpi_bus_register_driver(&fjes_acpi_driver);
1528658d439bSTaku Izumi 	if (result < 0)
1529658d439bSTaku Izumi 		goto fail_acpi_driver;
1530658d439bSTaku Izumi 
1531658d439bSTaku Izumi 	return 0;
1532658d439bSTaku Izumi 
1533658d439bSTaku Izumi fail_acpi_driver:
1534658d439bSTaku Izumi 	platform_driver_unregister(&fjes_driver);
1535c753119eSTaku Izumi 	fjes_dbg_exit();
1536658d439bSTaku Izumi 	return result;
1537658d439bSTaku Izumi }
1538658d439bSTaku Izumi 
1539658d439bSTaku Izumi module_init(fjes_init_module);
1540658d439bSTaku Izumi 
1541658d439bSTaku Izumi /* fjes_exit_module - Driver Exit Cleanup Routine */
1542658d439bSTaku Izumi static void __exit fjes_exit_module(void)
1543658d439bSTaku Izumi {
1544658d439bSTaku Izumi 	acpi_bus_unregister_driver(&fjes_acpi_driver);
1545658d439bSTaku Izumi 	platform_driver_unregister(&fjes_driver);
1546c753119eSTaku Izumi 	fjes_dbg_exit();
1547658d439bSTaku Izumi }
1548658d439bSTaku Izumi 
1549658d439bSTaku Izumi module_exit(fjes_exit_module);
1550