xref: /openbmc/linux/drivers/net/fjes/fjes_main.c (revision b48b89f9c189d24eb5e2b4a0ac067da5a24ee86d)
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 
86fa2aee65SUwe Kleine-König static acpi_status
87fa2aee65SUwe Kleine-König fjes_get_acpi_resource(struct acpi_resource *acpi_res, void *data)
88fa2aee65SUwe Kleine-König {
89fa2aee65SUwe Kleine-König 	struct acpi_resource_address32 *addr;
90fa2aee65SUwe Kleine-König 	struct acpi_resource_irq *irq;
91fa2aee65SUwe Kleine-König 	struct resource *res = data;
92fa2aee65SUwe Kleine-König 
93fa2aee65SUwe Kleine-König 	switch (acpi_res->type) {
94fa2aee65SUwe Kleine-König 	case ACPI_RESOURCE_TYPE_ADDRESS32:
95fa2aee65SUwe Kleine-König 		addr = &acpi_res->data.address32;
96fa2aee65SUwe Kleine-König 		res[0].start = addr->address.minimum;
97fa2aee65SUwe Kleine-König 		res[0].end = addr->address.minimum +
98fa2aee65SUwe Kleine-König 			addr->address.address_length - 1;
99fa2aee65SUwe Kleine-König 		break;
100fa2aee65SUwe Kleine-König 
101fa2aee65SUwe Kleine-König 	case ACPI_RESOURCE_TYPE_IRQ:
102fa2aee65SUwe Kleine-König 		irq = &acpi_res->data.irq;
103fa2aee65SUwe Kleine-König 		if (irq->interrupt_count != 1)
104fa2aee65SUwe Kleine-König 			return AE_ERROR;
105fa2aee65SUwe Kleine-König 		res[1].start = irq->interrupts[0];
106fa2aee65SUwe Kleine-König 		res[1].end = irq->interrupts[0];
107fa2aee65SUwe Kleine-König 		break;
108fa2aee65SUwe Kleine-König 
109fa2aee65SUwe Kleine-König 	default:
110fa2aee65SUwe Kleine-König 		break;
111fa2aee65SUwe Kleine-König 	}
112fa2aee65SUwe Kleine-König 
113fa2aee65SUwe Kleine-König 	return AE_OK;
114fa2aee65SUwe Kleine-König }
115fa2aee65SUwe Kleine-König 
116fa2aee65SUwe Kleine-König static struct resource fjes_resource[] = {
117fa2aee65SUwe Kleine-König 	DEFINE_RES_MEM(0, 1),
118fa2aee65SUwe Kleine-König 	DEFINE_RES_IRQ(0)
119fa2aee65SUwe Kleine-König };
120fa2aee65SUwe 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 
158fa2aee65SUwe Kleine-König static struct acpi_driver fjes_acpi_driver = {
159fa2aee65SUwe Kleine-König 	.name = DRV_NAME,
160fa2aee65SUwe Kleine-König 	.class = DRV_NAME,
161fa2aee65SUwe Kleine-König 	.owner = THIS_MODULE,
162fa2aee65SUwe Kleine-König 	.ids = fjes_acpi_ids,
163fa2aee65SUwe Kleine-König 	.ops = {
164fa2aee65SUwe Kleine-König 		.add = fjes_acpi_add,
165fa2aee65SUwe Kleine-König 		.remove = fjes_acpi_remove,
166fa2aee65SUwe Kleine-König 	},
167fa2aee65SUwe Kleine-König };
168fa2aee65SUwe Kleine-König 
169fa2aee65SUwe Kleine-König static int fjes_setup_resources(struct fjes_adapter *adapter)
170658d439bSTaku Izumi {
171fa2aee65SUwe Kleine-König 	struct net_device *netdev = adapter->netdev;
172fa2aee65SUwe Kleine-König 	struct ep_share_mem_info *buf_pair;
173fa2aee65SUwe Kleine-König 	struct fjes_hw *hw = &adapter->hw;
174fa2aee65SUwe Kleine-König 	unsigned long flags;
175fa2aee65SUwe Kleine-König 	int result;
176fa2aee65SUwe Kleine-König 	int epidx;
177658d439bSTaku Izumi 
178fa2aee65SUwe Kleine-König 	mutex_lock(&hw->hw_info.lock);
179fa2aee65SUwe Kleine-König 	result = fjes_hw_request_info(hw);
180fa2aee65SUwe Kleine-König 	switch (result) {
181fa2aee65SUwe Kleine-König 	case 0:
182fa2aee65SUwe Kleine-König 		for (epidx = 0; epidx < hw->max_epid; epidx++) {
183fa2aee65SUwe Kleine-König 			hw->ep_shm_info[epidx].es_status =
184fa2aee65SUwe Kleine-König 			    hw->hw_info.res_buf->info.info[epidx].es_status;
185fa2aee65SUwe Kleine-König 			hw->ep_shm_info[epidx].zone =
186fa2aee65SUwe Kleine-König 			    hw->hw_info.res_buf->info.info[epidx].zone;
187fa2aee65SUwe Kleine-König 		}
188658d439bSTaku Izumi 		break;
189658d439bSTaku Izumi 	default:
190fa2aee65SUwe Kleine-König 	case -ENOMSG:
191fa2aee65SUwe Kleine-König 	case -EBUSY:
192fa2aee65SUwe Kleine-König 		adapter->force_reset = true;
193fa2aee65SUwe Kleine-König 
194fa2aee65SUwe Kleine-König 		mutex_unlock(&hw->hw_info.lock);
195fa2aee65SUwe Kleine-König 		return result;
196fa2aee65SUwe Kleine-König 	}
197fa2aee65SUwe Kleine-König 	mutex_unlock(&hw->hw_info.lock);
198fa2aee65SUwe Kleine-König 
199fa2aee65SUwe Kleine-König 	for (epidx = 0; epidx < (hw->max_epid); epidx++) {
200fa2aee65SUwe Kleine-König 		if ((epidx != hw->my_epid) &&
201fa2aee65SUwe Kleine-König 		    (hw->ep_shm_info[epidx].es_status ==
202fa2aee65SUwe Kleine-König 		     FJES_ZONING_STATUS_ENABLE)) {
203fa2aee65SUwe Kleine-König 			fjes_hw_raise_interrupt(hw, epidx,
204fa2aee65SUwe Kleine-König 						REG_ICTL_MASK_INFO_UPDATE);
205fa2aee65SUwe Kleine-König 			hw->ep_shm_info[epidx].ep_stats
206fa2aee65SUwe Kleine-König 				.send_intr_zoneupdate += 1;
207fa2aee65SUwe Kleine-König 		}
208658d439bSTaku Izumi 	}
209658d439bSTaku Izumi 
210fa2aee65SUwe Kleine-König 	msleep(FJES_OPEN_ZONE_UPDATE_WAIT * hw->max_epid);
211fa2aee65SUwe Kleine-König 
212fa2aee65SUwe Kleine-König 	for (epidx = 0; epidx < (hw->max_epid); epidx++) {
213fa2aee65SUwe Kleine-König 		if (epidx == hw->my_epid)
214fa2aee65SUwe Kleine-König 			continue;
215fa2aee65SUwe Kleine-König 
216fa2aee65SUwe Kleine-König 		buf_pair = &hw->ep_shm_info[epidx];
217fa2aee65SUwe Kleine-König 
218fa2aee65SUwe Kleine-König 		spin_lock_irqsave(&hw->rx_status_lock, flags);
219fa2aee65SUwe Kleine-König 		fjes_hw_setup_epbuf(&buf_pair->tx, netdev->dev_addr,
220fa2aee65SUwe Kleine-König 				    netdev->mtu);
221fa2aee65SUwe Kleine-König 		spin_unlock_irqrestore(&hw->rx_status_lock, flags);
222fa2aee65SUwe Kleine-König 
223fa2aee65SUwe Kleine-König 		if (fjes_hw_epid_is_same_zone(hw, epidx)) {
224fa2aee65SUwe Kleine-König 			mutex_lock(&hw->hw_info.lock);
225fa2aee65SUwe Kleine-König 			result =
226fa2aee65SUwe Kleine-König 			fjes_hw_register_buff_addr(hw, epidx, buf_pair);
227fa2aee65SUwe Kleine-König 			mutex_unlock(&hw->hw_info.lock);
228fa2aee65SUwe Kleine-König 
229fa2aee65SUwe Kleine-König 			switch (result) {
230fa2aee65SUwe Kleine-König 			case 0:
231fa2aee65SUwe Kleine-König 				break;
232fa2aee65SUwe Kleine-König 			case -ENOMSG:
233fa2aee65SUwe Kleine-König 			case -EBUSY:
234fa2aee65SUwe Kleine-König 			default:
235fa2aee65SUwe Kleine-König 				adapter->force_reset = true;
236fa2aee65SUwe Kleine-König 				return result;
237fa2aee65SUwe Kleine-König 			}
238fa2aee65SUwe Kleine-König 
239fa2aee65SUwe Kleine-König 			hw->ep_shm_info[epidx].ep_stats
240fa2aee65SUwe Kleine-König 				.com_regist_buf_exec += 1;
241fa2aee65SUwe Kleine-König 		}
242fa2aee65SUwe Kleine-König 	}
243fa2aee65SUwe Kleine-König 
244fa2aee65SUwe Kleine-König 	return 0;
245fa2aee65SUwe Kleine-König }
246fa2aee65SUwe Kleine-König 
247fa2aee65SUwe Kleine-König static void fjes_rx_irq(struct fjes_adapter *adapter, int src_epid)
248fa2aee65SUwe Kleine-König {
249fa2aee65SUwe Kleine-König 	struct fjes_hw *hw = &adapter->hw;
250fa2aee65SUwe Kleine-König 
251fa2aee65SUwe Kleine-König 	fjes_hw_set_irqmask(hw, REG_ICTL_MASK_RX_DATA, true);
252fa2aee65SUwe Kleine-König 
253fa2aee65SUwe Kleine-König 	adapter->unset_rx_last = true;
254fa2aee65SUwe Kleine-König 	napi_schedule(&adapter->napi);
255fa2aee65SUwe Kleine-König }
256fa2aee65SUwe Kleine-König 
257fa2aee65SUwe Kleine-König static void fjes_stop_req_irq(struct fjes_adapter *adapter, int src_epid)
258fa2aee65SUwe Kleine-König {
259fa2aee65SUwe Kleine-König 	struct fjes_hw *hw = &adapter->hw;
260fa2aee65SUwe Kleine-König 	enum ep_partner_status status;
261fa2aee65SUwe Kleine-König 	unsigned long flags;
262fa2aee65SUwe Kleine-König 
263fa2aee65SUwe Kleine-König 	set_bit(src_epid, &hw->hw_info.buffer_unshare_reserve_bit);
264fa2aee65SUwe Kleine-König 
265fa2aee65SUwe Kleine-König 	status = fjes_hw_get_partner_ep_status(hw, src_epid);
266fa2aee65SUwe Kleine-König 	trace_fjes_stop_req_irq_pre(hw, src_epid, status);
267fa2aee65SUwe Kleine-König 	switch (status) {
268fa2aee65SUwe Kleine-König 	case EP_PARTNER_WAITING:
269fa2aee65SUwe Kleine-König 		spin_lock_irqsave(&hw->rx_status_lock, flags);
270fa2aee65SUwe Kleine-König 		hw->ep_shm_info[src_epid].tx.info->v1i.rx_status |=
271fa2aee65SUwe Kleine-König 				FJES_RX_STOP_REQ_DONE;
272fa2aee65SUwe Kleine-König 		spin_unlock_irqrestore(&hw->rx_status_lock, flags);
273fa2aee65SUwe Kleine-König 		clear_bit(src_epid, &hw->txrx_stop_req_bit);
274fa2aee65SUwe Kleine-König 		fallthrough;
275fa2aee65SUwe Kleine-König 	case EP_PARTNER_UNSHARE:
276fa2aee65SUwe Kleine-König 	case EP_PARTNER_COMPLETE:
277fa2aee65SUwe Kleine-König 	default:
278fa2aee65SUwe Kleine-König 		set_bit(src_epid, &adapter->unshare_watch_bitmask);
279fa2aee65SUwe Kleine-König 		if (!work_pending(&adapter->unshare_watch_task))
280fa2aee65SUwe Kleine-König 			queue_work(adapter->control_wq,
281fa2aee65SUwe Kleine-König 				   &adapter->unshare_watch_task);
282fa2aee65SUwe Kleine-König 		break;
283fa2aee65SUwe Kleine-König 	case EP_PARTNER_SHARED:
284fa2aee65SUwe Kleine-König 		set_bit(src_epid, &hw->epstop_req_bit);
285fa2aee65SUwe Kleine-König 
286fa2aee65SUwe Kleine-König 		if (!work_pending(&hw->epstop_task))
287fa2aee65SUwe Kleine-König 			queue_work(adapter->control_wq, &hw->epstop_task);
288fa2aee65SUwe Kleine-König 		break;
289fa2aee65SUwe Kleine-König 	}
290fa2aee65SUwe Kleine-König 	trace_fjes_stop_req_irq_post(hw, src_epid);
291fa2aee65SUwe Kleine-König }
292fa2aee65SUwe Kleine-König 
293fa2aee65SUwe Kleine-König static void fjes_txrx_stop_req_irq(struct fjes_adapter *adapter,
294fa2aee65SUwe Kleine-König 				   int src_epid)
295fa2aee65SUwe Kleine-König {
296fa2aee65SUwe Kleine-König 	struct fjes_hw *hw = &adapter->hw;
297fa2aee65SUwe Kleine-König 	enum ep_partner_status status;
298fa2aee65SUwe Kleine-König 	unsigned long flags;
299fa2aee65SUwe Kleine-König 
300fa2aee65SUwe Kleine-König 	status = fjes_hw_get_partner_ep_status(hw, src_epid);
301fa2aee65SUwe Kleine-König 	trace_fjes_txrx_stop_req_irq_pre(hw, src_epid, status);
302fa2aee65SUwe Kleine-König 	switch (status) {
303fa2aee65SUwe Kleine-König 	case EP_PARTNER_UNSHARE:
304fa2aee65SUwe Kleine-König 	case EP_PARTNER_COMPLETE:
305fa2aee65SUwe Kleine-König 	default:
306fa2aee65SUwe Kleine-König 		break;
307fa2aee65SUwe Kleine-König 	case EP_PARTNER_WAITING:
308fa2aee65SUwe Kleine-König 		if (src_epid < hw->my_epid) {
309fa2aee65SUwe Kleine-König 			spin_lock_irqsave(&hw->rx_status_lock, flags);
310fa2aee65SUwe Kleine-König 			hw->ep_shm_info[src_epid].tx.info->v1i.rx_status |=
311fa2aee65SUwe Kleine-König 				FJES_RX_STOP_REQ_DONE;
312fa2aee65SUwe Kleine-König 			spin_unlock_irqrestore(&hw->rx_status_lock, flags);
313fa2aee65SUwe Kleine-König 
314fa2aee65SUwe Kleine-König 			clear_bit(src_epid, &hw->txrx_stop_req_bit);
315fa2aee65SUwe Kleine-König 			set_bit(src_epid, &adapter->unshare_watch_bitmask);
316fa2aee65SUwe Kleine-König 
317fa2aee65SUwe Kleine-König 			if (!work_pending(&adapter->unshare_watch_task))
318fa2aee65SUwe Kleine-König 				queue_work(adapter->control_wq,
319fa2aee65SUwe Kleine-König 					   &adapter->unshare_watch_task);
320fa2aee65SUwe Kleine-König 		}
321fa2aee65SUwe Kleine-König 		break;
322fa2aee65SUwe Kleine-König 	case EP_PARTNER_SHARED:
323fa2aee65SUwe Kleine-König 		if (hw->ep_shm_info[src_epid].rx.info->v1i.rx_status &
324fa2aee65SUwe Kleine-König 		    FJES_RX_STOP_REQ_REQUEST) {
325fa2aee65SUwe Kleine-König 			set_bit(src_epid, &hw->epstop_req_bit);
326fa2aee65SUwe Kleine-König 			if (!work_pending(&hw->epstop_task))
327fa2aee65SUwe Kleine-König 				queue_work(adapter->control_wq,
328fa2aee65SUwe Kleine-König 					   &hw->epstop_task);
329fa2aee65SUwe Kleine-König 		}
330fa2aee65SUwe Kleine-König 		break;
331fa2aee65SUwe Kleine-König 	}
332fa2aee65SUwe Kleine-König 	trace_fjes_txrx_stop_req_irq_post(hw, src_epid);
333fa2aee65SUwe Kleine-König }
334fa2aee65SUwe Kleine-König 
335fa2aee65SUwe Kleine-König static void fjes_update_zone_irq(struct fjes_adapter *adapter,
336fa2aee65SUwe Kleine-König 				 int src_epid)
337fa2aee65SUwe Kleine-König {
338fa2aee65SUwe Kleine-König 	struct fjes_hw *hw = &adapter->hw;
339fa2aee65SUwe Kleine-König 
340fa2aee65SUwe Kleine-König 	if (!work_pending(&hw->update_zone_task))
341fa2aee65SUwe Kleine-König 		queue_work(adapter->control_wq, &hw->update_zone_task);
342fa2aee65SUwe Kleine-König }
343fa2aee65SUwe Kleine-König 
344fa2aee65SUwe Kleine-König static irqreturn_t fjes_intr(int irq, void *data)
345fa2aee65SUwe Kleine-König {
346fa2aee65SUwe Kleine-König 	struct fjes_adapter *adapter = data;
347fa2aee65SUwe Kleine-König 	struct fjes_hw *hw = &adapter->hw;
348fa2aee65SUwe Kleine-König 	irqreturn_t ret;
349fa2aee65SUwe Kleine-König 	u32 icr;
350fa2aee65SUwe Kleine-König 
351fa2aee65SUwe Kleine-König 	icr = fjes_hw_capture_interrupt_status(hw);
352fa2aee65SUwe Kleine-König 
353fa2aee65SUwe Kleine-König 	if (icr & REG_IS_MASK_IS_ASSERT) {
354fa2aee65SUwe Kleine-König 		if (icr & REG_ICTL_MASK_RX_DATA) {
355fa2aee65SUwe Kleine-König 			fjes_rx_irq(adapter, icr & REG_IS_MASK_EPID);
356fa2aee65SUwe Kleine-König 			hw->ep_shm_info[icr & REG_IS_MASK_EPID].ep_stats
357fa2aee65SUwe Kleine-König 				.recv_intr_rx += 1;
358fa2aee65SUwe Kleine-König 		}
359fa2aee65SUwe Kleine-König 
360fa2aee65SUwe Kleine-König 		if (icr & REG_ICTL_MASK_DEV_STOP_REQ) {
361fa2aee65SUwe Kleine-König 			fjes_stop_req_irq(adapter, icr & REG_IS_MASK_EPID);
362fa2aee65SUwe Kleine-König 			hw->ep_shm_info[icr & REG_IS_MASK_EPID].ep_stats
363fa2aee65SUwe Kleine-König 				.recv_intr_stop += 1;
364fa2aee65SUwe Kleine-König 		}
365fa2aee65SUwe Kleine-König 
366fa2aee65SUwe Kleine-König 		if (icr & REG_ICTL_MASK_TXRX_STOP_REQ) {
367fa2aee65SUwe Kleine-König 			fjes_txrx_stop_req_irq(adapter, icr & REG_IS_MASK_EPID);
368fa2aee65SUwe Kleine-König 			hw->ep_shm_info[icr & REG_IS_MASK_EPID].ep_stats
369fa2aee65SUwe Kleine-König 				.recv_intr_unshare += 1;
370fa2aee65SUwe Kleine-König 		}
371fa2aee65SUwe Kleine-König 
372fa2aee65SUwe Kleine-König 		if (icr & REG_ICTL_MASK_TXRX_STOP_DONE)
373fa2aee65SUwe Kleine-König 			fjes_hw_set_irqmask(hw,
374fa2aee65SUwe Kleine-König 					    REG_ICTL_MASK_TXRX_STOP_DONE, true);
375fa2aee65SUwe Kleine-König 
376fa2aee65SUwe Kleine-König 		if (icr & REG_ICTL_MASK_INFO_UPDATE) {
377fa2aee65SUwe Kleine-König 			fjes_update_zone_irq(adapter, icr & REG_IS_MASK_EPID);
378fa2aee65SUwe Kleine-König 			hw->ep_shm_info[icr & REG_IS_MASK_EPID].ep_stats
379fa2aee65SUwe Kleine-König 				.recv_intr_zoneupdate += 1;
380fa2aee65SUwe Kleine-König 		}
381fa2aee65SUwe Kleine-König 
382fa2aee65SUwe Kleine-König 		ret = IRQ_HANDLED;
383fa2aee65SUwe Kleine-König 	} else {
384fa2aee65SUwe Kleine-König 		ret = IRQ_NONE;
385fa2aee65SUwe Kleine-König 	}
386fa2aee65SUwe Kleine-König 
387fa2aee65SUwe 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 
429fa2aee65SUwe Kleine-König static void fjes_free_resources(struct fjes_adapter *adapter)
430fa2aee65SUwe Kleine-König {
431fa2aee65SUwe Kleine-König 	struct net_device *netdev = adapter->netdev;
432fa2aee65SUwe Kleine-König 	struct fjes_device_command_param param;
433fa2aee65SUwe Kleine-König 	struct ep_share_mem_info *buf_pair;
434fa2aee65SUwe Kleine-König 	struct fjes_hw *hw = &adapter->hw;
435fa2aee65SUwe Kleine-König 	bool reset_flag = false;
436fa2aee65SUwe Kleine-König 	unsigned long flags;
437fa2aee65SUwe Kleine-König 	int result;
438fa2aee65SUwe Kleine-König 	int epidx;
439fa2aee65SUwe Kleine-König 
440fa2aee65SUwe Kleine-König 	for (epidx = 0; epidx < hw->max_epid; epidx++) {
441fa2aee65SUwe Kleine-König 		if (epidx == hw->my_epid)
442fa2aee65SUwe Kleine-König 			continue;
443fa2aee65SUwe Kleine-König 
444fa2aee65SUwe Kleine-König 		mutex_lock(&hw->hw_info.lock);
445fa2aee65SUwe Kleine-König 		result = fjes_hw_unregister_buff_addr(hw, epidx);
446fa2aee65SUwe Kleine-König 		mutex_unlock(&hw->hw_info.lock);
447fa2aee65SUwe Kleine-König 
448fa2aee65SUwe Kleine-König 		hw->ep_shm_info[epidx].ep_stats.com_unregist_buf_exec += 1;
449fa2aee65SUwe Kleine-König 
450fa2aee65SUwe Kleine-König 		if (result)
451fa2aee65SUwe Kleine-König 			reset_flag = true;
452fa2aee65SUwe Kleine-König 
453fa2aee65SUwe Kleine-König 		buf_pair = &hw->ep_shm_info[epidx];
454fa2aee65SUwe Kleine-König 
455fa2aee65SUwe Kleine-König 		spin_lock_irqsave(&hw->rx_status_lock, flags);
456fa2aee65SUwe Kleine-König 		fjes_hw_setup_epbuf(&buf_pair->tx,
457fa2aee65SUwe Kleine-König 				    netdev->dev_addr, netdev->mtu);
458fa2aee65SUwe Kleine-König 		spin_unlock_irqrestore(&hw->rx_status_lock, flags);
459fa2aee65SUwe Kleine-König 
460fa2aee65SUwe Kleine-König 		clear_bit(epidx, &hw->txrx_stop_req_bit);
461fa2aee65SUwe Kleine-König 	}
462fa2aee65SUwe Kleine-König 
463fa2aee65SUwe Kleine-König 	if (reset_flag || adapter->force_reset) {
464fa2aee65SUwe Kleine-König 		result = fjes_hw_reset(hw);
465fa2aee65SUwe Kleine-König 
466fa2aee65SUwe Kleine-König 		adapter->force_reset = false;
467fa2aee65SUwe Kleine-König 
468fa2aee65SUwe Kleine-König 		if (result)
469fa2aee65SUwe Kleine-König 			adapter->open_guard = true;
470fa2aee65SUwe Kleine-König 
471fa2aee65SUwe Kleine-König 		hw->hw_info.buffer_share_bit = 0;
472fa2aee65SUwe Kleine-König 
473fa2aee65SUwe Kleine-König 		memset((void *)&param, 0, sizeof(param));
474fa2aee65SUwe Kleine-König 
475fa2aee65SUwe Kleine-König 		param.req_len = hw->hw_info.req_buf_size;
476fa2aee65SUwe Kleine-König 		param.req_start = __pa(hw->hw_info.req_buf);
477fa2aee65SUwe Kleine-König 		param.res_len = hw->hw_info.res_buf_size;
478fa2aee65SUwe Kleine-König 		param.res_start = __pa(hw->hw_info.res_buf);
479fa2aee65SUwe Kleine-König 		param.share_start = __pa(hw->hw_info.share->ep_status);
480fa2aee65SUwe Kleine-König 
481fa2aee65SUwe Kleine-König 		fjes_hw_init_command_registers(hw, &param);
482fa2aee65SUwe Kleine-König 	}
483fa2aee65SUwe 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 
842fa2aee65SUwe Kleine-König static void fjes_tx_retry(struct net_device *netdev, unsigned int txqueue)
843fa2aee65SUwe Kleine-König {
844fa2aee65SUwe Kleine-König 	struct netdev_queue *queue = netdev_get_tx_queue(netdev, 0);
845fa2aee65SUwe Kleine-König 
846fa2aee65SUwe Kleine-König 	netif_tx_wake_queue(queue);
847fa2aee65SUwe Kleine-König }
848fa2aee65SUwe 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 
885fa2aee65SUwe Kleine-König static const struct net_device_ops fjes_netdev_ops = {
886fa2aee65SUwe Kleine-König 	.ndo_open		= fjes_open,
887fa2aee65SUwe Kleine-König 	.ndo_stop		= fjes_close,
888fa2aee65SUwe Kleine-König 	.ndo_start_xmit		= fjes_xmit_frame,
889fa2aee65SUwe Kleine-König 	.ndo_get_stats64	= fjes_get_stats64,
890fa2aee65SUwe Kleine-König 	.ndo_change_mtu		= fjes_change_mtu,
891fa2aee65SUwe Kleine-König 	.ndo_tx_timeout		= fjes_tx_retry,
892fa2aee65SUwe Kleine-König 	.ndo_vlan_rx_add_vid	= fjes_vlan_rx_add_vid,
893fa2aee65SUwe Kleine-König 	.ndo_vlan_rx_kill_vid = fjes_vlan_rx_kill_vid,
894fa2aee65SUwe Kleine-König };
895fa2aee65SUwe Kleine-König 
896fa2aee65SUwe Kleine-König /* fjes_netdev_setup - netdevice initialization routine */
897fa2aee65SUwe Kleine-König static void fjes_netdev_setup(struct net_device *netdev)
898cb79eaaeSTaku Izumi {
899fa2aee65SUwe Kleine-König 	ether_setup(netdev);
900cb79eaaeSTaku Izumi 
901fa2aee65SUwe Kleine-König 	netdev->watchdog_timeo = FJES_TX_RETRY_INTERVAL;
902fa2aee65SUwe Kleine-König 	netdev->netdev_ops = &fjes_netdev_ops;
903fa2aee65SUwe Kleine-König 	fjes_set_ethtool_ops(netdev);
904fa2aee65SUwe Kleine-König 	netdev->mtu = fjes_support_mtu[3];
905fa2aee65SUwe Kleine-König 	netdev->min_mtu = fjes_support_mtu[0];
906fa2aee65SUwe Kleine-König 	netdev->max_mtu = fjes_support_mtu[3];
907fa2aee65SUwe 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 
1056fa2aee65SUwe Kleine-König static int fjes_sw_init(struct fjes_adapter *adapter)
1057fa2aee65SUwe Kleine-König {
1058fa2aee65SUwe Kleine-König 	struct net_device *netdev = adapter->netdev;
1059fa2aee65SUwe Kleine-König 
1060*b48b89f9SJakub Kicinski 	netif_napi_add(netdev, &adapter->napi, fjes_poll);
1061fa2aee65SUwe Kleine-König 
1062fa2aee65SUwe Kleine-König 	return 0;
1063fa2aee65SUwe Kleine-König }
1064fa2aee65SUwe Kleine-König 
1065fa2aee65SUwe Kleine-König static void fjes_force_close_task(struct work_struct *work)
1066fa2aee65SUwe Kleine-König {
1067fa2aee65SUwe Kleine-König 	struct fjes_adapter *adapter = container_of(work,
1068fa2aee65SUwe Kleine-König 			struct fjes_adapter, force_close_task);
1069fa2aee65SUwe Kleine-König 	struct net_device *netdev = adapter->netdev;
1070fa2aee65SUwe Kleine-König 
1071fa2aee65SUwe Kleine-König 	rtnl_lock();
1072fa2aee65SUwe Kleine-König 	dev_close(netdev);
1073fa2aee65SUwe Kleine-König 	rtnl_unlock();
1074fa2aee65SUwe Kleine-König }
1075fa2aee65SUwe Kleine-König 
1076fa2aee65SUwe Kleine-König static void fjes_tx_stall_task(struct work_struct *work)
1077fa2aee65SUwe Kleine-König {
1078fa2aee65SUwe Kleine-König 	struct fjes_adapter *adapter = container_of(work,
1079fa2aee65SUwe Kleine-König 			struct fjes_adapter, tx_stall_task);
1080fa2aee65SUwe Kleine-König 	struct net_device *netdev = adapter->netdev;
1081fa2aee65SUwe Kleine-König 	struct fjes_hw *hw = &adapter->hw;
1082fa2aee65SUwe Kleine-König 	int all_queue_available, sendable;
1083fa2aee65SUwe Kleine-König 	enum ep_partner_status pstatus;
1084fa2aee65SUwe Kleine-König 	int max_epid, my_epid, epid;
1085fa2aee65SUwe Kleine-König 	union ep_buffer_info *info;
1086fa2aee65SUwe Kleine-König 	int i;
1087fa2aee65SUwe Kleine-König 
1088fa2aee65SUwe Kleine-König 	if (((long)jiffies -
1089fa2aee65SUwe Kleine-König 		dev_trans_start(netdev)) > FJES_TX_TX_STALL_TIMEOUT) {
1090fa2aee65SUwe Kleine-König 		netif_wake_queue(netdev);
1091fa2aee65SUwe Kleine-König 		return;
1092fa2aee65SUwe Kleine-König 	}
1093fa2aee65SUwe Kleine-König 
1094fa2aee65SUwe Kleine-König 	my_epid = hw->my_epid;
1095fa2aee65SUwe Kleine-König 	max_epid = hw->max_epid;
1096fa2aee65SUwe Kleine-König 
1097fa2aee65SUwe Kleine-König 	for (i = 0; i < 5; i++) {
1098fa2aee65SUwe Kleine-König 		all_queue_available = 1;
1099fa2aee65SUwe Kleine-König 
1100fa2aee65SUwe Kleine-König 		for (epid = 0; epid < max_epid; epid++) {
1101fa2aee65SUwe Kleine-König 			if (my_epid == epid)
1102fa2aee65SUwe Kleine-König 				continue;
1103fa2aee65SUwe Kleine-König 
1104fa2aee65SUwe Kleine-König 			pstatus = fjes_hw_get_partner_ep_status(hw, epid);
1105fa2aee65SUwe Kleine-König 			sendable = (pstatus == EP_PARTNER_SHARED);
1106fa2aee65SUwe Kleine-König 			if (!sendable)
1107fa2aee65SUwe Kleine-König 				continue;
1108fa2aee65SUwe Kleine-König 
1109fa2aee65SUwe Kleine-König 			info = adapter->hw.ep_shm_info[epid].tx.info;
1110fa2aee65SUwe Kleine-König 
1111fa2aee65SUwe Kleine-König 			if (!(info->v1i.rx_status & FJES_RX_MTU_CHANGING_DONE))
1112fa2aee65SUwe Kleine-König 				return;
1113fa2aee65SUwe Kleine-König 
1114fa2aee65SUwe Kleine-König 			if (EP_RING_FULL(info->v1i.head, info->v1i.tail,
1115fa2aee65SUwe Kleine-König 					 info->v1i.count_max)) {
1116fa2aee65SUwe Kleine-König 				all_queue_available = 0;
1117fa2aee65SUwe Kleine-König 				break;
1118fa2aee65SUwe Kleine-König 			}
1119fa2aee65SUwe Kleine-König 		}
1120fa2aee65SUwe Kleine-König 
1121fa2aee65SUwe Kleine-König 		if (all_queue_available) {
1122fa2aee65SUwe Kleine-König 			netif_wake_queue(netdev);
1123fa2aee65SUwe Kleine-König 			return;
1124fa2aee65SUwe Kleine-König 		}
1125fa2aee65SUwe Kleine-König 	}
1126fa2aee65SUwe Kleine-König 
1127fa2aee65SUwe Kleine-König 	usleep_range(50, 100);
1128fa2aee65SUwe Kleine-König 
1129fa2aee65SUwe Kleine-König 	queue_work(adapter->txrx_wq, &adapter->tx_stall_task);
1130fa2aee65SUwe Kleine-König }
1131fa2aee65SUwe Kleine-König 
1132fa2aee65SUwe Kleine-König static void fjes_raise_intr_rxdata_task(struct work_struct *work)
1133fa2aee65SUwe Kleine-König {
1134fa2aee65SUwe Kleine-König 	struct fjes_adapter *adapter = container_of(work,
1135fa2aee65SUwe Kleine-König 			struct fjes_adapter, raise_intr_rxdata_task);
1136fa2aee65SUwe Kleine-König 	struct fjes_hw *hw = &adapter->hw;
1137fa2aee65SUwe Kleine-König 	enum ep_partner_status pstatus;
1138fa2aee65SUwe Kleine-König 	int max_epid, my_epid, epid;
1139fa2aee65SUwe Kleine-König 
1140fa2aee65SUwe Kleine-König 	my_epid = hw->my_epid;
1141fa2aee65SUwe Kleine-König 	max_epid = hw->max_epid;
1142fa2aee65SUwe Kleine-König 
1143fa2aee65SUwe Kleine-König 	for (epid = 0; epid < max_epid; epid++)
1144fa2aee65SUwe Kleine-König 		hw->ep_shm_info[epid].tx_status_work = 0;
1145fa2aee65SUwe Kleine-König 
1146fa2aee65SUwe Kleine-König 	for (epid = 0; epid < max_epid; epid++) {
1147fa2aee65SUwe Kleine-König 		if (epid == my_epid)
1148fa2aee65SUwe Kleine-König 			continue;
1149fa2aee65SUwe Kleine-König 
1150fa2aee65SUwe Kleine-König 		pstatus = fjes_hw_get_partner_ep_status(hw, epid);
1151fa2aee65SUwe Kleine-König 		if (pstatus == EP_PARTNER_SHARED) {
1152fa2aee65SUwe Kleine-König 			hw->ep_shm_info[epid].tx_status_work =
1153fa2aee65SUwe Kleine-König 				hw->ep_shm_info[epid].tx.info->v1i.tx_status;
1154fa2aee65SUwe Kleine-König 
1155fa2aee65SUwe Kleine-König 			if (hw->ep_shm_info[epid].tx_status_work ==
1156fa2aee65SUwe Kleine-König 				FJES_TX_DELAY_SEND_PENDING) {
1157fa2aee65SUwe Kleine-König 				hw->ep_shm_info[epid].tx.info->v1i.tx_status =
1158fa2aee65SUwe Kleine-König 					FJES_TX_DELAY_SEND_NONE;
1159fa2aee65SUwe Kleine-König 			}
1160fa2aee65SUwe Kleine-König 		}
1161fa2aee65SUwe Kleine-König 	}
1162fa2aee65SUwe Kleine-König 
1163fa2aee65SUwe Kleine-König 	for (epid = 0; epid < max_epid; epid++) {
1164fa2aee65SUwe Kleine-König 		if (epid == my_epid)
1165fa2aee65SUwe Kleine-König 			continue;
1166fa2aee65SUwe Kleine-König 
1167fa2aee65SUwe Kleine-König 		pstatus = fjes_hw_get_partner_ep_status(hw, epid);
1168fa2aee65SUwe Kleine-König 		if ((hw->ep_shm_info[epid].tx_status_work ==
1169fa2aee65SUwe Kleine-König 		     FJES_TX_DELAY_SEND_PENDING) &&
1170fa2aee65SUwe Kleine-König 		    (pstatus == EP_PARTNER_SHARED) &&
1171fa2aee65SUwe Kleine-König 		    !(hw->ep_shm_info[epid].rx.info->v1i.rx_status &
1172fa2aee65SUwe Kleine-König 		      FJES_RX_POLL_WORK)) {
1173fa2aee65SUwe Kleine-König 			fjes_hw_raise_interrupt(hw, epid,
1174fa2aee65SUwe Kleine-König 						REG_ICTL_MASK_RX_DATA);
1175fa2aee65SUwe Kleine-König 			hw->ep_shm_info[epid].ep_stats.send_intr_rx += 1;
1176fa2aee65SUwe Kleine-König 		}
1177fa2aee65SUwe Kleine-König 	}
1178fa2aee65SUwe Kleine-König 
1179fa2aee65SUwe Kleine-König 	usleep_range(500, 1000);
1180fa2aee65SUwe Kleine-König }
1181fa2aee65SUwe Kleine-König 
1182fa2aee65SUwe Kleine-König static void fjes_watch_unshare_task(struct work_struct *work)
1183fa2aee65SUwe Kleine-König {
1184fa2aee65SUwe Kleine-König 	struct fjes_adapter *adapter =
1185fa2aee65SUwe Kleine-König 	container_of(work, struct fjes_adapter, unshare_watch_task);
1186fa2aee65SUwe Kleine-König 
1187fa2aee65SUwe Kleine-König 	struct net_device *netdev = adapter->netdev;
1188fa2aee65SUwe Kleine-König 	struct fjes_hw *hw = &adapter->hw;
1189fa2aee65SUwe Kleine-König 
1190fa2aee65SUwe Kleine-König 	int unshare_watch, unshare_reserve;
1191fa2aee65SUwe Kleine-König 	int max_epid, my_epid, epidx;
1192fa2aee65SUwe Kleine-König 	int stop_req, stop_req_done;
1193fa2aee65SUwe Kleine-König 	ulong unshare_watch_bitmask;
1194fa2aee65SUwe Kleine-König 	unsigned long flags;
1195fa2aee65SUwe Kleine-König 	int wait_time = 0;
1196fa2aee65SUwe Kleine-König 	int is_shared;
1197fa2aee65SUwe Kleine-König 	int ret;
1198fa2aee65SUwe Kleine-König 
1199fa2aee65SUwe Kleine-König 	my_epid = hw->my_epid;
1200fa2aee65SUwe Kleine-König 	max_epid = hw->max_epid;
1201fa2aee65SUwe Kleine-König 
1202fa2aee65SUwe Kleine-König 	unshare_watch_bitmask = adapter->unshare_watch_bitmask;
1203fa2aee65SUwe Kleine-König 	adapter->unshare_watch_bitmask = 0;
1204fa2aee65SUwe Kleine-König 
1205fa2aee65SUwe Kleine-König 	while ((unshare_watch_bitmask || hw->txrx_stop_req_bit) &&
1206fa2aee65SUwe Kleine-König 	       (wait_time < 3000)) {
1207fa2aee65SUwe Kleine-König 		for (epidx = 0; epidx < max_epid; epidx++) {
1208fa2aee65SUwe Kleine-König 			if (epidx == my_epid)
1209fa2aee65SUwe Kleine-König 				continue;
1210fa2aee65SUwe Kleine-König 
1211fa2aee65SUwe Kleine-König 			is_shared = fjes_hw_epid_is_shared(hw->hw_info.share,
1212fa2aee65SUwe Kleine-König 							   epidx);
1213fa2aee65SUwe Kleine-König 
1214fa2aee65SUwe Kleine-König 			stop_req = test_bit(epidx, &hw->txrx_stop_req_bit);
1215fa2aee65SUwe Kleine-König 
1216fa2aee65SUwe Kleine-König 			stop_req_done = hw->ep_shm_info[epidx].rx.info->v1i.rx_status &
1217fa2aee65SUwe Kleine-König 					FJES_RX_STOP_REQ_DONE;
1218fa2aee65SUwe Kleine-König 
1219fa2aee65SUwe Kleine-König 			unshare_watch = test_bit(epidx, &unshare_watch_bitmask);
1220fa2aee65SUwe Kleine-König 
1221fa2aee65SUwe Kleine-König 			unshare_reserve = test_bit(epidx,
1222fa2aee65SUwe Kleine-König 						   &hw->hw_info.buffer_unshare_reserve_bit);
1223fa2aee65SUwe Kleine-König 
1224fa2aee65SUwe Kleine-König 			if ((!stop_req ||
1225fa2aee65SUwe Kleine-König 			     (is_shared && (!is_shared || !stop_req_done))) &&
1226fa2aee65SUwe Kleine-König 			    (is_shared || !unshare_watch || !unshare_reserve))
1227fa2aee65SUwe Kleine-König 				continue;
1228fa2aee65SUwe Kleine-König 
1229fa2aee65SUwe Kleine-König 			mutex_lock(&hw->hw_info.lock);
1230fa2aee65SUwe Kleine-König 			ret = fjes_hw_unregister_buff_addr(hw, epidx);
1231fa2aee65SUwe Kleine-König 			switch (ret) {
1232fa2aee65SUwe Kleine-König 			case 0:
1233fa2aee65SUwe Kleine-König 				break;
1234fa2aee65SUwe Kleine-König 			case -ENOMSG:
1235fa2aee65SUwe Kleine-König 			case -EBUSY:
1236fa2aee65SUwe Kleine-König 			default:
1237fa2aee65SUwe Kleine-König 				if (!work_pending(
1238fa2aee65SUwe Kleine-König 					&adapter->force_close_task)) {
1239fa2aee65SUwe Kleine-König 					adapter->force_reset = true;
1240fa2aee65SUwe Kleine-König 					schedule_work(
1241fa2aee65SUwe Kleine-König 						&adapter->force_close_task);
1242fa2aee65SUwe Kleine-König 				}
1243fa2aee65SUwe Kleine-König 				break;
1244fa2aee65SUwe Kleine-König 			}
1245fa2aee65SUwe Kleine-König 			mutex_unlock(&hw->hw_info.lock);
1246fa2aee65SUwe Kleine-König 			hw->ep_shm_info[epidx].ep_stats
1247fa2aee65SUwe Kleine-König 					.com_unregist_buf_exec += 1;
1248fa2aee65SUwe Kleine-König 
1249fa2aee65SUwe Kleine-König 			spin_lock_irqsave(&hw->rx_status_lock, flags);
1250fa2aee65SUwe Kleine-König 			fjes_hw_setup_epbuf(&hw->ep_shm_info[epidx].tx,
1251fa2aee65SUwe Kleine-König 					    netdev->dev_addr, netdev->mtu);
1252fa2aee65SUwe Kleine-König 			spin_unlock_irqrestore(&hw->rx_status_lock, flags);
1253fa2aee65SUwe Kleine-König 
1254fa2aee65SUwe Kleine-König 			clear_bit(epidx, &hw->txrx_stop_req_bit);
1255fa2aee65SUwe Kleine-König 			clear_bit(epidx, &unshare_watch_bitmask);
1256fa2aee65SUwe Kleine-König 			clear_bit(epidx,
1257fa2aee65SUwe Kleine-König 				  &hw->hw_info.buffer_unshare_reserve_bit);
1258fa2aee65SUwe Kleine-König 		}
1259fa2aee65SUwe Kleine-König 
1260fa2aee65SUwe Kleine-König 		msleep(100);
1261fa2aee65SUwe Kleine-König 		wait_time += 100;
1262fa2aee65SUwe Kleine-König 	}
1263fa2aee65SUwe Kleine-König 
1264fa2aee65SUwe Kleine-König 	if (hw->hw_info.buffer_unshare_reserve_bit) {
1265fa2aee65SUwe Kleine-König 		for (epidx = 0; epidx < max_epid; epidx++) {
1266fa2aee65SUwe Kleine-König 			if (epidx == my_epid)
1267fa2aee65SUwe Kleine-König 				continue;
1268fa2aee65SUwe Kleine-König 
1269fa2aee65SUwe Kleine-König 			if (test_bit(epidx,
1270fa2aee65SUwe Kleine-König 				     &hw->hw_info.buffer_unshare_reserve_bit)) {
1271fa2aee65SUwe Kleine-König 				mutex_lock(&hw->hw_info.lock);
1272fa2aee65SUwe Kleine-König 
1273fa2aee65SUwe Kleine-König 				ret = fjes_hw_unregister_buff_addr(hw, epidx);
1274fa2aee65SUwe Kleine-König 				switch (ret) {
1275fa2aee65SUwe Kleine-König 				case 0:
1276fa2aee65SUwe Kleine-König 					break;
1277fa2aee65SUwe Kleine-König 				case -ENOMSG:
1278fa2aee65SUwe Kleine-König 				case -EBUSY:
1279fa2aee65SUwe Kleine-König 				default:
1280fa2aee65SUwe Kleine-König 					if (!work_pending(
1281fa2aee65SUwe Kleine-König 						&adapter->force_close_task)) {
1282fa2aee65SUwe Kleine-König 						adapter->force_reset = true;
1283fa2aee65SUwe Kleine-König 						schedule_work(
1284fa2aee65SUwe Kleine-König 							&adapter->force_close_task);
1285fa2aee65SUwe Kleine-König 					}
1286fa2aee65SUwe Kleine-König 					break;
1287fa2aee65SUwe Kleine-König 				}
1288fa2aee65SUwe Kleine-König 				mutex_unlock(&hw->hw_info.lock);
1289fa2aee65SUwe Kleine-König 
1290fa2aee65SUwe Kleine-König 				hw->ep_shm_info[epidx].ep_stats
1291fa2aee65SUwe Kleine-König 					.com_unregist_buf_exec += 1;
1292fa2aee65SUwe Kleine-König 
1293fa2aee65SUwe Kleine-König 				spin_lock_irqsave(&hw->rx_status_lock, flags);
1294fa2aee65SUwe Kleine-König 				fjes_hw_setup_epbuf(
1295fa2aee65SUwe Kleine-König 					&hw->ep_shm_info[epidx].tx,
1296fa2aee65SUwe Kleine-König 					netdev->dev_addr, netdev->mtu);
1297fa2aee65SUwe Kleine-König 				spin_unlock_irqrestore(&hw->rx_status_lock,
1298fa2aee65SUwe Kleine-König 						       flags);
1299fa2aee65SUwe Kleine-König 
1300fa2aee65SUwe Kleine-König 				clear_bit(epidx, &hw->txrx_stop_req_bit);
1301fa2aee65SUwe Kleine-König 				clear_bit(epidx, &unshare_watch_bitmask);
1302fa2aee65SUwe Kleine-König 				clear_bit(epidx, &hw->hw_info.buffer_unshare_reserve_bit);
1303fa2aee65SUwe Kleine-König 			}
1304fa2aee65SUwe Kleine-König 
1305fa2aee65SUwe Kleine-König 			if (test_bit(epidx, &unshare_watch_bitmask)) {
1306fa2aee65SUwe Kleine-König 				spin_lock_irqsave(&hw->rx_status_lock, flags);
1307fa2aee65SUwe Kleine-König 				hw->ep_shm_info[epidx].tx.info->v1i.rx_status &=
1308fa2aee65SUwe Kleine-König 						~FJES_RX_STOP_REQ_DONE;
1309fa2aee65SUwe Kleine-König 				spin_unlock_irqrestore(&hw->rx_status_lock,
1310fa2aee65SUwe Kleine-König 						       flags);
1311fa2aee65SUwe Kleine-König 			}
1312fa2aee65SUwe Kleine-König 		}
1313fa2aee65SUwe Kleine-König 	}
1314fa2aee65SUwe Kleine-König }
1315fa2aee65SUwe Kleine-König 
1316fa2aee65SUwe Kleine-König static void fjes_irq_watch_task(struct work_struct *work)
1317fa2aee65SUwe Kleine-König {
1318fa2aee65SUwe Kleine-König 	struct fjes_adapter *adapter = container_of(to_delayed_work(work),
1319fa2aee65SUwe Kleine-König 			struct fjes_adapter, interrupt_watch_task);
1320fa2aee65SUwe Kleine-König 
1321fa2aee65SUwe Kleine-König 	local_irq_disable();
1322fa2aee65SUwe Kleine-König 	fjes_intr(adapter->hw.hw_res.irq, adapter);
1323fa2aee65SUwe Kleine-König 	local_irq_enable();
1324fa2aee65SUwe Kleine-König 
1325fa2aee65SUwe Kleine-König 	if (fjes_rxframe_search_exist(adapter, 0) >= 0)
1326fa2aee65SUwe Kleine-König 		napi_schedule(&adapter->napi);
1327fa2aee65SUwe Kleine-König 
1328fa2aee65SUwe Kleine-König 	if (adapter->interrupt_watch_enable) {
1329fa2aee65SUwe Kleine-König 		if (!delayed_work_pending(&adapter->interrupt_watch_task))
1330fa2aee65SUwe Kleine-König 			queue_delayed_work(adapter->control_wq,
1331fa2aee65SUwe Kleine-König 					   &adapter->interrupt_watch_task,
1332fa2aee65SUwe Kleine-König 					   FJES_IRQ_WATCH_DELAY);
1333fa2aee65SUwe Kleine-König 	}
1334fa2aee65SUwe Kleine-König }
1335fa2aee65SUwe 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 
1471fa2aee65SUwe Kleine-König static struct platform_driver fjes_driver = {
1472fa2aee65SUwe Kleine-König 	.driver = {
1473fa2aee65SUwe Kleine-König 		.name = DRV_NAME,
1474fa2aee65SUwe Kleine-König 	},
1475fa2aee65SUwe Kleine-König 	.probe = fjes_probe,
1476fa2aee65SUwe Kleine-König 	.remove = fjes_remove,
1477fa2aee65SUwe 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