diff options
author | Taku Izumi <izumi.taku@jp.fujitsu.com> | 2015-08-21 04:29:23 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-08-24 17:06:34 -0400 |
commit | e5d486dcaa45dd365970c09395ae24df5a0e3f77 (patch) | |
tree | 237e68516fdbf7e3276c2524508397f9b0dbc31a | |
parent | 7950e6c5da55715debef9fa06b5ac87fb3eb4355 (diff) |
fjes: net_device_ops.ndo_open and .ndo_stop
This patch adds net_device_ops.ndo_open and .ndo_stop
callback. These function is called when network device
activation and deactivation.
Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/fjes/fjes.h | 1 | ||||
-rw-r--r-- | drivers/net/fjes/fjes_hw.c | 145 | ||||
-rw-r--r-- | drivers/net/fjes/fjes_hw.h | 30 | ||||
-rw-r--r-- | drivers/net/fjes/fjes_main.c | 246 | ||||
-rw-r--r-- | drivers/net/fjes/fjes_regs.h | 17 |
5 files changed, 439 insertions, 0 deletions
diff --git a/drivers/net/fjes/fjes.h b/drivers/net/fjes/fjes.h index 54bc189a997c..f182ed3a4cd1 100644 --- a/drivers/net/fjes/fjes.h +++ b/drivers/net/fjes/fjes.h | |||
@@ -29,6 +29,7 @@ | |||
29 | #define FJES_ACPI_SYMBOL "Extended Socket" | 29 | #define FJES_ACPI_SYMBOL "Extended Socket" |
30 | #define FJES_MAX_QUEUES 1 | 30 | #define FJES_MAX_QUEUES 1 |
31 | #define FJES_TX_RETRY_INTERVAL (20 * HZ) | 31 | #define FJES_TX_RETRY_INTERVAL (20 * HZ) |
32 | #define FJES_OPEN_ZONE_UPDATE_WAIT (300) /* msec */ | ||
32 | 33 | ||
33 | /* board specific private data structure */ | 34 | /* board specific private data structure */ |
34 | struct fjes_adapter { | 35 | struct fjes_adapter { |
diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c index 1e807dfc548a..1935f48e9e43 100644 --- a/drivers/net/fjes/fjes_hw.c +++ b/drivers/net/fjes/fjes_hw.c | |||
@@ -638,6 +638,25 @@ int fjes_hw_unregister_buff_addr(struct fjes_hw *hw, int dest_epid) | |||
638 | return result; | 638 | return result; |
639 | } | 639 | } |
640 | 640 | ||
641 | int fjes_hw_raise_interrupt(struct fjes_hw *hw, int dest_epid, | ||
642 | enum REG_ICTL_MASK mask) | ||
643 | { | ||
644 | u32 ig = mask | dest_epid; | ||
645 | |||
646 | wr32(XSCT_IG, cpu_to_le32(ig)); | ||
647 | |||
648 | return 0; | ||
649 | } | ||
650 | |||
651 | u32 fjes_hw_capture_interrupt_status(struct fjes_hw *hw) | ||
652 | { | ||
653 | u32 cur_is; | ||
654 | |||
655 | cur_is = rd32(XSCT_IS); | ||
656 | |||
657 | return cur_is; | ||
658 | } | ||
659 | |||
641 | void fjes_hw_set_irqmask(struct fjes_hw *hw, | 660 | void fjes_hw_set_irqmask(struct fjes_hw *hw, |
642 | enum REG_ICTL_MASK intr_mask, bool mask) | 661 | enum REG_ICTL_MASK intr_mask, bool mask) |
643 | { | 662 | { |
@@ -646,3 +665,129 @@ void fjes_hw_set_irqmask(struct fjes_hw *hw, | |||
646 | else | 665 | else |
647 | wr32(XSCT_IMC, intr_mask); | 666 | wr32(XSCT_IMC, intr_mask); |
648 | } | 667 | } |
668 | |||
669 | bool fjes_hw_epid_is_same_zone(struct fjes_hw *hw, int epid) | ||
670 | { | ||
671 | if (epid >= hw->max_epid) | ||
672 | return false; | ||
673 | |||
674 | if ((hw->ep_shm_info[epid].es_status != | ||
675 | FJES_ZONING_STATUS_ENABLE) || | ||
676 | (hw->ep_shm_info[hw->my_epid].zone == | ||
677 | FJES_ZONING_ZONE_TYPE_NONE)) | ||
678 | return false; | ||
679 | else | ||
680 | return (hw->ep_shm_info[epid].zone == | ||
681 | hw->ep_shm_info[hw->my_epid].zone); | ||
682 | } | ||
683 | |||
684 | int fjes_hw_epid_is_shared(struct fjes_device_shared_info *share, | ||
685 | int dest_epid) | ||
686 | { | ||
687 | int value = false; | ||
688 | |||
689 | if (dest_epid < share->epnum) | ||
690 | value = share->ep_status[dest_epid]; | ||
691 | |||
692 | return value; | ||
693 | } | ||
694 | |||
695 | static bool fjes_hw_epid_is_stop_requested(struct fjes_hw *hw, int src_epid) | ||
696 | { | ||
697 | return test_bit(src_epid, &hw->txrx_stop_req_bit); | ||
698 | } | ||
699 | |||
700 | static bool fjes_hw_epid_is_stop_process_done(struct fjes_hw *hw, int src_epid) | ||
701 | { | ||
702 | return (hw->ep_shm_info[src_epid].tx.info->v1i.rx_status & | ||
703 | FJES_RX_STOP_REQ_DONE); | ||
704 | } | ||
705 | |||
706 | enum ep_partner_status | ||
707 | fjes_hw_get_partner_ep_status(struct fjes_hw *hw, int epid) | ||
708 | { | ||
709 | enum ep_partner_status status; | ||
710 | |||
711 | if (fjes_hw_epid_is_shared(hw->hw_info.share, epid)) { | ||
712 | if (fjes_hw_epid_is_stop_requested(hw, epid)) { | ||
713 | status = EP_PARTNER_WAITING; | ||
714 | } else { | ||
715 | if (fjes_hw_epid_is_stop_process_done(hw, epid)) | ||
716 | status = EP_PARTNER_COMPLETE; | ||
717 | else | ||
718 | status = EP_PARTNER_SHARED; | ||
719 | } | ||
720 | } else { | ||
721 | status = EP_PARTNER_UNSHARE; | ||
722 | } | ||
723 | |||
724 | return status; | ||
725 | } | ||
726 | |||
727 | void fjes_hw_raise_epstop(struct fjes_hw *hw) | ||
728 | { | ||
729 | enum ep_partner_status status; | ||
730 | int epidx; | ||
731 | |||
732 | for (epidx = 0; epidx < hw->max_epid; epidx++) { | ||
733 | if (epidx == hw->my_epid) | ||
734 | continue; | ||
735 | |||
736 | status = fjes_hw_get_partner_ep_status(hw, epidx); | ||
737 | switch (status) { | ||
738 | case EP_PARTNER_SHARED: | ||
739 | fjes_hw_raise_interrupt(hw, epidx, | ||
740 | REG_ICTL_MASK_TXRX_STOP_REQ); | ||
741 | break; | ||
742 | default: | ||
743 | break; | ||
744 | } | ||
745 | |||
746 | set_bit(epidx, &hw->hw_info.buffer_unshare_reserve_bit); | ||
747 | set_bit(epidx, &hw->txrx_stop_req_bit); | ||
748 | |||
749 | hw->ep_shm_info[epidx].tx.info->v1i.rx_status |= | ||
750 | FJES_RX_STOP_REQ_REQUEST; | ||
751 | } | ||
752 | } | ||
753 | |||
754 | int fjes_hw_wait_epstop(struct fjes_hw *hw) | ||
755 | { | ||
756 | enum ep_partner_status status; | ||
757 | union ep_buffer_info *info; | ||
758 | int wait_time = 0; | ||
759 | int epidx; | ||
760 | |||
761 | while (hw->hw_info.buffer_unshare_reserve_bit && | ||
762 | (wait_time < FJES_COMMAND_EPSTOP_WAIT_TIMEOUT * 1000)) { | ||
763 | for (epidx = 0; epidx < hw->max_epid; epidx++) { | ||
764 | if (epidx == hw->my_epid) | ||
765 | continue; | ||
766 | status = fjes_hw_epid_is_shared(hw->hw_info.share, | ||
767 | epidx); | ||
768 | info = hw->ep_shm_info[epidx].rx.info; | ||
769 | if ((!status || | ||
770 | (info->v1i.rx_status & | ||
771 | FJES_RX_STOP_REQ_DONE)) && | ||
772 | test_bit(epidx, | ||
773 | &hw->hw_info.buffer_unshare_reserve_bit)) { | ||
774 | clear_bit(epidx, | ||
775 | &hw->hw_info.buffer_unshare_reserve_bit); | ||
776 | } | ||
777 | } | ||
778 | |||
779 | msleep(100); | ||
780 | wait_time += 100; | ||
781 | } | ||
782 | |||
783 | for (epidx = 0; epidx < hw->max_epid; epidx++) { | ||
784 | if (epidx == hw->my_epid) | ||
785 | continue; | ||
786 | if (test_bit(epidx, &hw->hw_info.buffer_unshare_reserve_bit)) | ||
787 | clear_bit(epidx, | ||
788 | &hw->hw_info.buffer_unshare_reserve_bit); | ||
789 | } | ||
790 | |||
791 | return (wait_time < FJES_COMMAND_EPSTOP_WAIT_TIMEOUT * 1000) | ||
792 | ? 0 : -EBUSY; | ||
793 | } | ||
diff --git a/drivers/net/fjes/fjes_hw.h b/drivers/net/fjes/fjes_hw.h index 2e750e9655ef..9b8df553f730 100644 --- a/drivers/net/fjes/fjes_hw.h +++ b/drivers/net/fjes/fjes_hw.h | |||
@@ -36,6 +36,7 @@ struct fjes_hw; | |||
36 | #define FJES_DEVICE_RESET_TIMEOUT ((17 + 1) * 3) /* sec */ | 36 | #define FJES_DEVICE_RESET_TIMEOUT ((17 + 1) * 3) /* sec */ |
37 | #define FJES_COMMAND_REQ_TIMEOUT (5 + 1) /* sec */ | 37 | #define FJES_COMMAND_REQ_TIMEOUT (5 + 1) /* sec */ |
38 | #define FJES_COMMAND_REQ_BUFF_TIMEOUT (8 * 3) /* sec */ | 38 | #define FJES_COMMAND_REQ_BUFF_TIMEOUT (8 * 3) /* sec */ |
39 | #define FJES_COMMAND_EPSTOP_WAIT_TIMEOUT (1) /* sec */ | ||
39 | 40 | ||
40 | #define FJES_CMD_REQ_ERR_INFO_PARAM (0x0001) | 41 | #define FJES_CMD_REQ_ERR_INFO_PARAM (0x0001) |
41 | #define FJES_CMD_REQ_ERR_INFO_STATUS (0x0002) | 42 | #define FJES_CMD_REQ_ERR_INFO_STATUS (0x0002) |
@@ -43,6 +44,17 @@ struct fjes_hw; | |||
43 | #define FJES_CMD_REQ_RES_CODE_NORMAL (0) | 44 | #define FJES_CMD_REQ_RES_CODE_NORMAL (0) |
44 | #define FJES_CMD_REQ_RES_CODE_BUSY (1) | 45 | #define FJES_CMD_REQ_RES_CODE_BUSY (1) |
45 | 46 | ||
47 | #define FJES_ZONING_STATUS_DISABLE (0x00) | ||
48 | #define FJES_ZONING_STATUS_ENABLE (0x01) | ||
49 | #define FJES_ZONING_STATUS_INVALID (0xFF) | ||
50 | |||
51 | #define FJES_ZONING_ZONE_TYPE_NONE (0xFF) | ||
52 | |||
53 | #define FJES_RX_STOP_REQ_NONE (0x0) | ||
54 | #define FJES_RX_STOP_REQ_DONE (0x1) | ||
55 | #define FJES_RX_STOP_REQ_REQUEST (0x2) | ||
56 | #define FJES_RX_POLL_WORK (0x4) | ||
57 | |||
46 | #define EP_BUFFER_SIZE \ | 58 | #define EP_BUFFER_SIZE \ |
47 | (((sizeof(union ep_buffer_info) + (128 * (64 * 1024))) \ | 59 | (((sizeof(union ep_buffer_info) + (128 * (64 * 1024))) \ |
48 | / EP_BUFFER_INFO_SIZE) * EP_BUFFER_INFO_SIZE) | 60 | / EP_BUFFER_INFO_SIZE) * EP_BUFFER_INFO_SIZE) |
@@ -77,6 +89,15 @@ struct esmem_frame { | |||
77 | u8 frame_data[]; | 89 | u8 frame_data[]; |
78 | }; | 90 | }; |
79 | 91 | ||
92 | /* EP partner status */ | ||
93 | enum ep_partner_status { | ||
94 | EP_PARTNER_UNSHARE, | ||
95 | EP_PARTNER_SHARED, | ||
96 | EP_PARTNER_WAITING, | ||
97 | EP_PARTNER_COMPLETE, | ||
98 | EP_PARTNER_STATUS_MAX, | ||
99 | }; | ||
100 | |||
80 | /* shared status region */ | 101 | /* shared status region */ |
81 | struct fjes_device_shared_info { | 102 | struct fjes_device_shared_info { |
82 | int epnum; | 103 | int epnum; |
@@ -278,6 +299,15 @@ int fjes_hw_unregister_buff_addr(struct fjes_hw *, int); | |||
278 | void fjes_hw_init_command_registers(struct fjes_hw *, | 299 | void fjes_hw_init_command_registers(struct fjes_hw *, |
279 | struct fjes_device_command_param *); | 300 | struct fjes_device_command_param *); |
280 | void fjes_hw_setup_epbuf(struct epbuf_handler *, u8 *, u32); | 301 | void fjes_hw_setup_epbuf(struct epbuf_handler *, u8 *, u32); |
302 | int fjes_hw_raise_interrupt(struct fjes_hw *, int, enum REG_ICTL_MASK); | ||
281 | void fjes_hw_set_irqmask(struct fjes_hw *, enum REG_ICTL_MASK, bool); | 303 | void fjes_hw_set_irqmask(struct fjes_hw *, enum REG_ICTL_MASK, bool); |
304 | u32 fjes_hw_capture_interrupt_status(struct fjes_hw *); | ||
305 | void fjes_hw_raise_epstop(struct fjes_hw *); | ||
306 | int fjes_hw_wait_epstop(struct fjes_hw *); | ||
307 | enum ep_partner_status | ||
308 | fjes_hw_get_partner_ep_status(struct fjes_hw *, int); | ||
309 | |||
310 | bool fjes_hw_epid_is_same_zone(struct fjes_hw *, int); | ||
311 | int fjes_hw_epid_is_shared(struct fjes_device_shared_info *, int); | ||
282 | 312 | ||
283 | #endif /* FJES_HW_H_ */ | 313 | #endif /* FJES_HW_H_ */ |
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c index 45a8b9c52ae5..bd50cbd6915f 100644 --- a/drivers/net/fjes/fjes_main.c +++ b/drivers/net/fjes/fjes_main.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/nls.h> | 24 | #include <linux/nls.h> |
25 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
26 | #include <linux/netdevice.h> | 26 | #include <linux/netdevice.h> |
27 | #include <linux/interrupt.h> | ||
27 | 28 | ||
28 | #include "fjes.h" | 29 | #include "fjes.h" |
29 | 30 | ||
@@ -43,6 +44,15 @@ MODULE_DESCRIPTION("FUJITSU Extended Socket Network Device Driver"); | |||
43 | MODULE_LICENSE("GPL"); | 44 | MODULE_LICENSE("GPL"); |
44 | MODULE_VERSION(DRV_VERSION); | 45 | MODULE_VERSION(DRV_VERSION); |
45 | 46 | ||
47 | static int fjes_request_irq(struct fjes_adapter *); | ||
48 | static void fjes_free_irq(struct fjes_adapter *); | ||
49 | |||
50 | static int fjes_open(struct net_device *); | ||
51 | static int fjes_close(struct net_device *); | ||
52 | static int fjes_setup_resources(struct fjes_adapter *); | ||
53 | static void fjes_free_resources(struct fjes_adapter *); | ||
54 | static irqreturn_t fjes_intr(int, void*); | ||
55 | |||
46 | static int fjes_acpi_add(struct acpi_device *); | 56 | static int fjes_acpi_add(struct acpi_device *); |
47 | static int fjes_acpi_remove(struct acpi_device *); | 57 | static int fjes_acpi_remove(struct acpi_device *); |
48 | static acpi_status fjes_get_acpi_resource(struct acpi_resource *, void*); | 58 | static acpi_status fjes_get_acpi_resource(struct acpi_resource *, void*); |
@@ -170,9 +180,245 @@ fjes_get_acpi_resource(struct acpi_resource *acpi_res, void *data) | |||
170 | return AE_OK; | 180 | return AE_OK; |
171 | } | 181 | } |
172 | 182 | ||
183 | static int fjes_request_irq(struct fjes_adapter *adapter) | ||
184 | { | ||
185 | struct net_device *netdev = adapter->netdev; | ||
186 | int result = -1; | ||
187 | |||
188 | if (!adapter->irq_registered) { | ||
189 | result = request_irq(adapter->hw.hw_res.irq, fjes_intr, | ||
190 | IRQF_SHARED, netdev->name, adapter); | ||
191 | if (result) | ||
192 | adapter->irq_registered = false; | ||
193 | else | ||
194 | adapter->irq_registered = true; | ||
195 | } | ||
196 | |||
197 | return result; | ||
198 | } | ||
199 | |||
200 | static void fjes_free_irq(struct fjes_adapter *adapter) | ||
201 | { | ||
202 | struct fjes_hw *hw = &adapter->hw; | ||
203 | |||
204 | fjes_hw_set_irqmask(hw, REG_ICTL_MASK_ALL, true); | ||
205 | |||
206 | if (adapter->irq_registered) { | ||
207 | free_irq(adapter->hw.hw_res.irq, adapter); | ||
208 | adapter->irq_registered = false; | ||
209 | } | ||
210 | } | ||
211 | |||
173 | static const struct net_device_ops fjes_netdev_ops = { | 212 | static const struct net_device_ops fjes_netdev_ops = { |
213 | .ndo_open = fjes_open, | ||
214 | .ndo_stop = fjes_close, | ||
174 | }; | 215 | }; |
175 | 216 | ||
217 | /* fjes_open - Called when a network interface is made active */ | ||
218 | static int fjes_open(struct net_device *netdev) | ||
219 | { | ||
220 | struct fjes_adapter *adapter = netdev_priv(netdev); | ||
221 | struct fjes_hw *hw = &adapter->hw; | ||
222 | int result; | ||
223 | |||
224 | if (adapter->open_guard) | ||
225 | return -ENXIO; | ||
226 | |||
227 | result = fjes_setup_resources(adapter); | ||
228 | if (result) | ||
229 | goto err_setup_res; | ||
230 | |||
231 | hw->txrx_stop_req_bit = 0; | ||
232 | hw->epstop_req_bit = 0; | ||
233 | |||
234 | fjes_hw_capture_interrupt_status(hw); | ||
235 | |||
236 | result = fjes_request_irq(adapter); | ||
237 | if (result) | ||
238 | goto err_req_irq; | ||
239 | |||
240 | fjes_hw_set_irqmask(hw, REG_ICTL_MASK_ALL, false); | ||
241 | |||
242 | netif_tx_start_all_queues(netdev); | ||
243 | netif_carrier_on(netdev); | ||
244 | |||
245 | return 0; | ||
246 | |||
247 | err_req_irq: | ||
248 | fjes_free_irq(adapter); | ||
249 | |||
250 | err_setup_res: | ||
251 | fjes_free_resources(adapter); | ||
252 | return result; | ||
253 | } | ||
254 | |||
255 | /* fjes_close - Disables a network interface */ | ||
256 | static int fjes_close(struct net_device *netdev) | ||
257 | { | ||
258 | struct fjes_adapter *adapter = netdev_priv(netdev); | ||
259 | struct fjes_hw *hw = &adapter->hw; | ||
260 | int epidx; | ||
261 | |||
262 | netif_tx_stop_all_queues(netdev); | ||
263 | netif_carrier_off(netdev); | ||
264 | |||
265 | fjes_hw_raise_epstop(hw); | ||
266 | |||
267 | for (epidx = 0; epidx < hw->max_epid; epidx++) { | ||
268 | if (epidx == hw->my_epid) | ||
269 | continue; | ||
270 | |||
271 | adapter->hw.ep_shm_info[epidx].tx.info->v1i.rx_status &= | ||
272 | ~FJES_RX_POLL_WORK; | ||
273 | } | ||
274 | |||
275 | fjes_free_irq(adapter); | ||
276 | |||
277 | fjes_hw_wait_epstop(hw); | ||
278 | |||
279 | fjes_free_resources(adapter); | ||
280 | |||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | static int fjes_setup_resources(struct fjes_adapter *adapter) | ||
285 | { | ||
286 | struct net_device *netdev = adapter->netdev; | ||
287 | struct ep_share_mem_info *buf_pair; | ||
288 | struct fjes_hw *hw = &adapter->hw; | ||
289 | int result; | ||
290 | int epidx; | ||
291 | |||
292 | mutex_lock(&hw->hw_info.lock); | ||
293 | result = fjes_hw_request_info(hw); | ||
294 | switch (result) { | ||
295 | case 0: | ||
296 | for (epidx = 0; epidx < hw->max_epid; epidx++) { | ||
297 | hw->ep_shm_info[epidx].es_status = | ||
298 | hw->hw_info.res_buf->info.info[epidx].es_status; | ||
299 | hw->ep_shm_info[epidx].zone = | ||
300 | hw->hw_info.res_buf->info.info[epidx].zone; | ||
301 | } | ||
302 | break; | ||
303 | default: | ||
304 | case -ENOMSG: | ||
305 | case -EBUSY: | ||
306 | adapter->force_reset = true; | ||
307 | |||
308 | mutex_unlock(&hw->hw_info.lock); | ||
309 | return result; | ||
310 | } | ||
311 | mutex_unlock(&hw->hw_info.lock); | ||
312 | |||
313 | for (epidx = 0; epidx < (hw->max_epid); epidx++) { | ||
314 | if ((epidx != hw->my_epid) && | ||
315 | (hw->ep_shm_info[epidx].es_status == | ||
316 | FJES_ZONING_STATUS_ENABLE)) { | ||
317 | fjes_hw_raise_interrupt(hw, epidx, | ||
318 | REG_ICTL_MASK_INFO_UPDATE); | ||
319 | } | ||
320 | } | ||
321 | |||
322 | msleep(FJES_OPEN_ZONE_UPDATE_WAIT * hw->max_epid); | ||
323 | |||
324 | for (epidx = 0; epidx < (hw->max_epid); epidx++) { | ||
325 | if (epidx == hw->my_epid) | ||
326 | continue; | ||
327 | |||
328 | buf_pair = &hw->ep_shm_info[epidx]; | ||
329 | |||
330 | fjes_hw_setup_epbuf(&buf_pair->tx, netdev->dev_addr, | ||
331 | netdev->mtu); | ||
332 | |||
333 | if (fjes_hw_epid_is_same_zone(hw, epidx)) { | ||
334 | mutex_lock(&hw->hw_info.lock); | ||
335 | result = | ||
336 | fjes_hw_register_buff_addr(hw, epidx, buf_pair); | ||
337 | mutex_unlock(&hw->hw_info.lock); | ||
338 | |||
339 | switch (result) { | ||
340 | case 0: | ||
341 | break; | ||
342 | case -ENOMSG: | ||
343 | case -EBUSY: | ||
344 | default: | ||
345 | adapter->force_reset = true; | ||
346 | return result; | ||
347 | } | ||
348 | } | ||
349 | } | ||
350 | |||
351 | return 0; | ||
352 | } | ||
353 | |||
354 | static void fjes_free_resources(struct fjes_adapter *adapter) | ||
355 | { | ||
356 | struct net_device *netdev = adapter->netdev; | ||
357 | struct fjes_device_command_param param; | ||
358 | struct ep_share_mem_info *buf_pair; | ||
359 | struct fjes_hw *hw = &adapter->hw; | ||
360 | bool reset_flag = false; | ||
361 | int result; | ||
362 | int epidx; | ||
363 | |||
364 | for (epidx = 0; epidx < hw->max_epid; epidx++) { | ||
365 | if (epidx == hw->my_epid) | ||
366 | continue; | ||
367 | |||
368 | mutex_lock(&hw->hw_info.lock); | ||
369 | result = fjes_hw_unregister_buff_addr(hw, epidx); | ||
370 | mutex_unlock(&hw->hw_info.lock); | ||
371 | |||
372 | if (result) | ||
373 | reset_flag = true; | ||
374 | |||
375 | buf_pair = &hw->ep_shm_info[epidx]; | ||
376 | |||
377 | fjes_hw_setup_epbuf(&buf_pair->tx, | ||
378 | netdev->dev_addr, netdev->mtu); | ||
379 | |||
380 | clear_bit(epidx, &hw->txrx_stop_req_bit); | ||
381 | } | ||
382 | |||
383 | if (reset_flag || adapter->force_reset) { | ||
384 | result = fjes_hw_reset(hw); | ||
385 | |||
386 | adapter->force_reset = false; | ||
387 | |||
388 | if (result) | ||
389 | adapter->open_guard = true; | ||
390 | |||
391 | hw->hw_info.buffer_share_bit = 0; | ||
392 | |||
393 | memset((void *)¶m, 0, sizeof(param)); | ||
394 | |||
395 | param.req_len = hw->hw_info.req_buf_size; | ||
396 | param.req_start = __pa(hw->hw_info.req_buf); | ||
397 | param.res_len = hw->hw_info.res_buf_size; | ||
398 | param.res_start = __pa(hw->hw_info.res_buf); | ||
399 | param.share_start = __pa(hw->hw_info.share->ep_status); | ||
400 | |||
401 | fjes_hw_init_command_registers(hw, ¶m); | ||
402 | } | ||
403 | } | ||
404 | |||
405 | static irqreturn_t fjes_intr(int irq, void *data) | ||
406 | { | ||
407 | struct fjes_adapter *adapter = data; | ||
408 | struct fjes_hw *hw = &adapter->hw; | ||
409 | irqreturn_t ret; | ||
410 | u32 icr; | ||
411 | |||
412 | icr = fjes_hw_capture_interrupt_status(hw); | ||
413 | |||
414 | if (icr & REG_IS_MASK_IS_ASSERT) | ||
415 | ret = IRQ_HANDLED; | ||
416 | else | ||
417 | ret = IRQ_NONE; | ||
418 | |||
419 | return ret; | ||
420 | } | ||
421 | |||
176 | /* fjes_probe - Device Initialization Routine */ | 422 | /* fjes_probe - Device Initialization Routine */ |
177 | static int fjes_probe(struct platform_device *plat_dev) | 423 | static int fjes_probe(struct platform_device *plat_dev) |
178 | { | 424 | { |
diff --git a/drivers/net/fjes/fjes_regs.h b/drivers/net/fjes/fjes_regs.h index cc975a0fd111..029c924dc175 100644 --- a/drivers/net/fjes/fjes_regs.h +++ b/drivers/net/fjes/fjes_regs.h | |||
@@ -49,8 +49,11 @@ | |||
49 | #define XSCT_RESPBAH 0x004C /* Response Buffer Address High */ | 49 | #define XSCT_RESPBAH 0x004C /* Response Buffer Address High */ |
50 | 50 | ||
51 | /* Interrupt Control registers */ | 51 | /* Interrupt Control registers */ |
52 | #define XSCT_IS 0x0080 /* Interrupt status */ | ||
52 | #define XSCT_IMS 0x0084 /* Interrupt mask set */ | 53 | #define XSCT_IMS 0x0084 /* Interrupt mask set */ |
53 | #define XSCT_IMC 0x0088 /* Interrupt mask clear */ | 54 | #define XSCT_IMC 0x0088 /* Interrupt mask clear */ |
55 | #define XSCT_IG 0x008C /* Interrupt generator */ | ||
56 | #define XSCT_ICTL 0x0090 /* Interrupt control */ | ||
54 | 57 | ||
55 | /* register structure */ | 58 | /* register structure */ |
56 | /* Information registers */ | 59 | /* Information registers */ |
@@ -101,6 +104,15 @@ union REG_CS { | |||
101 | __le32 reg; | 104 | __le32 reg; |
102 | }; | 105 | }; |
103 | 106 | ||
107 | /* Interrupt Control registers */ | ||
108 | union REG_ICTL { | ||
109 | struct { | ||
110 | __le32 automak:1; | ||
111 | __le32 rsv0:31; | ||
112 | } bits; | ||
113 | __le32 reg; | ||
114 | }; | ||
115 | |||
104 | enum REG_ICTL_MASK { | 116 | enum REG_ICTL_MASK { |
105 | REG_ICTL_MASK_INFO_UPDATE = 1 << 20, | 117 | REG_ICTL_MASK_INFO_UPDATE = 1 << 20, |
106 | REG_ICTL_MASK_DEV_STOP_REQ = 1 << 19, | 118 | REG_ICTL_MASK_DEV_STOP_REQ = 1 << 19, |
@@ -110,6 +122,11 @@ enum REG_ICTL_MASK { | |||
110 | REG_ICTL_MASK_ALL = GENMASK(20, 16), | 122 | REG_ICTL_MASK_ALL = GENMASK(20, 16), |
111 | }; | 123 | }; |
112 | 124 | ||
125 | enum REG_IS_MASK { | ||
126 | REG_IS_MASK_IS_ASSERT = 1 << 31, | ||
127 | REG_IS_MASK_EPID = GENMASK(15, 0), | ||
128 | }; | ||
129 | |||
113 | struct fjes_hw; | 130 | struct fjes_hw; |
114 | 131 | ||
115 | u32 fjes_hw_rd32(struct fjes_hw *hw, u32 reg); | 132 | u32 fjes_hw_rd32(struct fjes_hw *hw, u32 reg); |