diff options
Diffstat (limited to 'drivers/s390/net')
-rw-r--r-- | drivers/s390/net/Kconfig | 53 | ||||
-rw-r--r-- | drivers/s390/net/claw.c | 38 | ||||
-rw-r--r-- | drivers/s390/net/ctcm_fsms.c | 2 | ||||
-rw-r--r-- | drivers/s390/net/ctcm_main.c | 16 | ||||
-rw-r--r-- | drivers/s390/net/ctcm_mpc.c | 15 | ||||
-rw-r--r-- | drivers/s390/net/lcs.c | 38 | ||||
-rw-r--r-- | drivers/s390/net/netiucv.c | 4 | ||||
-rw-r--r-- | drivers/s390/net/qeth_core.h | 52 | ||||
-rw-r--r-- | drivers/s390/net/qeth_core_main.c | 508 | ||||
-rw-r--r-- | drivers/s390/net/qeth_core_mpc.h | 19 | ||||
-rw-r--r-- | drivers/s390/net/qeth_core_sys.c | 63 | ||||
-rw-r--r-- | drivers/s390/net/qeth_l2_main.c | 272 | ||||
-rw-r--r-- | drivers/s390/net/qeth_l3.h | 2 | ||||
-rw-r--r-- | drivers/s390/net/qeth_l3_main.c | 796 | ||||
-rw-r--r-- | drivers/s390/net/qeth_l3_sys.c | 103 | ||||
-rw-r--r-- | drivers/s390/net/smsgiucv.c | 2 |
16 files changed, 1058 insertions, 925 deletions
diff --git a/drivers/s390/net/Kconfig b/drivers/s390/net/Kconfig index 977bb4d4ed15..fa80ba1f0344 100644 --- a/drivers/s390/net/Kconfig +++ b/drivers/s390/net/Kconfig | |||
@@ -2,7 +2,8 @@ menu "S/390 network device drivers" | |||
2 | depends on NETDEVICES && S390 | 2 | depends on NETDEVICES && S390 |
3 | 3 | ||
4 | config LCS | 4 | config LCS |
5 | tristate "Lan Channel Station Interface" | 5 | def_tristate m |
6 | prompt "Lan Channel Station Interface" | ||
6 | depends on CCW && NETDEVICES && (NET_ETHERNET || TR || FDDI) | 7 | depends on CCW && NETDEVICES && (NET_ETHERNET || TR || FDDI) |
7 | help | 8 | help |
8 | Select this option if you want to use LCS networking on IBM System z. | 9 | Select this option if you want to use LCS networking on IBM System z. |
@@ -12,7 +13,8 @@ config LCS | |||
12 | If you do not know what it is, it's safe to choose Y. | 13 | If you do not know what it is, it's safe to choose Y. |
13 | 14 | ||
14 | config CTCM | 15 | config CTCM |
15 | tristate "CTC and MPC SNA device support" | 16 | def_tristate m |
17 | prompt "CTC and MPC SNA device support" | ||
16 | depends on CCW && NETDEVICES | 18 | depends on CCW && NETDEVICES |
17 | help | 19 | help |
18 | Select this option if you want to use channel-to-channel | 20 | Select this option if you want to use channel-to-channel |
@@ -26,7 +28,8 @@ config CTCM | |||
26 | If you do not need any channel-to-channel connection, choose N. | 28 | If you do not need any channel-to-channel connection, choose N. |
27 | 29 | ||
28 | config NETIUCV | 30 | config NETIUCV |
29 | tristate "IUCV network device support (VM only)" | 31 | def_tristate m |
32 | prompt "IUCV network device support (VM only)" | ||
30 | depends on IUCV && NETDEVICES | 33 | depends on IUCV && NETDEVICES |
31 | help | 34 | help |
32 | Select this option if you want to use inter-user communication | 35 | Select this option if you want to use inter-user communication |
@@ -37,14 +40,16 @@ config NETIUCV | |||
37 | The module name is netiucv. If unsure, choose Y. | 40 | The module name is netiucv. If unsure, choose Y. |
38 | 41 | ||
39 | config SMSGIUCV | 42 | config SMSGIUCV |
40 | tristate "IUCV special message support (VM only)" | 43 | def_tristate m |
44 | prompt "IUCV special message support (VM only)" | ||
41 | depends on IUCV | 45 | depends on IUCV |
42 | help | 46 | help |
43 | Select this option if you want to be able to receive SMSG messages | 47 | Select this option if you want to be able to receive SMSG messages |
44 | from other VM guest systems. | 48 | from other VM guest systems. |
45 | 49 | ||
46 | config SMSGIUCV_EVENT | 50 | config SMSGIUCV_EVENT |
47 | tristate "Deliver IUCV special messages as uevents (VM only)" | 51 | def_tristate m |
52 | prompt "Deliver IUCV special messages as uevents (VM only)" | ||
48 | depends on SMSGIUCV | 53 | depends on SMSGIUCV |
49 | help | 54 | help |
50 | Select this option to deliver CP special messages (SMSGs) as | 55 | Select this option to deliver CP special messages (SMSGs) as |
@@ -54,7 +59,8 @@ config SMSGIUCV_EVENT | |||
54 | To compile as a module, choose M. The module name is "smsgiucv_app". | 59 | To compile as a module, choose M. The module name is "smsgiucv_app". |
55 | 60 | ||
56 | config CLAW | 61 | config CLAW |
57 | tristate "CLAW device support" | 62 | def_tristate m |
63 | prompt "CLAW device support" | ||
58 | depends on CCW && NETDEVICES | 64 | depends on CCW && NETDEVICES |
59 | help | 65 | help |
60 | This driver supports channel attached CLAW devices. | 66 | This driver supports channel attached CLAW devices. |
@@ -64,7 +70,8 @@ config CLAW | |||
64 | To compile into the kernel, choose Y. | 70 | To compile into the kernel, choose Y. |
65 | 71 | ||
66 | config QETH | 72 | config QETH |
67 | tristate "Gigabit Ethernet device support" | 73 | def_tristate y |
74 | prompt "Gigabit Ethernet device support" | ||
68 | depends on CCW && NETDEVICES && IP_MULTICAST && QDIO | 75 | depends on CCW && NETDEVICES && IP_MULTICAST && QDIO |
69 | help | 76 | help |
70 | This driver supports the IBM System z OSA Express adapters | 77 | This driver supports the IBM System z OSA Express adapters |
@@ -78,28 +85,28 @@ config QETH | |||
78 | The module name is qeth. | 85 | The module name is qeth. |
79 | 86 | ||
80 | config QETH_L2 | 87 | config QETH_L2 |
81 | tristate "qeth layer 2 device support" | 88 | def_tristate y |
82 | depends on QETH | 89 | prompt "qeth layer 2 device support" |
83 | help | 90 | depends on QETH |
84 | Select this option to be able to run qeth devices in layer 2 mode. | 91 | help |
85 | To compile as a module, choose M. The module name is qeth_l2. | 92 | Select this option to be able to run qeth devices in layer 2 mode. |
86 | If unsure, choose y. | 93 | To compile as a module, choose M. The module name is qeth_l2. |
94 | If unsure, choose y. | ||
87 | 95 | ||
88 | config QETH_L3 | 96 | config QETH_L3 |
89 | tristate "qeth layer 3 device support" | 97 | def_tristate y |
90 | depends on QETH | 98 | prompt "qeth layer 3 device support" |
91 | help | 99 | depends on QETH |
92 | Select this option to be able to run qeth devices in layer 3 mode. | 100 | help |
93 | To compile as a module choose M. The module name is qeth_l3. | 101 | Select this option to be able to run qeth devices in layer 3 mode. |
94 | If unsure, choose Y. | 102 | To compile as a module choose M. The module name is qeth_l3. |
103 | If unsure, choose Y. | ||
95 | 104 | ||
96 | config QETH_IPV6 | 105 | config QETH_IPV6 |
97 | bool | 106 | def_bool y if (QETH_L3 = IPV6) || (QETH_L3 && IPV6 = 'y') |
98 | depends on (QETH_L3 = IPV6) || (QETH_L3 && IPV6 = 'y') | ||
99 | default y | ||
100 | 107 | ||
101 | config CCWGROUP | 108 | config CCWGROUP |
102 | tristate | 109 | tristate |
103 | default (LCS || CTCM || QETH) | 110 | default (LCS || CTCM || QETH || CLAW) |
104 | 111 | ||
105 | endmenu | 112 | endmenu |
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c index 8e4153d740f3..f1fa2483ae6b 100644 --- a/drivers/s390/net/claw.c +++ b/drivers/s390/net/claw.c | |||
@@ -63,6 +63,7 @@ | |||
63 | 63 | ||
64 | #define KMSG_COMPONENT "claw" | 64 | #define KMSG_COMPONENT "claw" |
65 | 65 | ||
66 | #include <linux/kernel_stat.h> | ||
66 | #include <asm/ccwdev.h> | 67 | #include <asm/ccwdev.h> |
67 | #include <asm/ccwgroup.h> | 68 | #include <asm/ccwgroup.h> |
68 | #include <asm/debug.h> | 69 | #include <asm/debug.h> |
@@ -263,8 +264,10 @@ static struct device *claw_root_dev; | |||
263 | /* ccwgroup table */ | 264 | /* ccwgroup table */ |
264 | 265 | ||
265 | static struct ccwgroup_driver claw_group_driver = { | 266 | static struct ccwgroup_driver claw_group_driver = { |
266 | .owner = THIS_MODULE, | 267 | .driver = { |
267 | .name = "claw", | 268 | .owner = THIS_MODULE, |
269 | .name = "claw", | ||
270 | }, | ||
268 | .max_slaves = 2, | 271 | .max_slaves = 2, |
269 | .driver_id = 0xC3D3C1E6, | 272 | .driver_id = 0xC3D3C1E6, |
270 | .probe = claw_probe, | 273 | .probe = claw_probe, |
@@ -281,8 +284,10 @@ static struct ccw_device_id claw_ids[] = { | |||
281 | MODULE_DEVICE_TABLE(ccw, claw_ids); | 284 | MODULE_DEVICE_TABLE(ccw, claw_ids); |
282 | 285 | ||
283 | static struct ccw_driver claw_ccw_driver = { | 286 | static struct ccw_driver claw_ccw_driver = { |
284 | .owner = THIS_MODULE, | 287 | .driver = { |
285 | .name = "claw", | 288 | .owner = THIS_MODULE, |
289 | .name = "claw", | ||
290 | }, | ||
286 | .ids = claw_ids, | 291 | .ids = claw_ids, |
287 | .probe = ccwgroup_probe_ccwdev, | 292 | .probe = ccwgroup_probe_ccwdev, |
288 | .remove = ccwgroup_remove_ccwdev, | 293 | .remove = ccwgroup_remove_ccwdev, |
@@ -640,6 +645,7 @@ claw_irq_handler(struct ccw_device *cdev, | |||
640 | struct claw_env *p_env; | 645 | struct claw_env *p_env; |
641 | struct chbk *p_ch_r=NULL; | 646 | struct chbk *p_ch_r=NULL; |
642 | 647 | ||
648 | kstat_cpu(smp_processor_id()).irqs[IOINT_CLW]++; | ||
643 | CLAW_DBF_TEXT(4, trace, "clawirq"); | 649 | CLAW_DBF_TEXT(4, trace, "clawirq"); |
644 | /* Bypass all 'unsolicited interrupts' */ | 650 | /* Bypass all 'unsolicited interrupts' */ |
645 | privptr = dev_get_drvdata(&cdev->dev); | 651 | privptr = dev_get_drvdata(&cdev->dev); |
@@ -773,7 +779,7 @@ claw_irq_handler(struct ccw_device *cdev, | |||
773 | case CLAW_START_WRITE: | 779 | case CLAW_START_WRITE: |
774 | if (p_ch->irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) { | 780 | if (p_ch->irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) { |
775 | dev_info(&cdev->dev, | 781 | dev_info(&cdev->dev, |
776 | "%s: Unit Check Occured in " | 782 | "%s: Unit Check Occurred in " |
777 | "write channel\n", dev->name); | 783 | "write channel\n", dev->name); |
778 | clear_bit(0, (void *)&p_ch->IO_active); | 784 | clear_bit(0, (void *)&p_ch->IO_active); |
779 | if (p_ch->irb->ecw[0] & 0x80) { | 785 | if (p_ch->irb->ecw[0] & 0x80) { |
@@ -839,12 +845,10 @@ claw_irq_tasklet ( unsigned long data ) | |||
839 | { | 845 | { |
840 | struct chbk * p_ch; | 846 | struct chbk * p_ch; |
841 | struct net_device *dev; | 847 | struct net_device *dev; |
842 | struct claw_privbk * privptr; | ||
843 | 848 | ||
844 | p_ch = (struct chbk *) data; | 849 | p_ch = (struct chbk *) data; |
845 | dev = (struct net_device *)p_ch->ndev; | 850 | dev = (struct net_device *)p_ch->ndev; |
846 | CLAW_DBF_TEXT(4, trace, "IRQtask"); | 851 | CLAW_DBF_TEXT(4, trace, "IRQtask"); |
847 | privptr = (struct claw_privbk *)dev->ml_priv; | ||
848 | unpack_read(dev); | 852 | unpack_read(dev); |
849 | clear_bit(CLAW_BH_ACTIVE, (void *)&p_ch->flag_a); | 853 | clear_bit(CLAW_BH_ACTIVE, (void *)&p_ch->flag_a); |
850 | CLAW_DBF_TEXT(4, trace, "TskletXt"); | 854 | CLAW_DBF_TEXT(4, trace, "TskletXt"); |
@@ -1020,7 +1024,6 @@ claw_write_next ( struct chbk * p_ch ) | |||
1020 | struct net_device *dev; | 1024 | struct net_device *dev; |
1021 | struct claw_privbk *privptr=NULL; | 1025 | struct claw_privbk *privptr=NULL; |
1022 | struct sk_buff *pk_skb; | 1026 | struct sk_buff *pk_skb; |
1023 | int rc; | ||
1024 | 1027 | ||
1025 | CLAW_DBF_TEXT(4, trace, "claw_wrt"); | 1028 | CLAW_DBF_TEXT(4, trace, "claw_wrt"); |
1026 | if (p_ch->claw_state == CLAW_STOP) | 1029 | if (p_ch->claw_state == CLAW_STOP) |
@@ -1032,7 +1035,7 @@ claw_write_next ( struct chbk * p_ch ) | |||
1032 | !skb_queue_empty(&p_ch->collect_queue)) { | 1035 | !skb_queue_empty(&p_ch->collect_queue)) { |
1033 | pk_skb = claw_pack_skb(privptr); | 1036 | pk_skb = claw_pack_skb(privptr); |
1034 | while (pk_skb != NULL) { | 1037 | while (pk_skb != NULL) { |
1035 | rc = claw_hw_tx( pk_skb, dev,1); | 1038 | claw_hw_tx(pk_skb, dev, 1); |
1036 | if (privptr->write_free_count > 0) { | 1039 | if (privptr->write_free_count > 0) { |
1037 | pk_skb = claw_pack_skb(privptr); | 1040 | pk_skb = claw_pack_skb(privptr); |
1038 | } else | 1041 | } else |
@@ -1316,15 +1319,12 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid) | |||
1316 | unsigned char *pDataAddress; | 1319 | unsigned char *pDataAddress; |
1317 | struct endccw *pEnd; | 1320 | struct endccw *pEnd; |
1318 | struct ccw1 tempCCW; | 1321 | struct ccw1 tempCCW; |
1319 | struct chbk *p_ch; | ||
1320 | struct claw_env *p_env; | 1322 | struct claw_env *p_env; |
1321 | int lock; | ||
1322 | struct clawph *pk_head; | 1323 | struct clawph *pk_head; |
1323 | struct chbk *ch; | 1324 | struct chbk *ch; |
1324 | 1325 | ||
1325 | CLAW_DBF_TEXT(4, trace, "hw_tx"); | 1326 | CLAW_DBF_TEXT(4, trace, "hw_tx"); |
1326 | privptr = (struct claw_privbk *)(dev->ml_priv); | 1327 | privptr = (struct claw_privbk *)(dev->ml_priv); |
1327 | p_ch = (struct chbk *)&privptr->channel[WRITE_CHANNEL]; | ||
1328 | p_env =privptr->p_env; | 1328 | p_env =privptr->p_env; |
1329 | claw_free_wrt_buf(dev); /* Clean up free chain if posible */ | 1329 | claw_free_wrt_buf(dev); /* Clean up free chain if posible */ |
1330 | /* scan the write queue to free any completed write packets */ | 1330 | /* scan the write queue to free any completed write packets */ |
@@ -1505,12 +1505,6 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid) | |||
1505 | 1505 | ||
1506 | } /* endif (p_first_ccw!=NULL) */ | 1506 | } /* endif (p_first_ccw!=NULL) */ |
1507 | dev_kfree_skb_any(skb); | 1507 | dev_kfree_skb_any(skb); |
1508 | if (linkid==0) { | ||
1509 | lock=LOCK_NO; | ||
1510 | } | ||
1511 | else { | ||
1512 | lock=LOCK_YES; | ||
1513 | } | ||
1514 | claw_strt_out_IO(dev ); | 1508 | claw_strt_out_IO(dev ); |
1515 | /* if write free count is zero , set NOBUFFER */ | 1509 | /* if write free count is zero , set NOBUFFER */ |
1516 | if (privptr->write_free_count==0) { | 1510 | if (privptr->write_free_count==0) { |
@@ -2815,15 +2809,11 @@ claw_free_wrt_buf( struct net_device *dev ) | |||
2815 | { | 2809 | { |
2816 | 2810 | ||
2817 | struct claw_privbk *privptr = (struct claw_privbk *)dev->ml_priv; | 2811 | struct claw_privbk *privptr = (struct claw_privbk *)dev->ml_priv; |
2818 | struct ccwbk*p_first_ccw; | ||
2819 | struct ccwbk*p_last_ccw; | ||
2820 | struct ccwbk*p_this_ccw; | 2812 | struct ccwbk*p_this_ccw; |
2821 | struct ccwbk*p_next_ccw; | 2813 | struct ccwbk*p_next_ccw; |
2822 | 2814 | ||
2823 | CLAW_DBF_TEXT(4, trace, "freewrtb"); | 2815 | CLAW_DBF_TEXT(4, trace, "freewrtb"); |
2824 | /* scan the write queue to free any completed write packets */ | 2816 | /* scan the write queue to free any completed write packets */ |
2825 | p_first_ccw=NULL; | ||
2826 | p_last_ccw=NULL; | ||
2827 | p_this_ccw=privptr->p_write_active_first; | 2817 | p_this_ccw=privptr->p_write_active_first; |
2828 | while ( (p_this_ccw!=NULL) && (p_this_ccw->header.flag!=CLAW_PENDING)) | 2818 | while ( (p_this_ccw!=NULL) && (p_this_ccw->header.flag!=CLAW_PENDING)) |
2829 | { | 2819 | { |
@@ -3066,7 +3056,7 @@ claw_shutdown_device(struct ccwgroup_device *cgdev) | |||
3066 | { | 3056 | { |
3067 | struct claw_privbk *priv; | 3057 | struct claw_privbk *priv; |
3068 | struct net_device *ndev; | 3058 | struct net_device *ndev; |
3069 | int ret; | 3059 | int ret = 0; |
3070 | 3060 | ||
3071 | CLAW_DBF_TEXT_(2, setup, "%s", dev_name(&cgdev->dev)); | 3061 | CLAW_DBF_TEXT_(2, setup, "%s", dev_name(&cgdev->dev)); |
3072 | priv = dev_get_drvdata(&cgdev->dev); | 3062 | priv = dev_get_drvdata(&cgdev->dev); |
@@ -3089,7 +3079,7 @@ claw_shutdown_device(struct ccwgroup_device *cgdev) | |||
3089 | } | 3079 | } |
3090 | ccw_device_set_offline(cgdev->cdev[1]); | 3080 | ccw_device_set_offline(cgdev->cdev[1]); |
3091 | ccw_device_set_offline(cgdev->cdev[0]); | 3081 | ccw_device_set_offline(cgdev->cdev[0]); |
3092 | return 0; | 3082 | return ret; |
3093 | } | 3083 | } |
3094 | 3084 | ||
3095 | static void | 3085 | static void |
diff --git a/drivers/s390/net/ctcm_fsms.c b/drivers/s390/net/ctcm_fsms.c index 8c921fc3511a..2d602207541b 100644 --- a/drivers/s390/net/ctcm_fsms.c +++ b/drivers/s390/net/ctcm_fsms.c | |||
@@ -184,7 +184,7 @@ static void ctcmpc_chx_resend(fsm_instance *, int, void *); | |||
184 | static void ctcmpc_chx_send_sweep(fsm_instance *fsm, int event, void *arg); | 184 | static void ctcmpc_chx_send_sweep(fsm_instance *fsm, int event, void *arg); |
185 | 185 | ||
186 | /** | 186 | /** |
187 | * Check return code of a preceeding ccw_device call, halt_IO etc... | 187 | * Check return code of a preceding ccw_device call, halt_IO etc... |
188 | * | 188 | * |
189 | * ch : The channel, the error belongs to. | 189 | * ch : The channel, the error belongs to. |
190 | * Returns the error code (!= 0) to inspect. | 190 | * Returns the error code (!= 0) to inspect. |
diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c index 2c7d2d9be4d0..426787efc492 100644 --- a/drivers/s390/net/ctcm_main.c +++ b/drivers/s390/net/ctcm_main.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #define KMSG_COMPONENT "ctcm" | 24 | #define KMSG_COMPONENT "ctcm" |
25 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | 25 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt |
26 | 26 | ||
27 | #include <linux/kernel_stat.h> | ||
27 | #include <linux/module.h> | 28 | #include <linux/module.h> |
28 | #include <linux/init.h> | 29 | #include <linux/init.h> |
29 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
@@ -671,7 +672,6 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb) | |||
671 | int ccw_idx; | 672 | int ccw_idx; |
672 | unsigned long hi; | 673 | unsigned long hi; |
673 | unsigned long saveflags = 0; /* avoids compiler warning */ | 674 | unsigned long saveflags = 0; /* avoids compiler warning */ |
674 | __u16 block_len; | ||
675 | 675 | ||
676 | CTCM_PR_DEBUG("Enter %s: %s, cp=%i ch=0x%p id=%s state=%s\n", | 676 | CTCM_PR_DEBUG("Enter %s: %s, cp=%i ch=0x%p id=%s state=%s\n", |
677 | __func__, dev->name, smp_processor_id(), ch, | 677 | __func__, dev->name, smp_processor_id(), ch, |
@@ -718,7 +718,6 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb) | |||
718 | */ | 718 | */ |
719 | atomic_inc(&skb->users); | 719 | atomic_inc(&skb->users); |
720 | 720 | ||
721 | block_len = skb->len + TH_HEADER_LENGTH + PDU_HEADER_LENGTH; | ||
722 | /* | 721 | /* |
723 | * IDAL support in CTCM is broken, so we have to | 722 | * IDAL support in CTCM is broken, so we have to |
724 | * care about skb's above 2G ourselves. | 723 | * care about skb's above 2G ourselves. |
@@ -1204,6 +1203,7 @@ static void ctcm_irq_handler(struct ccw_device *cdev, | |||
1204 | int cstat; | 1203 | int cstat; |
1205 | int dstat; | 1204 | int dstat; |
1206 | 1205 | ||
1206 | kstat_cpu(smp_processor_id()).irqs[IOINT_CTC]++; | ||
1207 | CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG, | 1207 | CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG, |
1208 | "Enter %s(%s)", CTCM_FUNTAIL, dev_name(&cdev->dev)); | 1208 | "Enter %s(%s)", CTCM_FUNTAIL, dev_name(&cdev->dev)); |
1209 | 1209 | ||
@@ -1762,16 +1762,20 @@ static struct ccw_device_id ctcm_ids[] = { | |||
1762 | MODULE_DEVICE_TABLE(ccw, ctcm_ids); | 1762 | MODULE_DEVICE_TABLE(ccw, ctcm_ids); |
1763 | 1763 | ||
1764 | static struct ccw_driver ctcm_ccw_driver = { | 1764 | static struct ccw_driver ctcm_ccw_driver = { |
1765 | .owner = THIS_MODULE, | 1765 | .driver = { |
1766 | .name = "ctcm", | 1766 | .owner = THIS_MODULE, |
1767 | .name = "ctcm", | ||
1768 | }, | ||
1767 | .ids = ctcm_ids, | 1769 | .ids = ctcm_ids, |
1768 | .probe = ccwgroup_probe_ccwdev, | 1770 | .probe = ccwgroup_probe_ccwdev, |
1769 | .remove = ccwgroup_remove_ccwdev, | 1771 | .remove = ccwgroup_remove_ccwdev, |
1770 | }; | 1772 | }; |
1771 | 1773 | ||
1772 | static struct ccwgroup_driver ctcm_group_driver = { | 1774 | static struct ccwgroup_driver ctcm_group_driver = { |
1773 | .owner = THIS_MODULE, | 1775 | .driver = { |
1774 | .name = CTC_DRIVER_NAME, | 1776 | .owner = THIS_MODULE, |
1777 | .name = CTC_DRIVER_NAME, | ||
1778 | }, | ||
1775 | .max_slaves = 2, | 1779 | .max_slaves = 2, |
1776 | .driver_id = 0xC3E3C3D4, /* CTCM */ | 1780 | .driver_id = 0xC3E3C3D4, /* CTCM */ |
1777 | .probe = ctcm_probe_device, | 1781 | .probe = ctcm_probe_device, |
diff --git a/drivers/s390/net/ctcm_mpc.c b/drivers/s390/net/ctcm_mpc.c index 2861e78773cb..da4c747335e7 100644 --- a/drivers/s390/net/ctcm_mpc.c +++ b/drivers/s390/net/ctcm_mpc.c | |||
@@ -540,7 +540,7 @@ void ctc_mpc_dealloc_ch(int port_num) | |||
540 | 540 | ||
541 | CTCM_DBF_TEXT_(MPC_SETUP, CTC_DBF_DEBUG, | 541 | CTCM_DBF_TEXT_(MPC_SETUP, CTC_DBF_DEBUG, |
542 | "%s: %s: refcount = %d\n", | 542 | "%s: %s: refcount = %d\n", |
543 | CTCM_FUNTAIL, dev->name, atomic_read(&dev->refcnt)); | 543 | CTCM_FUNTAIL, dev->name, netdev_refcnt_read(dev)); |
544 | 544 | ||
545 | fsm_deltimer(&priv->restart_timer); | 545 | fsm_deltimer(&priv->restart_timer); |
546 | grp->channels_terminating = 0; | 546 | grp->channels_terminating = 0; |
@@ -653,7 +653,6 @@ static void ctcmpc_send_sweep_resp(struct channel *rch) | |||
653 | struct net_device *dev = rch->netdev; | 653 | struct net_device *dev = rch->netdev; |
654 | struct ctcm_priv *priv = dev->ml_priv; | 654 | struct ctcm_priv *priv = dev->ml_priv; |
655 | struct mpc_group *grp = priv->mpcg; | 655 | struct mpc_group *grp = priv->mpcg; |
656 | int rc = 0; | ||
657 | struct th_sweep *header; | 656 | struct th_sweep *header; |
658 | struct sk_buff *sweep_skb; | 657 | struct sk_buff *sweep_skb; |
659 | struct channel *ch = priv->channel[CTCM_WRITE]; | 658 | struct channel *ch = priv->channel[CTCM_WRITE]; |
@@ -665,16 +664,14 @@ static void ctcmpc_send_sweep_resp(struct channel *rch) | |||
665 | CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR, | 664 | CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR, |
666 | "%s(%s): sweep_skb allocation ERROR\n", | 665 | "%s(%s): sweep_skb allocation ERROR\n", |
667 | CTCM_FUNTAIL, rch->id); | 666 | CTCM_FUNTAIL, rch->id); |
668 | rc = -ENOMEM; | 667 | goto done; |
669 | goto done; | ||
670 | } | 668 | } |
671 | 669 | ||
672 | header = kmalloc(sizeof(struct th_sweep), gfp_type()); | 670 | header = kmalloc(sizeof(struct th_sweep), gfp_type()); |
673 | 671 | ||
674 | if (!header) { | 672 | if (!header) { |
675 | dev_kfree_skb_any(sweep_skb); | 673 | dev_kfree_skb_any(sweep_skb); |
676 | rc = -ENOMEM; | 674 | goto done; |
677 | goto done; | ||
678 | } | 675 | } |
679 | 676 | ||
680 | header->th.th_seg = 0x00 ; | 677 | header->th.th_seg = 0x00 ; |
@@ -1370,8 +1367,7 @@ static void mpc_action_go_inop(fsm_instance *fi, int event, void *arg) | |||
1370 | struct net_device *dev = arg; | 1367 | struct net_device *dev = arg; |
1371 | struct ctcm_priv *priv; | 1368 | struct ctcm_priv *priv; |
1372 | struct mpc_group *grp; | 1369 | struct mpc_group *grp; |
1373 | int rc = 0; | 1370 | struct channel *wch; |
1374 | struct channel *wch, *rch; | ||
1375 | 1371 | ||
1376 | BUG_ON(dev == NULL); | 1372 | BUG_ON(dev == NULL); |
1377 | CTCM_PR_DEBUG("Enter %s: %s\n", __func__, dev->name); | 1373 | CTCM_PR_DEBUG("Enter %s: %s\n", __func__, dev->name); |
@@ -1396,7 +1392,6 @@ static void mpc_action_go_inop(fsm_instance *fi, int event, void *arg) | |||
1396 | fsm_deltimer(&priv->restart_timer); | 1392 | fsm_deltimer(&priv->restart_timer); |
1397 | 1393 | ||
1398 | wch = priv->channel[CTCM_WRITE]; | 1394 | wch = priv->channel[CTCM_WRITE]; |
1399 | rch = priv->channel[CTCM_READ]; | ||
1400 | 1395 | ||
1401 | switch (grp->saved_state) { | 1396 | switch (grp->saved_state) { |
1402 | case MPCG_STATE_RESET: | 1397 | case MPCG_STATE_RESET: |
@@ -1435,7 +1430,7 @@ static void mpc_action_go_inop(fsm_instance *fi, int event, void *arg) | |||
1435 | 1430 | ||
1436 | if (grp->send_qllc_disc == 1) { | 1431 | if (grp->send_qllc_disc == 1) { |
1437 | grp->send_qllc_disc = 0; | 1432 | grp->send_qllc_disc = 0; |
1438 | rc = mpc_send_qllc_discontact(dev); | 1433 | mpc_send_qllc_discontact(dev); |
1439 | } | 1434 | } |
1440 | 1435 | ||
1441 | /* DO NOT issue DEV_EVENT_STOP directly out of this code */ | 1436 | /* DO NOT issue DEV_EVENT_STOP directly out of this code */ |
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index 0f19d540b655..c3b8064a102d 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #define KMSG_COMPONENT "lcs" | 26 | #define KMSG_COMPONENT "lcs" |
27 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | 27 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt |
28 | 28 | ||
29 | #include <linux/kernel_stat.h> | ||
29 | #include <linux/module.h> | 30 | #include <linux/module.h> |
30 | #include <linux/if.h> | 31 | #include <linux/if.h> |
31 | #include <linux/netdevice.h> | 32 | #include <linux/netdevice.h> |
@@ -840,7 +841,7 @@ lcs_notify_lancmd_waiters(struct lcs_card *card, struct lcs_cmd *cmd) | |||
840 | } | 841 | } |
841 | 842 | ||
842 | /** | 843 | /** |
843 | * Emit buffer of a lan comand. | 844 | * Emit buffer of a lan command. |
844 | */ | 845 | */ |
845 | static void | 846 | static void |
846 | lcs_lancmd_timeout(unsigned long data) | 847 | lcs_lancmd_timeout(unsigned long data) |
@@ -1122,7 +1123,7 @@ list_modified: | |||
1122 | list_for_each_entry_safe(ipm, tmp, &card->ipm_list, list){ | 1123 | list_for_each_entry_safe(ipm, tmp, &card->ipm_list, list){ |
1123 | switch (ipm->ipm_state) { | 1124 | switch (ipm->ipm_state) { |
1124 | case LCS_IPM_STATE_SET_REQUIRED: | 1125 | case LCS_IPM_STATE_SET_REQUIRED: |
1125 | /* del from ipm_list so noone else can tamper with | 1126 | /* del from ipm_list so no one else can tamper with |
1126 | * this entry */ | 1127 | * this entry */ |
1127 | list_del_init(&ipm->list); | 1128 | list_del_init(&ipm->list); |
1128 | spin_unlock_irqrestore(&card->ipm_lock, flags); | 1129 | spin_unlock_irqrestore(&card->ipm_lock, flags); |
@@ -1188,7 +1189,8 @@ lcs_remove_mc_addresses(struct lcs_card *card, struct in_device *in4_dev) | |||
1188 | spin_lock_irqsave(&card->ipm_lock, flags); | 1189 | spin_lock_irqsave(&card->ipm_lock, flags); |
1189 | list_for_each(l, &card->ipm_list) { | 1190 | list_for_each(l, &card->ipm_list) { |
1190 | ipm = list_entry(l, struct lcs_ipm_list, list); | 1191 | ipm = list_entry(l, struct lcs_ipm_list, list); |
1191 | for (im4 = in4_dev->mc_list; im4 != NULL; im4 = im4->next) { | 1192 | for (im4 = rcu_dereference(in4_dev->mc_list); |
1193 | im4 != NULL; im4 = rcu_dereference(im4->next_rcu)) { | ||
1192 | lcs_get_mac_for_ipm(im4->multiaddr, buf, card->dev); | 1194 | lcs_get_mac_for_ipm(im4->multiaddr, buf, card->dev); |
1193 | if ( (ipm->ipm.ip_addr == im4->multiaddr) && | 1195 | if ( (ipm->ipm.ip_addr == im4->multiaddr) && |
1194 | (memcmp(buf, &ipm->ipm.mac_addr, | 1196 | (memcmp(buf, &ipm->ipm.mac_addr, |
@@ -1233,7 +1235,8 @@ lcs_set_mc_addresses(struct lcs_card *card, struct in_device *in4_dev) | |||
1233 | unsigned long flags; | 1235 | unsigned long flags; |
1234 | 1236 | ||
1235 | LCS_DBF_TEXT(4, trace, "setmclst"); | 1237 | LCS_DBF_TEXT(4, trace, "setmclst"); |
1236 | for (im4 = in4_dev->mc_list; im4; im4 = im4->next) { | 1238 | for (im4 = rcu_dereference(in4_dev->mc_list); im4 != NULL; |
1239 | im4 = rcu_dereference(im4->next_rcu)) { | ||
1237 | lcs_get_mac_for_ipm(im4->multiaddr, buf, card->dev); | 1240 | lcs_get_mac_for_ipm(im4->multiaddr, buf, card->dev); |
1238 | ipm = lcs_check_addr_entry(card, im4, buf); | 1241 | ipm = lcs_check_addr_entry(card, im4, buf); |
1239 | if (ipm != NULL) | 1242 | if (ipm != NULL) |
@@ -1269,10 +1272,10 @@ lcs_register_mc_addresses(void *data) | |||
1269 | in4_dev = in_dev_get(card->dev); | 1272 | in4_dev = in_dev_get(card->dev); |
1270 | if (in4_dev == NULL) | 1273 | if (in4_dev == NULL) |
1271 | goto out; | 1274 | goto out; |
1272 | read_lock(&in4_dev->mc_list_lock); | 1275 | rcu_read_lock(); |
1273 | lcs_remove_mc_addresses(card,in4_dev); | 1276 | lcs_remove_mc_addresses(card,in4_dev); |
1274 | lcs_set_mc_addresses(card, in4_dev); | 1277 | lcs_set_mc_addresses(card, in4_dev); |
1275 | read_unlock(&in4_dev->mc_list_lock); | 1278 | rcu_read_unlock(); |
1276 | in_dev_put(in4_dev); | 1279 | in_dev_put(in4_dev); |
1277 | 1280 | ||
1278 | netif_carrier_off(card->dev); | 1281 | netif_carrier_off(card->dev); |
@@ -1396,6 +1399,7 @@ lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb) | |||
1396 | int rc, index; | 1399 | int rc, index; |
1397 | int cstat, dstat; | 1400 | int cstat, dstat; |
1398 | 1401 | ||
1402 | kstat_cpu(smp_processor_id()).irqs[IOINT_LCS]++; | ||
1399 | if (lcs_check_irb_error(cdev, irb)) | 1403 | if (lcs_check_irb_error(cdev, irb)) |
1400 | return; | 1404 | return; |
1401 | 1405 | ||
@@ -1479,7 +1483,6 @@ lcs_tasklet(unsigned long data) | |||
1479 | struct lcs_channel *channel; | 1483 | struct lcs_channel *channel; |
1480 | struct lcs_buffer *iob; | 1484 | struct lcs_buffer *iob; |
1481 | int buf_idx; | 1485 | int buf_idx; |
1482 | int rc; | ||
1483 | 1486 | ||
1484 | channel = (struct lcs_channel *) data; | 1487 | channel = (struct lcs_channel *) data; |
1485 | LCS_DBF_TEXT_(5, trace, "tlet%s", dev_name(&channel->ccwdev->dev)); | 1488 | LCS_DBF_TEXT_(5, trace, "tlet%s", dev_name(&channel->ccwdev->dev)); |
@@ -1496,14 +1499,11 @@ lcs_tasklet(unsigned long data) | |||
1496 | channel->buf_idx = buf_idx; | 1499 | channel->buf_idx = buf_idx; |
1497 | 1500 | ||
1498 | if (channel->state == LCS_CH_STATE_STOPPED) | 1501 | if (channel->state == LCS_CH_STATE_STOPPED) |
1499 | // FIXME: what if rc != 0 ?? | 1502 | lcs_start_channel(channel); |
1500 | rc = lcs_start_channel(channel); | ||
1501 | spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags); | 1503 | spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags); |
1502 | if (channel->state == LCS_CH_STATE_SUSPENDED && | 1504 | if (channel->state == LCS_CH_STATE_SUSPENDED && |
1503 | channel->iob[channel->io_idx].state == LCS_BUF_STATE_READY) { | 1505 | channel->iob[channel->io_idx].state == LCS_BUF_STATE_READY) |
1504 | // FIXME: what if rc != 0 ?? | 1506 | __lcs_resume_channel(channel); |
1505 | rc = __lcs_resume_channel(channel); | ||
1506 | } | ||
1507 | spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags); | 1507 | spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags); |
1508 | 1508 | ||
1509 | /* Something happened on the channel. Wake up waiters. */ | 1509 | /* Something happened on the channel. Wake up waiters. */ |
@@ -2392,8 +2392,10 @@ static struct ccw_device_id lcs_ids[] = { | |||
2392 | MODULE_DEVICE_TABLE(ccw, lcs_ids); | 2392 | MODULE_DEVICE_TABLE(ccw, lcs_ids); |
2393 | 2393 | ||
2394 | static struct ccw_driver lcs_ccw_driver = { | 2394 | static struct ccw_driver lcs_ccw_driver = { |
2395 | .owner = THIS_MODULE, | 2395 | .driver = { |
2396 | .name = "lcs", | 2396 | .owner = THIS_MODULE, |
2397 | .name = "lcs", | ||
2398 | }, | ||
2397 | .ids = lcs_ids, | 2399 | .ids = lcs_ids, |
2398 | .probe = ccwgroup_probe_ccwdev, | 2400 | .probe = ccwgroup_probe_ccwdev, |
2399 | .remove = ccwgroup_remove_ccwdev, | 2401 | .remove = ccwgroup_remove_ccwdev, |
@@ -2403,8 +2405,10 @@ static struct ccw_driver lcs_ccw_driver = { | |||
2403 | * LCS ccwgroup driver registration | 2405 | * LCS ccwgroup driver registration |
2404 | */ | 2406 | */ |
2405 | static struct ccwgroup_driver lcs_group_driver = { | 2407 | static struct ccwgroup_driver lcs_group_driver = { |
2406 | .owner = THIS_MODULE, | 2408 | .driver = { |
2407 | .name = "lcs", | 2409 | .owner = THIS_MODULE, |
2410 | .name = "lcs", | ||
2411 | }, | ||
2408 | .max_slaves = 2, | 2412 | .max_slaves = 2, |
2409 | .driver_id = 0xD3C3E2, | 2413 | .driver_id = 0xD3C3E2, |
2410 | .probe = lcs_probe_device, | 2414 | .probe = lcs_probe_device, |
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index 65ebee0a3266..3251333a23df 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c | |||
@@ -565,7 +565,7 @@ static int netiucv_callback_connreq(struct iucv_path *path, | |||
565 | struct iucv_event ev; | 565 | struct iucv_event ev; |
566 | int rc; | 566 | int rc; |
567 | 567 | ||
568 | if (memcmp(iucvMagic, ipuser, sizeof(ipuser))) | 568 | if (memcmp(iucvMagic, ipuser, 16)) |
569 | /* ipuser must match iucvMagic. */ | 569 | /* ipuser must match iucvMagic. */ |
570 | return -EINVAL; | 570 | return -EINVAL; |
571 | rc = -EINVAL; | 571 | rc = -EINVAL; |
@@ -1994,8 +1994,6 @@ static struct net_device *netiucv_init_netdevice(char *username) | |||
1994 | netiucv_setup_netdevice); | 1994 | netiucv_setup_netdevice); |
1995 | if (!dev) | 1995 | if (!dev) |
1996 | return NULL; | 1996 | return NULL; |
1997 | if (dev_alloc_name(dev, dev->name) < 0) | ||
1998 | goto out_netdev; | ||
1999 | 1997 | ||
2000 | privptr = netdev_priv(dev); | 1998 | privptr = netdev_priv(dev); |
2001 | privptr->fsm = init_fsm("netiucvdev", dev_state_names, | 1999 | privptr->fsm = init_fsm("netiucvdev", dev_state_names, |
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index d1257768be90..d3cee33e554c 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h | |||
@@ -225,7 +225,8 @@ static inline int qeth_is_ipa_enabled(struct qeth_ipa_info *ipa, | |||
225 | /*****************************************************************************/ | 225 | /*****************************************************************************/ |
226 | #define QETH_MAX_QUEUES 4 | 226 | #define QETH_MAX_QUEUES 4 |
227 | #define QETH_IN_BUF_SIZE_DEFAULT 65536 | 227 | #define QETH_IN_BUF_SIZE_DEFAULT 65536 |
228 | #define QETH_IN_BUF_COUNT_DEFAULT 16 | 228 | #define QETH_IN_BUF_COUNT_DEFAULT 64 |
229 | #define QETH_IN_BUF_COUNT_HSDEFAULT 128 | ||
229 | #define QETH_IN_BUF_COUNT_MIN 8 | 230 | #define QETH_IN_BUF_COUNT_MIN 8 |
230 | #define QETH_IN_BUF_COUNT_MAX 128 | 231 | #define QETH_IN_BUF_COUNT_MAX 128 |
231 | #define QETH_MAX_BUFFER_ELEMENTS(card) ((card)->qdio.in_buf_size >> 12) | 232 | #define QETH_MAX_BUFFER_ELEMENTS(card) ((card)->qdio.in_buf_size >> 12) |
@@ -360,7 +361,7 @@ enum qeth_header_ids { | |||
360 | 361 | ||
361 | static inline int qeth_is_last_sbale(struct qdio_buffer_element *sbale) | 362 | static inline int qeth_is_last_sbale(struct qdio_buffer_element *sbale) |
362 | { | 363 | { |
363 | return (sbale->flags & SBAL_FLAGS_LAST_ENTRY); | 364 | return (sbale->eflags & SBAL_EFLAGS_LAST_ENTRY); |
364 | } | 365 | } |
365 | 366 | ||
366 | enum qeth_qdio_buffer_states { | 367 | enum qeth_qdio_buffer_states { |
@@ -406,12 +407,6 @@ struct qeth_qdio_q { | |||
406 | int next_buf_to_init; | 407 | int next_buf_to_init; |
407 | } __attribute__ ((aligned(256))); | 408 | } __attribute__ ((aligned(256))); |
408 | 409 | ||
409 | /* possible types of qeth large_send support */ | ||
410 | enum qeth_large_send_types { | ||
411 | QETH_LARGE_SEND_NO, | ||
412 | QETH_LARGE_SEND_TSO, | ||
413 | }; | ||
414 | |||
415 | struct qeth_qdio_out_buffer { | 410 | struct qeth_qdio_out_buffer { |
416 | struct qdio_buffer *buffer; | 411 | struct qdio_buffer *buffer; |
417 | atomic_t state; | 412 | atomic_t state; |
@@ -440,7 +435,6 @@ struct qeth_qdio_out_q { | |||
440 | * index of buffer to be filled by driver; state EMPTY or PACKING | 435 | * index of buffer to be filled by driver; state EMPTY or PACKING |
441 | */ | 436 | */ |
442 | int next_buf_to_fill; | 437 | int next_buf_to_fill; |
443 | int sync_iqdio_error; | ||
444 | /* | 438 | /* |
445 | * number of buffers that are currently filled (PRIMED) | 439 | * number of buffers that are currently filled (PRIMED) |
446 | * -> these buffers are hardware-owned | 440 | * -> these buffers are hardware-owned |
@@ -637,6 +631,8 @@ struct qeth_card_info { | |||
637 | __u32 csum_mask; | 631 | __u32 csum_mask; |
638 | __u32 tx_csum_mask; | 632 | __u32 tx_csum_mask; |
639 | enum qeth_ipa_promisc_modes promisc_mode; | 633 | enum qeth_ipa_promisc_modes promisc_mode; |
634 | __u32 diagass_support; | ||
635 | __u32 hwtrap; | ||
640 | }; | 636 | }; |
641 | 637 | ||
642 | struct qeth_card_options { | 638 | struct qeth_card_options { |
@@ -645,13 +641,11 @@ struct qeth_card_options { | |||
645 | struct qeth_ipa_info adp; /*Adapter parameters*/ | 641 | struct qeth_ipa_info adp; /*Adapter parameters*/ |
646 | struct qeth_routing_info route6; | 642 | struct qeth_routing_info route6; |
647 | struct qeth_ipa_info ipa6; | 643 | struct qeth_ipa_info ipa6; |
648 | enum qeth_checksum_types checksum_type; | ||
649 | int broadcast_mode; | 644 | int broadcast_mode; |
650 | int macaddr_mode; | 645 | int macaddr_mode; |
651 | int fake_broadcast; | 646 | int fake_broadcast; |
652 | int add_hhlen; | 647 | int add_hhlen; |
653 | int layer2; | 648 | int layer2; |
654 | enum qeth_large_send_types large_send; | ||
655 | int performance_stats; | 649 | int performance_stats; |
656 | int rx_sg_cb; | 650 | int rx_sg_cb; |
657 | enum qeth_ipa_isolation_modes isolation; | 651 | enum qeth_ipa_isolation_modes isolation; |
@@ -676,6 +670,7 @@ enum qeth_discipline_id { | |||
676 | }; | 670 | }; |
677 | 671 | ||
678 | struct qeth_discipline { | 672 | struct qeth_discipline { |
673 | void (*start_poll)(struct ccw_device *, int, unsigned long); | ||
679 | qdio_handler_t *input_handler; | 674 | qdio_handler_t *input_handler; |
680 | qdio_handler_t *output_handler; | 675 | qdio_handler_t *output_handler; |
681 | int (*recover)(void *ptr); | 676 | int (*recover)(void *ptr); |
@@ -694,13 +689,15 @@ struct qeth_mc_mac { | |||
694 | int is_vmac; | 689 | int is_vmac; |
695 | }; | 690 | }; |
696 | 691 | ||
697 | struct qeth_skb_data { | 692 | struct qeth_rx { |
698 | __u32 magic; | 693 | int b_count; |
699 | int count; | 694 | int b_index; |
695 | struct qdio_buffer_element *b_element; | ||
696 | int e_offset; | ||
697 | int qdio_err; | ||
700 | }; | 698 | }; |
701 | 699 | ||
702 | #define QETH_SKB_MAGIC 0x71657468 | 700 | #define QETH_NAPI_WEIGHT 128 |
703 | #define QETH_SIGA_CC2_RETRIES 3 | ||
704 | 701 | ||
705 | struct qeth_card { | 702 | struct qeth_card { |
706 | struct list_head list; | 703 | struct list_head list; |
@@ -739,7 +736,6 @@ struct qeth_card { | |||
739 | /* QDIO buffer handling */ | 736 | /* QDIO buffer handling */ |
740 | struct qeth_qdio_info qdio; | 737 | struct qeth_qdio_info qdio; |
741 | struct qeth_perf_stats perf_stats; | 738 | struct qeth_perf_stats perf_stats; |
742 | int use_hard_stop; | ||
743 | int read_or_write_problem; | 739 | int read_or_write_problem; |
744 | struct qeth_osn_info osn_info; | 740 | struct qeth_osn_info osn_info; |
745 | struct qeth_discipline discipline; | 741 | struct qeth_discipline discipline; |
@@ -749,6 +745,8 @@ struct qeth_card { | |||
749 | debug_info_t *debug; | 745 | debug_info_t *debug; |
750 | struct mutex conf_mutex; | 746 | struct mutex conf_mutex; |
751 | struct mutex discipline_mutex; | 747 | struct mutex discipline_mutex; |
748 | struct napi_struct napi; | ||
749 | struct qeth_rx rx; | ||
752 | }; | 750 | }; |
753 | 751 | ||
754 | struct qeth_card_list_struct { | 752 | struct qeth_card_list_struct { |
@@ -756,6 +754,14 @@ struct qeth_card_list_struct { | |||
756 | rwlock_t rwlock; | 754 | rwlock_t rwlock; |
757 | }; | 755 | }; |
758 | 756 | ||
757 | struct qeth_trap_id { | ||
758 | __u16 lparnr; | ||
759 | char vmname[8]; | ||
760 | __u8 chpid; | ||
761 | __u8 ssid; | ||
762 | __u16 devno; | ||
763 | } __packed; | ||
764 | |||
759 | /*some helper functions*/ | 765 | /*some helper functions*/ |
760 | #define QETH_CARD_IFNAME(card) (((card)->dev)? (card)->dev->name : "") | 766 | #define QETH_CARD_IFNAME(card) (((card)->dev)? (card)->dev->name : "") |
761 | 767 | ||
@@ -790,6 +796,12 @@ static inline void qeth_put_buffer_pool_entry(struct qeth_card *card, | |||
790 | list_add_tail(&entry->list, &card->qdio.in_buf_pool.entry_list); | 796 | list_add_tail(&entry->list, &card->qdio.in_buf_pool.entry_list); |
791 | } | 797 | } |
792 | 798 | ||
799 | static inline int qeth_is_diagass_supported(struct qeth_card *card, | ||
800 | enum qeth_diags_cmds cmd) | ||
801 | { | ||
802 | return card->info.diagass_support & (__u32)cmd; | ||
803 | } | ||
804 | |||
793 | extern struct ccwgroup_driver qeth_l2_ccwgroup_driver; | 805 | extern struct ccwgroup_driver qeth_l2_ccwgroup_driver; |
794 | extern struct ccwgroup_driver qeth_l3_ccwgroup_driver; | 806 | extern struct ccwgroup_driver qeth_l3_ccwgroup_driver; |
795 | const char *qeth_get_cardname_short(struct qeth_card *); | 807 | const char *qeth_get_cardname_short(struct qeth_card *); |
@@ -831,6 +843,10 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *, | |||
831 | struct qdio_buffer *, struct qdio_buffer_element **, int *, | 843 | struct qdio_buffer *, struct qdio_buffer_element **, int *, |
832 | struct qeth_hdr **); | 844 | struct qeth_hdr **); |
833 | void qeth_schedule_recovery(struct qeth_card *); | 845 | void qeth_schedule_recovery(struct qeth_card *); |
846 | void qeth_qdio_start_poll(struct ccw_device *, int, unsigned long); | ||
847 | void qeth_qdio_input_handler(struct ccw_device *, | ||
848 | unsigned int, unsigned int, int, | ||
849 | int, unsigned long); | ||
834 | void qeth_qdio_output_handler(struct ccw_device *, unsigned int, | 850 | void qeth_qdio_output_handler(struct ccw_device *, unsigned int, |
835 | int, int, int, unsigned long); | 851 | int, int, int, unsigned long); |
836 | void qeth_clear_ipacmd_list(struct qeth_card *); | 852 | void qeth_clear_ipacmd_list(struct qeth_card *); |
@@ -871,6 +887,8 @@ void qeth_dbf_longtext(debug_info_t *id, int level, char *text, ...); | |||
871 | int qeth_core_ethtool_get_settings(struct net_device *, struct ethtool_cmd *); | 887 | int qeth_core_ethtool_get_settings(struct net_device *, struct ethtool_cmd *); |
872 | int qeth_set_access_ctrl_online(struct qeth_card *card); | 888 | int qeth_set_access_ctrl_online(struct qeth_card *card); |
873 | int qeth_hdr_chk_and_bounce(struct sk_buff *, int); | 889 | int qeth_hdr_chk_and_bounce(struct sk_buff *, int); |
890 | int qeth_hw_trap(struct qeth_card *, enum qeth_diags_trap_action); | ||
891 | int qeth_query_ipassists(struct qeth_card *, enum qeth_prot_versions prot); | ||
874 | 892 | ||
875 | /* exports for OSN */ | 893 | /* exports for OSN */ |
876 | int qeth_osn_assist(struct net_device *, void *, int); | 894 | int qeth_osn_assist(struct net_device *, void *, int); |
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 3a5a18a0fc28..dd08f7b42fb8 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c | |||
@@ -24,6 +24,7 @@ | |||
24 | 24 | ||
25 | #include <asm/ebcdic.h> | 25 | #include <asm/ebcdic.h> |
26 | #include <asm/io.h> | 26 | #include <asm/io.h> |
27 | #include <asm/sysinfo.h> | ||
27 | 28 | ||
28 | #include "qeth_core.h" | 29 | #include "qeth_core.h" |
29 | 30 | ||
@@ -302,12 +303,15 @@ static void qeth_issue_ipa_msg(struct qeth_ipa_cmd *cmd, int rc, | |||
302 | int com = cmd->hdr.command; | 303 | int com = cmd->hdr.command; |
303 | ipa_name = qeth_get_ipa_cmd_name(com); | 304 | ipa_name = qeth_get_ipa_cmd_name(com); |
304 | if (rc) | 305 | if (rc) |
305 | QETH_DBF_MESSAGE(2, "IPA: %s(x%X) for %s returned x%X \"%s\"\n", | 306 | QETH_DBF_MESSAGE(2, "IPA: %s(x%X) for %s/%s returned " |
306 | ipa_name, com, QETH_CARD_IFNAME(card), | 307 | "x%X \"%s\"\n", |
307 | rc, qeth_get_ipa_msg(rc)); | 308 | ipa_name, com, dev_name(&card->gdev->dev), |
309 | QETH_CARD_IFNAME(card), rc, | ||
310 | qeth_get_ipa_msg(rc)); | ||
308 | else | 311 | else |
309 | QETH_DBF_MESSAGE(5, "IPA: %s(x%X) for %s succeeded\n", | 312 | QETH_DBF_MESSAGE(5, "IPA: %s(x%X) for %s/%s succeeded\n", |
310 | ipa_name, com, QETH_CARD_IFNAME(card)); | 313 | ipa_name, com, dev_name(&card->gdev->dev), |
314 | QETH_CARD_IFNAME(card)); | ||
311 | } | 315 | } |
312 | 316 | ||
313 | static struct qeth_ipa_cmd *qeth_check_ipa_data(struct qeth_card *card, | 317 | static struct qeth_ipa_cmd *qeth_check_ipa_data(struct qeth_card *card, |
@@ -346,6 +350,8 @@ static struct qeth_ipa_cmd *qeth_check_ipa_data(struct qeth_card *card, | |||
346 | card->info.chpid); | 350 | card->info.chpid); |
347 | netif_carrier_on(card->dev); | 351 | netif_carrier_on(card->dev); |
348 | card->lan_online = 1; | 352 | card->lan_online = 1; |
353 | if (card->info.hwtrap) | ||
354 | card->info.hwtrap = 2; | ||
349 | qeth_schedule_recovery(card); | 355 | qeth_schedule_recovery(card); |
350 | return NULL; | 356 | return NULL; |
351 | case IPA_CMD_MODCCID: | 357 | case IPA_CMD_MODCCID: |
@@ -877,23 +883,21 @@ out: | |||
877 | return; | 883 | return; |
878 | } | 884 | } |
879 | 885 | ||
880 | static void __qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, | 886 | static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, |
881 | struct qeth_qdio_out_buffer *buf, unsigned int qeth_skip_skb) | 887 | struct qeth_qdio_out_buffer *buf) |
882 | { | 888 | { |
883 | int i; | 889 | int i; |
884 | struct sk_buff *skb; | 890 | struct sk_buff *skb; |
885 | 891 | ||
886 | /* is PCI flag set on buffer? */ | 892 | /* is PCI flag set on buffer? */ |
887 | if (buf->buffer->element[0].flags & 0x40) | 893 | if (buf->buffer->element[0].sflags & SBAL_SFLAGS0_PCI_REQ) |
888 | atomic_dec(&queue->set_pci_flags_count); | 894 | atomic_dec(&queue->set_pci_flags_count); |
889 | 895 | ||
890 | if (!qeth_skip_skb) { | 896 | skb = skb_dequeue(&buf->skb_list); |
897 | while (skb) { | ||
898 | atomic_dec(&skb->users); | ||
899 | dev_kfree_skb_any(skb); | ||
891 | skb = skb_dequeue(&buf->skb_list); | 900 | skb = skb_dequeue(&buf->skb_list); |
892 | while (skb) { | ||
893 | atomic_dec(&skb->users); | ||
894 | dev_kfree_skb_any(skb); | ||
895 | skb = skb_dequeue(&buf->skb_list); | ||
896 | } | ||
897 | } | 901 | } |
898 | for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(queue->card); ++i) { | 902 | for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(queue->card); ++i) { |
899 | if (buf->buffer->element[i].addr && buf->is_header[i]) | 903 | if (buf->buffer->element[i].addr && buf->is_header[i]) |
@@ -902,19 +906,15 @@ static void __qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, | |||
902 | buf->is_header[i] = 0; | 906 | buf->is_header[i] = 0; |
903 | buf->buffer->element[i].length = 0; | 907 | buf->buffer->element[i].length = 0; |
904 | buf->buffer->element[i].addr = NULL; | 908 | buf->buffer->element[i].addr = NULL; |
905 | buf->buffer->element[i].flags = 0; | 909 | buf->buffer->element[i].eflags = 0; |
910 | buf->buffer->element[i].sflags = 0; | ||
906 | } | 911 | } |
907 | buf->buffer->element[15].flags = 0; | 912 | buf->buffer->element[15].eflags = 0; |
913 | buf->buffer->element[15].sflags = 0; | ||
908 | buf->next_element_to_fill = 0; | 914 | buf->next_element_to_fill = 0; |
909 | atomic_set(&buf->state, QETH_QDIO_BUF_EMPTY); | 915 | atomic_set(&buf->state, QETH_QDIO_BUF_EMPTY); |
910 | } | 916 | } |
911 | 917 | ||
912 | static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, | ||
913 | struct qeth_qdio_out_buffer *buf) | ||
914 | { | ||
915 | __qeth_clear_output_buffer(queue, buf, 0); | ||
916 | } | ||
917 | |||
918 | void qeth_clear_qdio_buffers(struct qeth_card *card) | 918 | void qeth_clear_qdio_buffers(struct qeth_card *card) |
919 | { | 919 | { |
920 | int i, j; | 920 | int i, j; |
@@ -996,16 +996,30 @@ static void qeth_get_channel_path_desc(struct qeth_card *card) | |||
996 | chp_dsc = (struct channelPath_dsc *)ccw_device_get_chp_desc(ccwdev, 0); | 996 | chp_dsc = (struct channelPath_dsc *)ccw_device_get_chp_desc(ccwdev, 0); |
997 | if (chp_dsc != NULL) { | 997 | if (chp_dsc != NULL) { |
998 | /* CHPP field bit 6 == 1 -> single queue */ | 998 | /* CHPP field bit 6 == 1 -> single queue */ |
999 | if ((chp_dsc->chpp & 0x02) == 0x02) | 999 | if ((chp_dsc->chpp & 0x02) == 0x02) { |
1000 | if ((atomic_read(&card->qdio.state) != | ||
1001 | QETH_QDIO_UNINITIALIZED) && | ||
1002 | (card->qdio.no_out_queues == 4)) | ||
1003 | /* change from 4 to 1 outbound queues */ | ||
1004 | qeth_free_qdio_buffers(card); | ||
1000 | card->qdio.no_out_queues = 1; | 1005 | card->qdio.no_out_queues = 1; |
1006 | if (card->qdio.default_out_queue != 0) | ||
1007 | dev_info(&card->gdev->dev, | ||
1008 | "Priority Queueing not supported\n"); | ||
1009 | card->qdio.default_out_queue = 0; | ||
1010 | } else { | ||
1011 | if ((atomic_read(&card->qdio.state) != | ||
1012 | QETH_QDIO_UNINITIALIZED) && | ||
1013 | (card->qdio.no_out_queues == 1)) { | ||
1014 | /* change from 1 to 4 outbound queues */ | ||
1015 | qeth_free_qdio_buffers(card); | ||
1016 | card->qdio.default_out_queue = 2; | ||
1017 | } | ||
1018 | card->qdio.no_out_queues = 4; | ||
1019 | } | ||
1001 | card->info.func_level = 0x4100 + chp_dsc->desc; | 1020 | card->info.func_level = 0x4100 + chp_dsc->desc; |
1002 | kfree(chp_dsc); | 1021 | kfree(chp_dsc); |
1003 | } | 1022 | } |
1004 | if (card->qdio.no_out_queues == 1) { | ||
1005 | card->qdio.default_out_queue = 0; | ||
1006 | dev_info(&card->gdev->dev, | ||
1007 | "Priority Queueing not supported\n"); | ||
1008 | } | ||
1009 | QETH_DBF_TEXT_(SETUP, 2, "nr:%x", card->qdio.no_out_queues); | 1023 | QETH_DBF_TEXT_(SETUP, 2, "nr:%x", card->qdio.no_out_queues); |
1010 | QETH_DBF_TEXT_(SETUP, 2, "lvl:%02x", card->info.func_level); | 1024 | QETH_DBF_TEXT_(SETUP, 2, "lvl:%02x", card->info.func_level); |
1011 | return; | 1025 | return; |
@@ -1017,7 +1031,10 @@ static void qeth_init_qdio_info(struct qeth_card *card) | |||
1017 | atomic_set(&card->qdio.state, QETH_QDIO_UNINITIALIZED); | 1031 | atomic_set(&card->qdio.state, QETH_QDIO_UNINITIALIZED); |
1018 | /* inbound */ | 1032 | /* inbound */ |
1019 | card->qdio.in_buf_size = QETH_IN_BUF_SIZE_DEFAULT; | 1033 | card->qdio.in_buf_size = QETH_IN_BUF_SIZE_DEFAULT; |
1020 | card->qdio.init_pool.buf_count = QETH_IN_BUF_COUNT_DEFAULT; | 1034 | if (card->info.type == QETH_CARD_TYPE_IQD) |
1035 | card->qdio.init_pool.buf_count = QETH_IN_BUF_COUNT_HSDEFAULT; | ||
1036 | else | ||
1037 | card->qdio.init_pool.buf_count = QETH_IN_BUF_COUNT_DEFAULT; | ||
1021 | card->qdio.in_buf_pool.buf_count = card->qdio.init_pool.buf_count; | 1038 | card->qdio.in_buf_pool.buf_count = card->qdio.init_pool.buf_count; |
1022 | INIT_LIST_HEAD(&card->qdio.in_buf_pool.entry_list); | 1039 | INIT_LIST_HEAD(&card->qdio.in_buf_pool.entry_list); |
1023 | INIT_LIST_HEAD(&card->qdio.init_pool.entry_list); | 1040 | INIT_LIST_HEAD(&card->qdio.init_pool.entry_list); |
@@ -1027,7 +1044,6 @@ static void qeth_set_intial_options(struct qeth_card *card) | |||
1027 | { | 1044 | { |
1028 | card->options.route4.type = NO_ROUTER; | 1045 | card->options.route4.type = NO_ROUTER; |
1029 | card->options.route6.type = NO_ROUTER; | 1046 | card->options.route6.type = NO_ROUTER; |
1030 | card->options.checksum_type = QETH_CHECKSUM_DEFAULT; | ||
1031 | card->options.broadcast_mode = QETH_TR_BROADCAST_ALLRINGS; | 1047 | card->options.broadcast_mode = QETH_TR_BROADCAST_ALLRINGS; |
1032 | card->options.macaddr_mode = QETH_TR_MACADDR_NONCANONICAL; | 1048 | card->options.macaddr_mode = QETH_TR_MACADDR_NONCANONICAL; |
1033 | card->options.fake_broadcast = 0; | 1049 | card->options.fake_broadcast = 0; |
@@ -1077,7 +1093,6 @@ static int qeth_setup_card(struct qeth_card *card) | |||
1077 | card->data.state = CH_STATE_DOWN; | 1093 | card->data.state = CH_STATE_DOWN; |
1078 | card->state = CARD_STATE_DOWN; | 1094 | card->state = CARD_STATE_DOWN; |
1079 | card->lan_online = 0; | 1095 | card->lan_online = 0; |
1080 | card->use_hard_stop = 0; | ||
1081 | card->read_or_write_problem = 0; | 1096 | card->read_or_write_problem = 0; |
1082 | card->dev = NULL; | 1097 | card->dev = NULL; |
1083 | spin_lock_init(&card->vlanlock); | 1098 | spin_lock_init(&card->vlanlock); |
@@ -1096,7 +1111,7 @@ static int qeth_setup_card(struct qeth_card *card) | |||
1096 | INIT_LIST_HEAD(card->ip_tbd_list); | 1111 | INIT_LIST_HEAD(card->ip_tbd_list); |
1097 | INIT_LIST_HEAD(&card->cmd_waiter_list); | 1112 | INIT_LIST_HEAD(&card->cmd_waiter_list); |
1098 | init_waitqueue_head(&card->wait_q); | 1113 | init_waitqueue_head(&card->wait_q); |
1099 | /* intial options */ | 1114 | /* initial options */ |
1100 | qeth_set_intial_options(card); | 1115 | qeth_set_intial_options(card); |
1101 | /* IP address takeover */ | 1116 | /* IP address takeover */ |
1102 | INIT_LIST_HEAD(&card->ipato.entries); | 1117 | INIT_LIST_HEAD(&card->ipato.entries); |
@@ -1726,20 +1741,22 @@ int qeth_send_control_data(struct qeth_card *card, int len, | |||
1726 | }; | 1741 | }; |
1727 | } | 1742 | } |
1728 | 1743 | ||
1744 | if (reply->rc == -EIO) | ||
1745 | goto error; | ||
1729 | rc = reply->rc; | 1746 | rc = reply->rc; |
1730 | qeth_put_reply(reply); | 1747 | qeth_put_reply(reply); |
1731 | return rc; | 1748 | return rc; |
1732 | 1749 | ||
1733 | time_err: | 1750 | time_err: |
1751 | reply->rc = -ETIME; | ||
1734 | spin_lock_irqsave(&reply->card->lock, flags); | 1752 | spin_lock_irqsave(&reply->card->lock, flags); |
1735 | list_del_init(&reply->list); | 1753 | list_del_init(&reply->list); |
1736 | spin_unlock_irqrestore(&reply->card->lock, flags); | 1754 | spin_unlock_irqrestore(&reply->card->lock, flags); |
1737 | reply->rc = -ETIME; | ||
1738 | atomic_inc(&reply->received); | 1755 | atomic_inc(&reply->received); |
1756 | error: | ||
1739 | atomic_set(&card->write.irq_pending, 0); | 1757 | atomic_set(&card->write.irq_pending, 0); |
1740 | qeth_release_buffer(iob->channel, iob); | 1758 | qeth_release_buffer(iob->channel, iob); |
1741 | card->write.buf_no = (card->write.buf_no + 1) % QETH_CMD_BUFFER_NO; | 1759 | card->write.buf_no = (card->write.buf_no + 1) % QETH_CMD_BUFFER_NO; |
1742 | wake_up(&reply->wait_q); | ||
1743 | rc = reply->rc; | 1760 | rc = reply->rc; |
1744 | qeth_put_reply(reply); | 1761 | qeth_put_reply(reply); |
1745 | return rc; | 1762 | return rc; |
@@ -1840,33 +1857,6 @@ static inline int qeth_get_initial_mtu_for_card(struct qeth_card *card) | |||
1840 | } | 1857 | } |
1841 | } | 1858 | } |
1842 | 1859 | ||
1843 | static inline int qeth_get_max_mtu_for_card(int cardtype) | ||
1844 | { | ||
1845 | switch (cardtype) { | ||
1846 | |||
1847 | case QETH_CARD_TYPE_UNKNOWN: | ||
1848 | case QETH_CARD_TYPE_OSD: | ||
1849 | case QETH_CARD_TYPE_OSN: | ||
1850 | case QETH_CARD_TYPE_OSM: | ||
1851 | case QETH_CARD_TYPE_OSX: | ||
1852 | return 61440; | ||
1853 | case QETH_CARD_TYPE_IQD: | ||
1854 | return 57344; | ||
1855 | default: | ||
1856 | return 1500; | ||
1857 | } | ||
1858 | } | ||
1859 | |||
1860 | static inline int qeth_get_mtu_out_of_mpc(int cardtype) | ||
1861 | { | ||
1862 | switch (cardtype) { | ||
1863 | case QETH_CARD_TYPE_IQD: | ||
1864 | return 1; | ||
1865 | default: | ||
1866 | return 0; | ||
1867 | } | ||
1868 | } | ||
1869 | |||
1870 | static inline int qeth_get_mtu_outof_framesize(int framesize) | 1860 | static inline int qeth_get_mtu_outof_framesize(int framesize) |
1871 | { | 1861 | { |
1872 | switch (framesize) { | 1862 | switch (framesize) { |
@@ -1889,10 +1879,9 @@ static inline int qeth_mtu_is_valid(struct qeth_card *card, int mtu) | |||
1889 | case QETH_CARD_TYPE_OSD: | 1879 | case QETH_CARD_TYPE_OSD: |
1890 | case QETH_CARD_TYPE_OSM: | 1880 | case QETH_CARD_TYPE_OSM: |
1891 | case QETH_CARD_TYPE_OSX: | 1881 | case QETH_CARD_TYPE_OSX: |
1892 | return ((mtu >= 576) && (mtu <= 61440)); | ||
1893 | case QETH_CARD_TYPE_IQD: | 1882 | case QETH_CARD_TYPE_IQD: |
1894 | return ((mtu >= 576) && | 1883 | return ((mtu >= 576) && |
1895 | (mtu <= card->info.max_mtu + 4096 - 32)); | 1884 | (mtu <= card->info.max_mtu)); |
1896 | case QETH_CARD_TYPE_OSN: | 1885 | case QETH_CARD_TYPE_OSN: |
1897 | case QETH_CARD_TYPE_UNKNOWN: | 1886 | case QETH_CARD_TYPE_UNKNOWN: |
1898 | default: | 1887 | default: |
@@ -1915,7 +1904,7 @@ static int qeth_ulp_enable_cb(struct qeth_card *card, struct qeth_reply *reply, | |||
1915 | memcpy(&card->token.ulp_filter_r, | 1904 | memcpy(&card->token.ulp_filter_r, |
1916 | QETH_ULP_ENABLE_RESP_FILTER_TOKEN(iob->data), | 1905 | QETH_ULP_ENABLE_RESP_FILTER_TOKEN(iob->data), |
1917 | QETH_MPC_TOKEN_LENGTH); | 1906 | QETH_MPC_TOKEN_LENGTH); |
1918 | if (qeth_get_mtu_out_of_mpc(card->info.type)) { | 1907 | if (card->info.type == QETH_CARD_TYPE_IQD) { |
1919 | memcpy(&framesize, QETH_ULP_ENABLE_RESP_MAX_MTU(iob->data), 2); | 1908 | memcpy(&framesize, QETH_ULP_ENABLE_RESP_MAX_MTU(iob->data), 2); |
1920 | mtu = qeth_get_mtu_outof_framesize(framesize); | 1909 | mtu = qeth_get_mtu_outof_framesize(framesize); |
1921 | if (!mtu) { | 1910 | if (!mtu) { |
@@ -1923,12 +1912,21 @@ static int qeth_ulp_enable_cb(struct qeth_card *card, struct qeth_reply *reply, | |||
1923 | QETH_DBF_TEXT_(SETUP, 2, " rc%d", iob->rc); | 1912 | QETH_DBF_TEXT_(SETUP, 2, " rc%d", iob->rc); |
1924 | return 0; | 1913 | return 0; |
1925 | } | 1914 | } |
1926 | card->info.max_mtu = mtu; | 1915 | if (card->info.initial_mtu && (card->info.initial_mtu != mtu)) { |
1916 | /* frame size has changed */ | ||
1917 | if (card->dev && | ||
1918 | ((card->dev->mtu == card->info.initial_mtu) || | ||
1919 | (card->dev->mtu > mtu))) | ||
1920 | card->dev->mtu = mtu; | ||
1921 | qeth_free_qdio_buffers(card); | ||
1922 | } | ||
1927 | card->info.initial_mtu = mtu; | 1923 | card->info.initial_mtu = mtu; |
1924 | card->info.max_mtu = mtu; | ||
1928 | card->qdio.in_buf_size = mtu + 2 * PAGE_SIZE; | 1925 | card->qdio.in_buf_size = mtu + 2 * PAGE_SIZE; |
1929 | } else { | 1926 | } else { |
1930 | card->info.initial_mtu = qeth_get_initial_mtu_for_card(card); | 1927 | card->info.initial_mtu = qeth_get_initial_mtu_for_card(card); |
1931 | card->info.max_mtu = qeth_get_max_mtu_for_card(card->info.type); | 1928 | card->info.max_mtu = *(__u16 *)QETH_ULP_ENABLE_RESP_MAX_MTU( |
1929 | iob->data); | ||
1932 | card->qdio.in_buf_size = QETH_IN_BUF_SIZE_DEFAULT; | 1930 | card->qdio.in_buf_size = QETH_IN_BUF_SIZE_DEFAULT; |
1933 | } | 1931 | } |
1934 | 1932 | ||
@@ -2372,9 +2370,10 @@ static int qeth_init_input_buffer(struct qeth_card *card, | |||
2372 | buf->buffer->element[i].length = PAGE_SIZE; | 2370 | buf->buffer->element[i].length = PAGE_SIZE; |
2373 | buf->buffer->element[i].addr = pool_entry->elements[i]; | 2371 | buf->buffer->element[i].addr = pool_entry->elements[i]; |
2374 | if (i == QETH_MAX_BUFFER_ELEMENTS(card) - 1) | 2372 | if (i == QETH_MAX_BUFFER_ELEMENTS(card) - 1) |
2375 | buf->buffer->element[i].flags = SBAL_FLAGS_LAST_ENTRY; | 2373 | buf->buffer->element[i].eflags = SBAL_EFLAGS_LAST_ENTRY; |
2376 | else | 2374 | else |
2377 | buf->buffer->element[i].flags = 0; | 2375 | buf->buffer->element[i].eflags = 0; |
2376 | buf->buffer->element[i].sflags = 0; | ||
2378 | } | 2377 | } |
2379 | return 0; | 2378 | return 0; |
2380 | } | 2379 | } |
@@ -2503,45 +2502,19 @@ int qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob, | |||
2503 | } | 2502 | } |
2504 | EXPORT_SYMBOL_GPL(qeth_send_ipa_cmd); | 2503 | EXPORT_SYMBOL_GPL(qeth_send_ipa_cmd); |
2505 | 2504 | ||
2506 | static int qeth_send_startstoplan(struct qeth_card *card, | ||
2507 | enum qeth_ipa_cmds ipacmd, enum qeth_prot_versions prot) | ||
2508 | { | ||
2509 | int rc; | ||
2510 | struct qeth_cmd_buffer *iob; | ||
2511 | |||
2512 | iob = qeth_get_ipacmd_buffer(card, ipacmd, prot); | ||
2513 | rc = qeth_send_ipa_cmd(card, iob, NULL, NULL); | ||
2514 | |||
2515 | return rc; | ||
2516 | } | ||
2517 | |||
2518 | int qeth_send_startlan(struct qeth_card *card) | 2505 | int qeth_send_startlan(struct qeth_card *card) |
2519 | { | 2506 | { |
2520 | int rc; | 2507 | int rc; |
2508 | struct qeth_cmd_buffer *iob; | ||
2521 | 2509 | ||
2522 | QETH_DBF_TEXT(SETUP, 2, "strtlan"); | 2510 | QETH_DBF_TEXT(SETUP, 2, "strtlan"); |
2523 | 2511 | ||
2524 | rc = qeth_send_startstoplan(card, IPA_CMD_STARTLAN, 0); | 2512 | iob = qeth_get_ipacmd_buffer(card, IPA_CMD_STARTLAN, 0); |
2513 | rc = qeth_send_ipa_cmd(card, iob, NULL, NULL); | ||
2525 | return rc; | 2514 | return rc; |
2526 | } | 2515 | } |
2527 | EXPORT_SYMBOL_GPL(qeth_send_startlan); | 2516 | EXPORT_SYMBOL_GPL(qeth_send_startlan); |
2528 | 2517 | ||
2529 | int qeth_send_stoplan(struct qeth_card *card) | ||
2530 | { | ||
2531 | int rc = 0; | ||
2532 | |||
2533 | /* | ||
2534 | * TODO: according to the IPA format document page 14, | ||
2535 | * TCP/IP (we!) never issue a STOPLAN | ||
2536 | * is this right ?!? | ||
2537 | */ | ||
2538 | QETH_DBF_TEXT(SETUP, 2, "stoplan"); | ||
2539 | |||
2540 | rc = qeth_send_startstoplan(card, IPA_CMD_STOPLAN, 0); | ||
2541 | return rc; | ||
2542 | } | ||
2543 | EXPORT_SYMBOL_GPL(qeth_send_stoplan); | ||
2544 | |||
2545 | int qeth_default_setadapterparms_cb(struct qeth_card *card, | 2518 | int qeth_default_setadapterparms_cb(struct qeth_card *card, |
2546 | struct qeth_reply *reply, unsigned long data) | 2519 | struct qeth_reply *reply, unsigned long data) |
2547 | { | 2520 | { |
@@ -2606,17 +2579,153 @@ int qeth_query_setadapterparms(struct qeth_card *card) | |||
2606 | } | 2579 | } |
2607 | EXPORT_SYMBOL_GPL(qeth_query_setadapterparms); | 2580 | EXPORT_SYMBOL_GPL(qeth_query_setadapterparms); |
2608 | 2581 | ||
2582 | static int qeth_query_ipassists_cb(struct qeth_card *card, | ||
2583 | struct qeth_reply *reply, unsigned long data) | ||
2584 | { | ||
2585 | struct qeth_ipa_cmd *cmd; | ||
2586 | |||
2587 | QETH_DBF_TEXT(SETUP, 2, "qipasscb"); | ||
2588 | |||
2589 | cmd = (struct qeth_ipa_cmd *) data; | ||
2590 | if (cmd->hdr.prot_version == QETH_PROT_IPV4) { | ||
2591 | card->options.ipa4.supported_funcs = cmd->hdr.ipa_supported; | ||
2592 | card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled; | ||
2593 | } else { | ||
2594 | card->options.ipa6.supported_funcs = cmd->hdr.ipa_supported; | ||
2595 | card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled; | ||
2596 | } | ||
2597 | QETH_DBF_TEXT(SETUP, 2, "suppenbl"); | ||
2598 | QETH_DBF_TEXT_(SETUP, 2, "%x", cmd->hdr.ipa_supported); | ||
2599 | QETH_DBF_TEXT_(SETUP, 2, "%x", cmd->hdr.ipa_enabled); | ||
2600 | return 0; | ||
2601 | } | ||
2602 | |||
2603 | int qeth_query_ipassists(struct qeth_card *card, enum qeth_prot_versions prot) | ||
2604 | { | ||
2605 | int rc; | ||
2606 | struct qeth_cmd_buffer *iob; | ||
2607 | |||
2608 | QETH_DBF_TEXT_(SETUP, 2, "qipassi%i", prot); | ||
2609 | iob = qeth_get_ipacmd_buffer(card, IPA_CMD_QIPASSIST, prot); | ||
2610 | rc = qeth_send_ipa_cmd(card, iob, qeth_query_ipassists_cb, NULL); | ||
2611 | return rc; | ||
2612 | } | ||
2613 | EXPORT_SYMBOL_GPL(qeth_query_ipassists); | ||
2614 | |||
2615 | static int qeth_query_setdiagass_cb(struct qeth_card *card, | ||
2616 | struct qeth_reply *reply, unsigned long data) | ||
2617 | { | ||
2618 | struct qeth_ipa_cmd *cmd; | ||
2619 | __u16 rc; | ||
2620 | |||
2621 | cmd = (struct qeth_ipa_cmd *)data; | ||
2622 | rc = cmd->hdr.return_code; | ||
2623 | if (rc) | ||
2624 | QETH_CARD_TEXT_(card, 2, "diagq:%x", rc); | ||
2625 | else | ||
2626 | card->info.diagass_support = cmd->data.diagass.ext; | ||
2627 | return 0; | ||
2628 | } | ||
2629 | |||
2630 | static int qeth_query_setdiagass(struct qeth_card *card) | ||
2631 | { | ||
2632 | struct qeth_cmd_buffer *iob; | ||
2633 | struct qeth_ipa_cmd *cmd; | ||
2634 | |||
2635 | QETH_DBF_TEXT(SETUP, 2, "qdiagass"); | ||
2636 | iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SET_DIAG_ASS, 0); | ||
2637 | cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); | ||
2638 | cmd->data.diagass.subcmd_len = 16; | ||
2639 | cmd->data.diagass.subcmd = QETH_DIAGS_CMD_QUERY; | ||
2640 | return qeth_send_ipa_cmd(card, iob, qeth_query_setdiagass_cb, NULL); | ||
2641 | } | ||
2642 | |||
2643 | static void qeth_get_trap_id(struct qeth_card *card, struct qeth_trap_id *tid) | ||
2644 | { | ||
2645 | unsigned long info = get_zeroed_page(GFP_KERNEL); | ||
2646 | struct sysinfo_2_2_2 *info222 = (struct sysinfo_2_2_2 *)info; | ||
2647 | struct sysinfo_3_2_2 *info322 = (struct sysinfo_3_2_2 *)info; | ||
2648 | struct ccw_dev_id ccwid; | ||
2649 | int level, rc; | ||
2650 | |||
2651 | tid->chpid = card->info.chpid; | ||
2652 | ccw_device_get_id(CARD_RDEV(card), &ccwid); | ||
2653 | tid->ssid = ccwid.ssid; | ||
2654 | tid->devno = ccwid.devno; | ||
2655 | if (!info) | ||
2656 | return; | ||
2657 | |||
2658 | rc = stsi(NULL, 0, 0, 0); | ||
2659 | if (rc == -ENOSYS) | ||
2660 | level = rc; | ||
2661 | else | ||
2662 | level = (((unsigned int) rc) >> 28); | ||
2663 | |||
2664 | if ((level >= 2) && (stsi(info222, 2, 2, 2) != -ENOSYS)) | ||
2665 | tid->lparnr = info222->lpar_number; | ||
2666 | |||
2667 | if ((level >= 3) && (stsi(info322, 3, 2, 2) != -ENOSYS)) { | ||
2668 | EBCASC(info322->vm[0].name, sizeof(info322->vm[0].name)); | ||
2669 | memcpy(tid->vmname, info322->vm[0].name, sizeof(tid->vmname)); | ||
2670 | } | ||
2671 | free_page(info); | ||
2672 | return; | ||
2673 | } | ||
2674 | |||
2675 | static int qeth_hw_trap_cb(struct qeth_card *card, | ||
2676 | struct qeth_reply *reply, unsigned long data) | ||
2677 | { | ||
2678 | struct qeth_ipa_cmd *cmd; | ||
2679 | __u16 rc; | ||
2680 | |||
2681 | cmd = (struct qeth_ipa_cmd *)data; | ||
2682 | rc = cmd->hdr.return_code; | ||
2683 | if (rc) | ||
2684 | QETH_CARD_TEXT_(card, 2, "trapc:%x", rc); | ||
2685 | return 0; | ||
2686 | } | ||
2687 | |||
2688 | int qeth_hw_trap(struct qeth_card *card, enum qeth_diags_trap_action action) | ||
2689 | { | ||
2690 | struct qeth_cmd_buffer *iob; | ||
2691 | struct qeth_ipa_cmd *cmd; | ||
2692 | |||
2693 | QETH_DBF_TEXT(SETUP, 2, "diagtrap"); | ||
2694 | iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SET_DIAG_ASS, 0); | ||
2695 | cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); | ||
2696 | cmd->data.diagass.subcmd_len = 80; | ||
2697 | cmd->data.diagass.subcmd = QETH_DIAGS_CMD_TRAP; | ||
2698 | cmd->data.diagass.type = 1; | ||
2699 | cmd->data.diagass.action = action; | ||
2700 | switch (action) { | ||
2701 | case QETH_DIAGS_TRAP_ARM: | ||
2702 | cmd->data.diagass.options = 0x0003; | ||
2703 | cmd->data.diagass.ext = 0x00010000 + | ||
2704 | sizeof(struct qeth_trap_id); | ||
2705 | qeth_get_trap_id(card, | ||
2706 | (struct qeth_trap_id *)cmd->data.diagass.cdata); | ||
2707 | break; | ||
2708 | case QETH_DIAGS_TRAP_DISARM: | ||
2709 | cmd->data.diagass.options = 0x0001; | ||
2710 | break; | ||
2711 | case QETH_DIAGS_TRAP_CAPTURE: | ||
2712 | break; | ||
2713 | } | ||
2714 | return qeth_send_ipa_cmd(card, iob, qeth_hw_trap_cb, NULL); | ||
2715 | } | ||
2716 | EXPORT_SYMBOL_GPL(qeth_hw_trap); | ||
2717 | |||
2609 | int qeth_check_qdio_errors(struct qeth_card *card, struct qdio_buffer *buf, | 2718 | int qeth_check_qdio_errors(struct qeth_card *card, struct qdio_buffer *buf, |
2610 | unsigned int qdio_error, const char *dbftext) | 2719 | unsigned int qdio_error, const char *dbftext) |
2611 | { | 2720 | { |
2612 | if (qdio_error) { | 2721 | if (qdio_error) { |
2613 | QETH_CARD_TEXT(card, 2, dbftext); | 2722 | QETH_CARD_TEXT(card, 2, dbftext); |
2614 | QETH_CARD_TEXT_(card, 2, " F15=%02X", | 2723 | QETH_CARD_TEXT_(card, 2, " F15=%02X", |
2615 | buf->element[15].flags & 0xff); | 2724 | buf->element[15].sflags); |
2616 | QETH_CARD_TEXT_(card, 2, " F14=%02X", | 2725 | QETH_CARD_TEXT_(card, 2, " F14=%02X", |
2617 | buf->element[14].flags & 0xff); | 2726 | buf->element[14].sflags); |
2618 | QETH_CARD_TEXT_(card, 2, " qerr=%X", qdio_error); | 2727 | QETH_CARD_TEXT_(card, 2, " qerr=%X", qdio_error); |
2619 | if ((buf->element[15].flags & 0xff) == 0x12) { | 2728 | if ((buf->element[15].sflags) == 0x12) { |
2620 | card->stats.rx_dropped++; | 2729 | card->stats.rx_dropped++; |
2621 | return 0; | 2730 | return 0; |
2622 | } else | 2731 | } else |
@@ -2692,7 +2801,7 @@ EXPORT_SYMBOL_GPL(qeth_queue_input_buffer); | |||
2692 | static int qeth_handle_send_error(struct qeth_card *card, | 2801 | static int qeth_handle_send_error(struct qeth_card *card, |
2693 | struct qeth_qdio_out_buffer *buffer, unsigned int qdio_err) | 2802 | struct qeth_qdio_out_buffer *buffer, unsigned int qdio_err) |
2694 | { | 2803 | { |
2695 | int sbalf15 = buffer->buffer->element[15].flags & 0xff; | 2804 | int sbalf15 = buffer->buffer->element[15].sflags; |
2696 | 2805 | ||
2697 | QETH_CARD_TEXT(card, 6, "hdsnderr"); | 2806 | QETH_CARD_TEXT(card, 6, "hdsnderr"); |
2698 | if (card->info.type == QETH_CARD_TYPE_IQD) { | 2807 | if (card->info.type == QETH_CARD_TYPE_IQD) { |
@@ -2801,8 +2910,8 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index, | |||
2801 | 2910 | ||
2802 | for (i = index; i < index + count; ++i) { | 2911 | for (i = index; i < index + count; ++i) { |
2803 | buf = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q]; | 2912 | buf = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q]; |
2804 | buf->buffer->element[buf->next_element_to_fill - 1].flags |= | 2913 | buf->buffer->element[buf->next_element_to_fill - 1].eflags |= |
2805 | SBAL_FLAGS_LAST_ENTRY; | 2914 | SBAL_EFLAGS_LAST_ENTRY; |
2806 | 2915 | ||
2807 | if (queue->card->info.type == QETH_CARD_TYPE_IQD) | 2916 | if (queue->card->info.type == QETH_CARD_TYPE_IQD) |
2808 | continue; | 2917 | continue; |
@@ -2815,7 +2924,7 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index, | |||
2815 | /* it's likely that we'll go to packing | 2924 | /* it's likely that we'll go to packing |
2816 | * mode soon */ | 2925 | * mode soon */ |
2817 | atomic_inc(&queue->set_pci_flags_count); | 2926 | atomic_inc(&queue->set_pci_flags_count); |
2818 | buf->buffer->element[0].flags |= 0x40; | 2927 | buf->buffer->element[0].sflags |= SBAL_SFLAGS0_PCI_REQ; |
2819 | } | 2928 | } |
2820 | } else { | 2929 | } else { |
2821 | if (!atomic_read(&queue->set_pci_flags_count)) { | 2930 | if (!atomic_read(&queue->set_pci_flags_count)) { |
@@ -2828,12 +2937,11 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index, | |||
2828 | * further send was requested by the stack | 2937 | * further send was requested by the stack |
2829 | */ | 2938 | */ |
2830 | atomic_inc(&queue->set_pci_flags_count); | 2939 | atomic_inc(&queue->set_pci_flags_count); |
2831 | buf->buffer->element[0].flags |= 0x40; | 2940 | buf->buffer->element[0].sflags |= SBAL_SFLAGS0_PCI_REQ; |
2832 | } | 2941 | } |
2833 | } | 2942 | } |
2834 | } | 2943 | } |
2835 | 2944 | ||
2836 | queue->sync_iqdio_error = 0; | ||
2837 | queue->card->dev->trans_start = jiffies; | 2945 | queue->card->dev->trans_start = jiffies; |
2838 | if (queue->card->options.performance_stats) { | 2946 | if (queue->card->options.performance_stats) { |
2839 | queue->card->perf_stats.outbound_do_qdio_cnt++; | 2947 | queue->card->perf_stats.outbound_do_qdio_cnt++; |
@@ -2849,10 +2957,7 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index, | |||
2849 | queue->card->perf_stats.outbound_do_qdio_time += | 2957 | queue->card->perf_stats.outbound_do_qdio_time += |
2850 | qeth_get_micros() - | 2958 | qeth_get_micros() - |
2851 | queue->card->perf_stats.outbound_do_qdio_start_time; | 2959 | queue->card->perf_stats.outbound_do_qdio_start_time; |
2852 | if (rc > 0) { | 2960 | atomic_add(count, &queue->used_buffers); |
2853 | if (!(rc & QDIO_ERROR_SIGA_BUSY)) | ||
2854 | queue->sync_iqdio_error = rc & 3; | ||
2855 | } | ||
2856 | if (rc) { | 2961 | if (rc) { |
2857 | queue->card->stats.tx_errors += count; | 2962 | queue->card->stats.tx_errors += count; |
2858 | /* ignore temporary SIGA errors without busy condition */ | 2963 | /* ignore temporary SIGA errors without busy condition */ |
@@ -2866,7 +2971,6 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index, | |||
2866 | qeth_schedule_recovery(queue->card); | 2971 | qeth_schedule_recovery(queue->card); |
2867 | return; | 2972 | return; |
2868 | } | 2973 | } |
2869 | atomic_add(count, &queue->used_buffers); | ||
2870 | if (queue->card->options.performance_stats) | 2974 | if (queue->card->options.performance_stats) |
2871 | queue->card->perf_stats.bufs_sent += count; | 2975 | queue->card->perf_stats.bufs_sent += count; |
2872 | } | 2976 | } |
@@ -2911,6 +3015,27 @@ static void qeth_check_outbound_queue(struct qeth_qdio_out_q *queue) | |||
2911 | } | 3015 | } |
2912 | } | 3016 | } |
2913 | 3017 | ||
3018 | void qeth_qdio_start_poll(struct ccw_device *ccwdev, int queue, | ||
3019 | unsigned long card_ptr) | ||
3020 | { | ||
3021 | struct qeth_card *card = (struct qeth_card *)card_ptr; | ||
3022 | |||
3023 | if (card->dev && (card->dev->flags & IFF_UP)) | ||
3024 | napi_schedule(&card->napi); | ||
3025 | } | ||
3026 | EXPORT_SYMBOL_GPL(qeth_qdio_start_poll); | ||
3027 | |||
3028 | void qeth_qdio_input_handler(struct ccw_device *ccwdev, unsigned int qdio_err, | ||
3029 | unsigned int queue, int first_element, int count, | ||
3030 | unsigned long card_ptr) | ||
3031 | { | ||
3032 | struct qeth_card *card = (struct qeth_card *)card_ptr; | ||
3033 | |||
3034 | if (qdio_err) | ||
3035 | qeth_schedule_recovery(card); | ||
3036 | } | ||
3037 | EXPORT_SYMBOL_GPL(qeth_qdio_input_handler); | ||
3038 | |||
2914 | void qeth_qdio_output_handler(struct ccw_device *ccwdev, | 3039 | void qeth_qdio_output_handler(struct ccw_device *ccwdev, |
2915 | unsigned int qdio_error, int __queue, int first_element, | 3040 | unsigned int qdio_error, int __queue, int first_element, |
2916 | int count, unsigned long card_ptr) | 3041 | int count, unsigned long card_ptr) |
@@ -2919,7 +3044,6 @@ void qeth_qdio_output_handler(struct ccw_device *ccwdev, | |||
2919 | struct qeth_qdio_out_q *queue = card->qdio.out_qs[__queue]; | 3044 | struct qeth_qdio_out_q *queue = card->qdio.out_qs[__queue]; |
2920 | struct qeth_qdio_out_buffer *buffer; | 3045 | struct qeth_qdio_out_buffer *buffer; |
2921 | int i; | 3046 | int i; |
2922 | unsigned qeth_send_err; | ||
2923 | 3047 | ||
2924 | QETH_CARD_TEXT(card, 6, "qdouhdl"); | 3048 | QETH_CARD_TEXT(card, 6, "qdouhdl"); |
2925 | if (qdio_error & QDIO_ERROR_ACTIVATE_CHECK_CONDITION) { | 3049 | if (qdio_error & QDIO_ERROR_ACTIVATE_CHECK_CONDITION) { |
@@ -2935,9 +3059,8 @@ void qeth_qdio_output_handler(struct ccw_device *ccwdev, | |||
2935 | } | 3059 | } |
2936 | for (i = first_element; i < (first_element + count); ++i) { | 3060 | for (i = first_element; i < (first_element + count); ++i) { |
2937 | buffer = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q]; | 3061 | buffer = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q]; |
2938 | qeth_send_err = qeth_handle_send_error(card, buffer, qdio_error); | 3062 | qeth_handle_send_error(card, buffer, qdio_error); |
2939 | __qeth_clear_output_buffer(queue, buffer, | 3063 | qeth_clear_output_buffer(queue, buffer); |
2940 | (qeth_send_err == QETH_SEND_ERROR_RETRY) ? 1 : 0); | ||
2941 | } | 3064 | } |
2942 | atomic_sub(count, &queue->used_buffers); | 3065 | atomic_sub(count, &queue->used_buffers); |
2943 | /* check if we need to do something on this outbound queue */ | 3066 | /* check if we need to do something on this outbound queue */ |
@@ -3060,20 +3183,20 @@ static inline void __qeth_fill_buffer(struct sk_buff *skb, | |||
3060 | if (!length) { | 3183 | if (!length) { |
3061 | if (first_lap) | 3184 | if (first_lap) |
3062 | if (skb_shinfo(skb)->nr_frags) | 3185 | if (skb_shinfo(skb)->nr_frags) |
3063 | buffer->element[element].flags = | 3186 | buffer->element[element].eflags = |
3064 | SBAL_FLAGS_FIRST_FRAG; | 3187 | SBAL_EFLAGS_FIRST_FRAG; |
3065 | else | 3188 | else |
3066 | buffer->element[element].flags = 0; | 3189 | buffer->element[element].eflags = 0; |
3067 | else | 3190 | else |
3068 | buffer->element[element].flags = | 3191 | buffer->element[element].eflags = |
3069 | SBAL_FLAGS_MIDDLE_FRAG; | 3192 | SBAL_EFLAGS_MIDDLE_FRAG; |
3070 | } else { | 3193 | } else { |
3071 | if (first_lap) | 3194 | if (first_lap) |
3072 | buffer->element[element].flags = | 3195 | buffer->element[element].eflags = |
3073 | SBAL_FLAGS_FIRST_FRAG; | 3196 | SBAL_EFLAGS_FIRST_FRAG; |
3074 | else | 3197 | else |
3075 | buffer->element[element].flags = | 3198 | buffer->element[element].eflags = |
3076 | SBAL_FLAGS_MIDDLE_FRAG; | 3199 | SBAL_EFLAGS_MIDDLE_FRAG; |
3077 | } | 3200 | } |
3078 | data += length_here; | 3201 | data += length_here; |
3079 | element++; | 3202 | element++; |
@@ -3085,12 +3208,12 @@ static inline void __qeth_fill_buffer(struct sk_buff *skb, | |||
3085 | buffer->element[element].addr = (char *)page_to_phys(frag->page) | 3208 | buffer->element[element].addr = (char *)page_to_phys(frag->page) |
3086 | + frag->page_offset; | 3209 | + frag->page_offset; |
3087 | buffer->element[element].length = frag->size; | 3210 | buffer->element[element].length = frag->size; |
3088 | buffer->element[element].flags = SBAL_FLAGS_MIDDLE_FRAG; | 3211 | buffer->element[element].eflags = SBAL_EFLAGS_MIDDLE_FRAG; |
3089 | element++; | 3212 | element++; |
3090 | } | 3213 | } |
3091 | 3214 | ||
3092 | if (buffer->element[element - 1].flags) | 3215 | if (buffer->element[element - 1].eflags) |
3093 | buffer->element[element - 1].flags = SBAL_FLAGS_LAST_FRAG; | 3216 | buffer->element[element - 1].eflags = SBAL_EFLAGS_LAST_FRAG; |
3094 | *next_element_to_fill = element; | 3217 | *next_element_to_fill = element; |
3095 | } | 3218 | } |
3096 | 3219 | ||
@@ -3114,7 +3237,7 @@ static inline int qeth_fill_buffer(struct qeth_qdio_out_q *queue, | |||
3114 | /*fill first buffer entry only with header information */ | 3237 | /*fill first buffer entry only with header information */ |
3115 | buffer->element[element].addr = skb->data; | 3238 | buffer->element[element].addr = skb->data; |
3116 | buffer->element[element].length = hdr_len; | 3239 | buffer->element[element].length = hdr_len; |
3117 | buffer->element[element].flags = SBAL_FLAGS_FIRST_FRAG; | 3240 | buffer->element[element].eflags = SBAL_EFLAGS_FIRST_FRAG; |
3118 | buf->next_element_to_fill++; | 3241 | buf->next_element_to_fill++; |
3119 | skb->data += hdr_len; | 3242 | skb->data += hdr_len; |
3120 | skb->len -= hdr_len; | 3243 | skb->len -= hdr_len; |
@@ -3126,7 +3249,7 @@ static inline int qeth_fill_buffer(struct qeth_qdio_out_q *queue, | |||
3126 | buffer->element[element].addr = hdr; | 3249 | buffer->element[element].addr = hdr; |
3127 | buffer->element[element].length = sizeof(struct qeth_hdr) + | 3250 | buffer->element[element].length = sizeof(struct qeth_hdr) + |
3128 | hd_len; | 3251 | hd_len; |
3129 | buffer->element[element].flags = SBAL_FLAGS_FIRST_FRAG; | 3252 | buffer->element[element].eflags = SBAL_EFLAGS_FIRST_FRAG; |
3130 | buf->is_header[element] = 1; | 3253 | buf->is_header[element] = 1; |
3131 | buf->next_element_to_fill++; | 3254 | buf->next_element_to_fill++; |
3132 | } | 3255 | } |
@@ -3162,10 +3285,7 @@ int qeth_do_send_packet_fast(struct qeth_card *card, | |||
3162 | int offset, int hd_len) | 3285 | int offset, int hd_len) |
3163 | { | 3286 | { |
3164 | struct qeth_qdio_out_buffer *buffer; | 3287 | struct qeth_qdio_out_buffer *buffer; |
3165 | struct sk_buff *skb1; | ||
3166 | struct qeth_skb_data *retry_ctrl; | ||
3167 | int index; | 3288 | int index; |
3168 | int rc; | ||
3169 | 3289 | ||
3170 | /* spin until we get the queue ... */ | 3290 | /* spin until we get the queue ... */ |
3171 | while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED, | 3291 | while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED, |
@@ -3184,25 +3304,6 @@ int qeth_do_send_packet_fast(struct qeth_card *card, | |||
3184 | atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); | 3304 | atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); |
3185 | qeth_fill_buffer(queue, buffer, skb, hdr, offset, hd_len); | 3305 | qeth_fill_buffer(queue, buffer, skb, hdr, offset, hd_len); |
3186 | qeth_flush_buffers(queue, index, 1); | 3306 | qeth_flush_buffers(queue, index, 1); |
3187 | if (queue->sync_iqdio_error == 2) { | ||
3188 | skb1 = skb_dequeue(&buffer->skb_list); | ||
3189 | while (skb1) { | ||
3190 | atomic_dec(&skb1->users); | ||
3191 | skb1 = skb_dequeue(&buffer->skb_list); | ||
3192 | } | ||
3193 | retry_ctrl = (struct qeth_skb_data *) &skb->cb[16]; | ||
3194 | if (retry_ctrl->magic != QETH_SKB_MAGIC) { | ||
3195 | retry_ctrl->magic = QETH_SKB_MAGIC; | ||
3196 | retry_ctrl->count = 0; | ||
3197 | } | ||
3198 | if (retry_ctrl->count < QETH_SIGA_CC2_RETRIES) { | ||
3199 | retry_ctrl->count++; | ||
3200 | rc = dev_queue_xmit(skb); | ||
3201 | } else { | ||
3202 | dev_kfree_skb_any(skb); | ||
3203 | QETH_CARD_TEXT(card, 2, "qrdrop"); | ||
3204 | } | ||
3205 | } | ||
3206 | return 0; | 3307 | return 0; |
3207 | out: | 3308 | out: |
3208 | atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); | 3309 | atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); |
@@ -3791,6 +3892,47 @@ static inline int qeth_get_qdio_q_format(struct qeth_card *card) | |||
3791 | } | 3892 | } |
3792 | } | 3893 | } |
3793 | 3894 | ||
3895 | static void qeth_determine_capabilities(struct qeth_card *card) | ||
3896 | { | ||
3897 | int rc; | ||
3898 | int length; | ||
3899 | char *prcd; | ||
3900 | struct ccw_device *ddev; | ||
3901 | int ddev_offline = 0; | ||
3902 | |||
3903 | QETH_DBF_TEXT(SETUP, 2, "detcapab"); | ||
3904 | ddev = CARD_DDEV(card); | ||
3905 | if (!ddev->online) { | ||
3906 | ddev_offline = 1; | ||
3907 | rc = ccw_device_set_online(ddev); | ||
3908 | if (rc) { | ||
3909 | QETH_DBF_TEXT_(SETUP, 2, "3err%d", rc); | ||
3910 | goto out; | ||
3911 | } | ||
3912 | } | ||
3913 | |||
3914 | rc = qeth_read_conf_data(card, (void **) &prcd, &length); | ||
3915 | if (rc) { | ||
3916 | QETH_DBF_MESSAGE(2, "%s qeth_read_conf_data returned %i\n", | ||
3917 | dev_name(&card->gdev->dev), rc); | ||
3918 | QETH_DBF_TEXT_(SETUP, 2, "5err%d", rc); | ||
3919 | goto out_offline; | ||
3920 | } | ||
3921 | qeth_configure_unitaddr(card, prcd); | ||
3922 | qeth_configure_blkt_default(card, prcd); | ||
3923 | kfree(prcd); | ||
3924 | |||
3925 | rc = qdio_get_ssqd_desc(ddev, &card->ssqd); | ||
3926 | if (rc) | ||
3927 | QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc); | ||
3928 | |||
3929 | out_offline: | ||
3930 | if (ddev_offline == 1) | ||
3931 | ccw_device_set_offline(ddev); | ||
3932 | out: | ||
3933 | return; | ||
3934 | } | ||
3935 | |||
3794 | static int qeth_qdio_establish(struct qeth_card *card) | 3936 | static int qeth_qdio_establish(struct qeth_card *card) |
3795 | { | 3937 | { |
3796 | struct qdio_initialize init_data; | 3938 | struct qdio_initialize init_data; |
@@ -3843,9 +3985,12 @@ static int qeth_qdio_establish(struct qeth_card *card) | |||
3843 | init_data.no_output_qs = card->qdio.no_out_queues; | 3985 | init_data.no_output_qs = card->qdio.no_out_queues; |
3844 | init_data.input_handler = card->discipline.input_handler; | 3986 | init_data.input_handler = card->discipline.input_handler; |
3845 | init_data.output_handler = card->discipline.output_handler; | 3987 | init_data.output_handler = card->discipline.output_handler; |
3988 | init_data.queue_start_poll = card->discipline.start_poll; | ||
3846 | init_data.int_parm = (unsigned long) card; | 3989 | init_data.int_parm = (unsigned long) card; |
3847 | init_data.input_sbal_addr_array = (void **) in_sbal_ptrs; | 3990 | init_data.input_sbal_addr_array = (void **) in_sbal_ptrs; |
3848 | init_data.output_sbal_addr_array = (void **) out_sbal_ptrs; | 3991 | init_data.output_sbal_addr_array = (void **) out_sbal_ptrs; |
3992 | init_data.scan_threshold = | ||
3993 | (card->info.type == QETH_CARD_TYPE_IQD) ? 8 : 32; | ||
3849 | 3994 | ||
3850 | if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_ALLOCATED, | 3995 | if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_ALLOCATED, |
3851 | QETH_QDIO_ESTABLISHED) == QETH_QDIO_ALLOCATED) { | 3996 | QETH_QDIO_ESTABLISHED) == QETH_QDIO_ALLOCATED) { |
@@ -3898,7 +4043,10 @@ static struct ccw_device_id qeth_ids[] = { | |||
3898 | MODULE_DEVICE_TABLE(ccw, qeth_ids); | 4043 | MODULE_DEVICE_TABLE(ccw, qeth_ids); |
3899 | 4044 | ||
3900 | static struct ccw_driver qeth_ccw_driver = { | 4045 | static struct ccw_driver qeth_ccw_driver = { |
3901 | .name = "qeth", | 4046 | .driver = { |
4047 | .owner = THIS_MODULE, | ||
4048 | .name = "qeth", | ||
4049 | }, | ||
3902 | .ids = qeth_ids, | 4050 | .ids = qeth_ids, |
3903 | .probe = ccwgroup_probe_ccwdev, | 4051 | .probe = ccwgroup_probe_ccwdev, |
3904 | .remove = ccwgroup_remove_ccwdev, | 4052 | .remove = ccwgroup_remove_ccwdev, |
@@ -3918,6 +4066,7 @@ int qeth_core_hardsetup_card(struct qeth_card *card) | |||
3918 | 4066 | ||
3919 | QETH_DBF_TEXT(SETUP, 2, "hrdsetup"); | 4067 | QETH_DBF_TEXT(SETUP, 2, "hrdsetup"); |
3920 | atomic_set(&card->force_alloc_skb, 0); | 4068 | atomic_set(&card->force_alloc_skb, 0); |
4069 | qeth_get_channel_path_desc(card); | ||
3921 | retry: | 4070 | retry: |
3922 | if (retries) | 4071 | if (retries) |
3923 | QETH_DBF_MESSAGE(2, "%s Retrying to do IDX activates.\n", | 4072 | QETH_DBF_MESSAGE(2, "%s Retrying to do IDX activates.\n", |
@@ -3946,6 +4095,7 @@ retriable: | |||
3946 | else | 4095 | else |
3947 | goto retry; | 4096 | goto retry; |
3948 | } | 4097 | } |
4098 | qeth_determine_capabilities(card); | ||
3949 | qeth_init_tokens(card); | 4099 | qeth_init_tokens(card); |
3950 | qeth_init_func_level(card); | 4100 | qeth_init_func_level(card); |
3951 | rc = qeth_idx_activate_channel(&card->read, qeth_idx_read_cb); | 4101 | rc = qeth_idx_activate_channel(&card->read, qeth_idx_read_cb); |
@@ -3976,6 +4126,15 @@ retriable: | |||
3976 | QETH_DBF_TEXT_(SETUP, 2, "5err%d", rc); | 4126 | QETH_DBF_TEXT_(SETUP, 2, "5err%d", rc); |
3977 | goto out; | 4127 | goto out; |
3978 | } | 4128 | } |
4129 | |||
4130 | card->options.ipa4.supported_funcs = 0; | ||
4131 | card->options.adp.supported_funcs = 0; | ||
4132 | card->info.diagass_support = 0; | ||
4133 | qeth_query_ipassists(card, QETH_PROT_IPV4); | ||
4134 | if (qeth_is_supported(card, IPA_SETADAPTERPARMS)) | ||
4135 | qeth_query_setadapterparms(card); | ||
4136 | if (qeth_adp_supported(card, IPA_SETADP_SET_DIAG_ASSIST)) | ||
4137 | qeth_query_setdiagass(card); | ||
3979 | return 0; | 4138 | return 0; |
3980 | out: | 4139 | out: |
3981 | dev_warn(&card->gdev->dev, "The qeth device driver failed to recover " | 4140 | dev_warn(&card->gdev->dev, "The qeth device driver failed to recover " |
@@ -4215,41 +4374,6 @@ void qeth_core_free_discipline(struct qeth_card *card) | |||
4215 | card->discipline.ccwgdriver = NULL; | 4374 | card->discipline.ccwgdriver = NULL; |
4216 | } | 4375 | } |
4217 | 4376 | ||
4218 | static void qeth_determine_capabilities(struct qeth_card *card) | ||
4219 | { | ||
4220 | int rc; | ||
4221 | int length; | ||
4222 | char *prcd; | ||
4223 | |||
4224 | QETH_DBF_TEXT(SETUP, 2, "detcapab"); | ||
4225 | rc = ccw_device_set_online(CARD_DDEV(card)); | ||
4226 | if (rc) { | ||
4227 | QETH_DBF_TEXT_(SETUP, 2, "3err%d", rc); | ||
4228 | goto out; | ||
4229 | } | ||
4230 | |||
4231 | |||
4232 | rc = qeth_read_conf_data(card, (void **) &prcd, &length); | ||
4233 | if (rc) { | ||
4234 | QETH_DBF_MESSAGE(2, "%s qeth_read_conf_data returned %i\n", | ||
4235 | dev_name(&card->gdev->dev), rc); | ||
4236 | QETH_DBF_TEXT_(SETUP, 2, "5err%d", rc); | ||
4237 | goto out_offline; | ||
4238 | } | ||
4239 | qeth_configure_unitaddr(card, prcd); | ||
4240 | qeth_configure_blkt_default(card, prcd); | ||
4241 | kfree(prcd); | ||
4242 | |||
4243 | rc = qdio_get_ssqd_desc(CARD_DDEV(card), &card->ssqd); | ||
4244 | if (rc) | ||
4245 | QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc); | ||
4246 | |||
4247 | out_offline: | ||
4248 | ccw_device_set_offline(CARD_DDEV(card)); | ||
4249 | out: | ||
4250 | return; | ||
4251 | } | ||
4252 | |||
4253 | static int qeth_core_probe_device(struct ccwgroup_device *gdev) | 4377 | static int qeth_core_probe_device(struct ccwgroup_device *gdev) |
4254 | { | 4378 | { |
4255 | struct qeth_card *card; | 4379 | struct qeth_card *card; |
@@ -4457,8 +4581,10 @@ static int qeth_core_restore(struct ccwgroup_device *gdev) | |||
4457 | } | 4581 | } |
4458 | 4582 | ||
4459 | static struct ccwgroup_driver qeth_core_ccwgroup_driver = { | 4583 | static struct ccwgroup_driver qeth_core_ccwgroup_driver = { |
4460 | .owner = THIS_MODULE, | 4584 | .driver = { |
4461 | .name = "qeth", | 4585 | .owner = THIS_MODULE, |
4586 | .name = "qeth", | ||
4587 | }, | ||
4462 | .driver_id = 0xD8C5E3C8, | 4588 | .driver_id = 0xD8C5E3C8, |
4463 | .probe = qeth_core_probe_device, | 4589 | .probe = qeth_core_probe_device, |
4464 | .remove = qeth_core_remove_device, | 4590 | .remove = qeth_core_remove_device, |
@@ -4513,8 +4639,8 @@ static struct { | |||
4513 | /* 20 */{"queue 1 buffer usage"}, | 4639 | /* 20 */{"queue 1 buffer usage"}, |
4514 | {"queue 2 buffer usage"}, | 4640 | {"queue 2 buffer usage"}, |
4515 | {"queue 3 buffer usage"}, | 4641 | {"queue 3 buffer usage"}, |
4516 | {"rx handler time"}, | 4642 | {"rx poll time"}, |
4517 | {"rx handler count"}, | 4643 | {"rx poll count"}, |
4518 | {"rx do_QDIO time"}, | 4644 | {"rx do_QDIO time"}, |
4519 | {"rx do_QDIO count"}, | 4645 | {"rx do_QDIO count"}, |
4520 | {"tx handler time"}, | 4646 | {"tx handler time"}, |
diff --git a/drivers/s390/net/qeth_core_mpc.h b/drivers/s390/net/qeth_core_mpc.h index e37dd8c4bf4e..e5a9d1c03839 100644 --- a/drivers/s390/net/qeth_core_mpc.h +++ b/drivers/s390/net/qeth_core_mpc.h | |||
@@ -80,14 +80,6 @@ enum qeth_tr_broadcast_modes { | |||
80 | QETH_TR_BROADCAST_LOCAL = 1, | 80 | QETH_TR_BROADCAST_LOCAL = 1, |
81 | }; | 81 | }; |
82 | 82 | ||
83 | /* these values match CHECKSUM_* in include/linux/skbuff.h */ | ||
84 | enum qeth_checksum_types { | ||
85 | SW_CHECKSUMMING = 0, /* TODO: set to bit flag used in IPA Command */ | ||
86 | HW_CHECKSUMMING = 1, | ||
87 | NO_CHECKSUMMING = 2, | ||
88 | }; | ||
89 | #define QETH_CHECKSUM_DEFAULT SW_CHECKSUMMING | ||
90 | |||
91 | /* | 83 | /* |
92 | * Routing stuff | 84 | * Routing stuff |
93 | */ | 85 | */ |
@@ -333,7 +325,7 @@ struct qeth_arp_query_data { | |||
333 | __u16 request_bits; | 325 | __u16 request_bits; |
334 | __u16 reply_bits; | 326 | __u16 reply_bits; |
335 | __u32 no_entries; | 327 | __u32 no_entries; |
336 | char data; | 328 | char data; /* only for replies */ |
337 | } __attribute__((packed)); | 329 | } __attribute__((packed)); |
338 | 330 | ||
339 | /* used as parameter for arp_query reply */ | 331 | /* used as parameter for arp_query reply */ |
@@ -456,6 +448,12 @@ enum qeth_diags_trace_cmds { | |||
456 | QETH_DIAGS_CMD_TRACE_QUERY = 0x0010, | 448 | QETH_DIAGS_CMD_TRACE_QUERY = 0x0010, |
457 | }; | 449 | }; |
458 | 450 | ||
451 | enum qeth_diags_trap_action { | ||
452 | QETH_DIAGS_TRAP_ARM = 0x01, | ||
453 | QETH_DIAGS_TRAP_DISARM = 0x02, | ||
454 | QETH_DIAGS_TRAP_CAPTURE = 0x04, | ||
455 | }; | ||
456 | |||
459 | struct qeth_ipacmd_diagass { | 457 | struct qeth_ipacmd_diagass { |
460 | __u32 host_tod2; | 458 | __u32 host_tod2; |
461 | __u32:32; | 459 | __u32:32; |
@@ -465,7 +463,8 @@ struct qeth_ipacmd_diagass { | |||
465 | __u8 type; | 463 | __u8 type; |
466 | __u8 action; | 464 | __u8 action; |
467 | __u16 options; | 465 | __u16 options; |
468 | __u32:32; | 466 | __u32 ext; |
467 | __u8 cdata[64]; | ||
469 | } __attribute__ ((packed)); | 468 | } __attribute__ ((packed)); |
470 | 469 | ||
471 | /* Header for each IPA command */ | 470 | /* Header for each IPA command */ |
diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c index 42fa783a70c8..0a8e86c1b0ea 100644 --- a/drivers/s390/net/qeth_core_sys.c +++ b/drivers/s390/net/qeth_core_sys.c | |||
@@ -372,7 +372,7 @@ static ssize_t qeth_dev_performance_stats_store(struct device *dev, | |||
372 | i = simple_strtoul(buf, &tmp, 16); | 372 | i = simple_strtoul(buf, &tmp, 16); |
373 | if ((i == 0) || (i == 1)) { | 373 | if ((i == 0) || (i == 1)) { |
374 | if (i == card->options.performance_stats) | 374 | if (i == card->options.performance_stats) |
375 | goto out;; | 375 | goto out; |
376 | card->options.performance_stats = i; | 376 | card->options.performance_stats = i; |
377 | if (i == 0) | 377 | if (i == 0) |
378 | memset(&card->perf_stats, 0, | 378 | memset(&card->perf_stats, 0, |
@@ -530,6 +530,66 @@ out: | |||
530 | static DEVICE_ATTR(isolation, 0644, qeth_dev_isolation_show, | 530 | static DEVICE_ATTR(isolation, 0644, qeth_dev_isolation_show, |
531 | qeth_dev_isolation_store); | 531 | qeth_dev_isolation_store); |
532 | 532 | ||
533 | static ssize_t qeth_hw_trap_show(struct device *dev, | ||
534 | struct device_attribute *attr, char *buf) | ||
535 | { | ||
536 | struct qeth_card *card = dev_get_drvdata(dev); | ||
537 | |||
538 | if (!card) | ||
539 | return -EINVAL; | ||
540 | if (card->info.hwtrap) | ||
541 | return snprintf(buf, 5, "arm\n"); | ||
542 | else | ||
543 | return snprintf(buf, 8, "disarm\n"); | ||
544 | } | ||
545 | |||
546 | static ssize_t qeth_hw_trap_store(struct device *dev, | ||
547 | struct device_attribute *attr, const char *buf, size_t count) | ||
548 | { | ||
549 | struct qeth_card *card = dev_get_drvdata(dev); | ||
550 | int rc = 0; | ||
551 | char *tmp, *curtoken; | ||
552 | int state = 0; | ||
553 | curtoken = (char *)buf; | ||
554 | |||
555 | if (!card) | ||
556 | return -EINVAL; | ||
557 | |||
558 | mutex_lock(&card->conf_mutex); | ||
559 | if (card->state == CARD_STATE_SOFTSETUP || card->state == CARD_STATE_UP) | ||
560 | state = 1; | ||
561 | tmp = strsep(&curtoken, "\n"); | ||
562 | |||
563 | if (!strcmp(tmp, "arm") && !card->info.hwtrap) { | ||
564 | if (state) { | ||
565 | if (qeth_is_diagass_supported(card, | ||
566 | QETH_DIAGS_CMD_TRAP)) { | ||
567 | rc = qeth_hw_trap(card, QETH_DIAGS_TRAP_ARM); | ||
568 | if (!rc) | ||
569 | card->info.hwtrap = 1; | ||
570 | } else | ||
571 | rc = -EINVAL; | ||
572 | } else | ||
573 | card->info.hwtrap = 1; | ||
574 | } else if (!strcmp(tmp, "disarm") && card->info.hwtrap) { | ||
575 | if (state) { | ||
576 | rc = qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); | ||
577 | if (!rc) | ||
578 | card->info.hwtrap = 0; | ||
579 | } else | ||
580 | card->info.hwtrap = 0; | ||
581 | } else if (!strcmp(tmp, "trap") && state && card->info.hwtrap) | ||
582 | rc = qeth_hw_trap(card, QETH_DIAGS_TRAP_CAPTURE); | ||
583 | else | ||
584 | rc = -EINVAL; | ||
585 | |||
586 | mutex_unlock(&card->conf_mutex); | ||
587 | return rc ? rc : count; | ||
588 | } | ||
589 | |||
590 | static DEVICE_ATTR(hw_trap, 0644, qeth_hw_trap_show, | ||
591 | qeth_hw_trap_store); | ||
592 | |||
533 | static ssize_t qeth_dev_blkt_show(char *buf, struct qeth_card *card, int value) | 593 | static ssize_t qeth_dev_blkt_show(char *buf, struct qeth_card *card, int value) |
534 | { | 594 | { |
535 | 595 | ||
@@ -653,6 +713,7 @@ static struct attribute *qeth_device_attrs[] = { | |||
653 | &dev_attr_performance_stats.attr, | 713 | &dev_attr_performance_stats.attr, |
654 | &dev_attr_layer2.attr, | 714 | &dev_attr_layer2.attr, |
655 | &dev_attr_isolation.attr, | 715 | &dev_attr_isolation.attr, |
716 | &dev_attr_hw_trap.attr, | ||
656 | NULL, | 717 | NULL, |
657 | }; | 718 | }; |
658 | 719 | ||
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 830d63524d61..b70b47fbd6cd 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c | |||
@@ -202,17 +202,19 @@ static void qeth_l2_add_mc(struct qeth_card *card, __u8 *mac, int vmac) | |||
202 | kfree(mc); | 202 | kfree(mc); |
203 | } | 203 | } |
204 | 204 | ||
205 | static void qeth_l2_del_all_mc(struct qeth_card *card) | 205 | static void qeth_l2_del_all_mc(struct qeth_card *card, int del) |
206 | { | 206 | { |
207 | struct qeth_mc_mac *mc, *tmp; | 207 | struct qeth_mc_mac *mc, *tmp; |
208 | 208 | ||
209 | spin_lock_bh(&card->mclock); | 209 | spin_lock_bh(&card->mclock); |
210 | list_for_each_entry_safe(mc, tmp, &card->mc_list, list) { | 210 | list_for_each_entry_safe(mc, tmp, &card->mc_list, list) { |
211 | if (mc->is_vmac) | 211 | if (del) { |
212 | qeth_l2_send_setdelmac(card, mc->mc_addr, | 212 | if (mc->is_vmac) |
213 | qeth_l2_send_setdelmac(card, mc->mc_addr, | ||
213 | IPA_CMD_DELVMAC, NULL); | 214 | IPA_CMD_DELVMAC, NULL); |
214 | else | 215 | else |
215 | qeth_l2_send_delgroupmac(card, mc->mc_addr); | 216 | qeth_l2_send_delgroupmac(card, mc->mc_addr); |
217 | } | ||
216 | list_del(&mc->list); | 218 | list_del(&mc->list); |
217 | kfree(mc); | 219 | kfree(mc); |
218 | } | 220 | } |
@@ -288,18 +290,13 @@ static int qeth_l2_send_setdelvlan(struct qeth_card *card, __u16 i, | |||
288 | qeth_l2_send_setdelvlan_cb, NULL); | 290 | qeth_l2_send_setdelvlan_cb, NULL); |
289 | } | 291 | } |
290 | 292 | ||
291 | static void qeth_l2_process_vlans(struct qeth_card *card, int clear) | 293 | static void qeth_l2_process_vlans(struct qeth_card *card) |
292 | { | 294 | { |
293 | struct qeth_vlan_vid *id; | 295 | struct qeth_vlan_vid *id; |
294 | QETH_CARD_TEXT(card, 3, "L2prcvln"); | 296 | QETH_CARD_TEXT(card, 3, "L2prcvln"); |
295 | spin_lock_bh(&card->vlanlock); | 297 | spin_lock_bh(&card->vlanlock); |
296 | list_for_each_entry(id, &card->vid_list, list) { | 298 | list_for_each_entry(id, &card->vid_list, list) { |
297 | if (clear) | 299 | qeth_l2_send_setdelvlan(card, id->vid, IPA_CMD_SETVLAN); |
298 | qeth_l2_send_setdelvlan(card, id->vid, | ||
299 | IPA_CMD_DELVLAN); | ||
300 | else | ||
301 | qeth_l2_send_setdelvlan(card, id->vid, | ||
302 | IPA_CMD_SETVLAN); | ||
303 | } | 300 | } |
304 | spin_unlock_bh(&card->vlanlock); | 301 | spin_unlock_bh(&card->vlanlock); |
305 | } | 302 | } |
@@ -310,6 +307,8 @@ static void qeth_l2_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) | |||
310 | struct qeth_vlan_vid *id; | 307 | struct qeth_vlan_vid *id; |
311 | 308 | ||
312 | QETH_CARD_TEXT_(card, 4, "aid:%d", vid); | 309 | QETH_CARD_TEXT_(card, 4, "aid:%d", vid); |
310 | if (!vid) | ||
311 | return; | ||
313 | if (card->info.type == QETH_CARD_TYPE_OSM) { | 312 | if (card->info.type == QETH_CARD_TYPE_OSM) { |
314 | QETH_CARD_TEXT(card, 3, "aidOSM"); | 313 | QETH_CARD_TEXT(card, 3, "aidOSM"); |
315 | return; | 314 | return; |
@@ -377,19 +376,11 @@ static int qeth_l2_stop_card(struct qeth_card *card, int recovery_mode) | |||
377 | dev_close(card->dev); | 376 | dev_close(card->dev); |
378 | rtnl_unlock(); | 377 | rtnl_unlock(); |
379 | } | 378 | } |
380 | if (!card->use_hard_stop || | 379 | card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED; |
381 | recovery_mode) { | ||
382 | __u8 *mac = &card->dev->dev_addr[0]; | ||
383 | rc = qeth_l2_send_delmac(card, mac); | ||
384 | QETH_DBF_TEXT_(SETUP, 2, "Lerr%d", rc); | ||
385 | } | ||
386 | card->state = CARD_STATE_SOFTSETUP; | 380 | card->state = CARD_STATE_SOFTSETUP; |
387 | } | 381 | } |
388 | if (card->state == CARD_STATE_SOFTSETUP) { | 382 | if (card->state == CARD_STATE_SOFTSETUP) { |
389 | qeth_l2_process_vlans(card, 1); | 383 | qeth_l2_del_all_mc(card, 0); |
390 | if (!card->use_hard_stop || | ||
391 | recovery_mode) | ||
392 | qeth_l2_del_all_mc(card); | ||
393 | qeth_clear_ipacmd_list(card); | 384 | qeth_clear_ipacmd_list(card); |
394 | card->state = CARD_STATE_HARDSETUP; | 385 | card->state = CARD_STATE_HARDSETUP; |
395 | } | 386 | } |
@@ -403,45 +394,37 @@ static int qeth_l2_stop_card(struct qeth_card *card, int recovery_mode) | |||
403 | qeth_clear_cmd_buffers(&card->read); | 394 | qeth_clear_cmd_buffers(&card->read); |
404 | qeth_clear_cmd_buffers(&card->write); | 395 | qeth_clear_cmd_buffers(&card->write); |
405 | } | 396 | } |
406 | card->use_hard_stop = 0; | ||
407 | return rc; | 397 | return rc; |
408 | } | 398 | } |
409 | 399 | ||
410 | static void qeth_l2_process_inbound_buffer(struct qeth_card *card, | 400 | static int qeth_l2_process_inbound_buffer(struct qeth_card *card, |
411 | struct qeth_qdio_buffer *buf, int index) | 401 | int budget, int *done) |
412 | { | 402 | { |
413 | struct qdio_buffer_element *element; | 403 | int work_done = 0; |
414 | struct sk_buff *skb; | 404 | struct sk_buff *skb; |
415 | struct qeth_hdr *hdr; | 405 | struct qeth_hdr *hdr; |
416 | int offset; | ||
417 | unsigned int len; | 406 | unsigned int len; |
418 | 407 | ||
419 | /* get first element of current buffer */ | 408 | *done = 0; |
420 | element = (struct qdio_buffer_element *)&buf->buffer->element[0]; | 409 | BUG_ON(!budget); |
421 | offset = 0; | 410 | while (budget) { |
422 | if (card->options.performance_stats) | 411 | skb = qeth_core_get_next_skb(card, |
423 | card->perf_stats.bufs_rec++; | 412 | card->qdio.in_q->bufs[card->rx.b_index].buffer, |
424 | while ((skb = qeth_core_get_next_skb(card, buf->buffer, &element, | 413 | &card->rx.b_element, &card->rx.e_offset, &hdr); |
425 | &offset, &hdr))) { | 414 | if (!skb) { |
426 | skb->dev = card->dev; | 415 | *done = 1; |
427 | /* is device UP ? */ | 416 | break; |
428 | if (!(card->dev->flags & IFF_UP)) { | ||
429 | dev_kfree_skb_any(skb); | ||
430 | continue; | ||
431 | } | 417 | } |
432 | 418 | skb->dev = card->dev; | |
433 | switch (hdr->hdr.l2.id) { | 419 | switch (hdr->hdr.l2.id) { |
434 | case QETH_HEADER_TYPE_LAYER2: | 420 | case QETH_HEADER_TYPE_LAYER2: |
435 | skb->pkt_type = PACKET_HOST; | 421 | skb->pkt_type = PACKET_HOST; |
436 | skb->protocol = eth_type_trans(skb, skb->dev); | 422 | skb->protocol = eth_type_trans(skb, skb->dev); |
437 | if (card->options.checksum_type == NO_CHECKSUMMING) | 423 | skb->ip_summed = CHECKSUM_NONE; |
438 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
439 | else | ||
440 | skb->ip_summed = CHECKSUM_NONE; | ||
441 | if (skb->protocol == htons(ETH_P_802_2)) | 424 | if (skb->protocol == htons(ETH_P_802_2)) |
442 | *((__u32 *)skb->cb) = ++card->seqno.pkt_seqno; | 425 | *((__u32 *)skb->cb) = ++card->seqno.pkt_seqno; |
443 | len = skb->len; | 426 | len = skb->len; |
444 | netif_rx(skb); | 427 | netif_receive_skb(skb); |
445 | break; | 428 | break; |
446 | case QETH_HEADER_TYPE_OSN: | 429 | case QETH_HEADER_TYPE_OSN: |
447 | if (card->info.type == QETH_CARD_TYPE_OSN) { | 430 | if (card->info.type == QETH_CARD_TYPE_OSN) { |
@@ -459,9 +442,87 @@ static void qeth_l2_process_inbound_buffer(struct qeth_card *card, | |||
459 | QETH_DBF_HEX(CTRL, 3, hdr, QETH_DBF_CTRL_LEN); | 442 | QETH_DBF_HEX(CTRL, 3, hdr, QETH_DBF_CTRL_LEN); |
460 | continue; | 443 | continue; |
461 | } | 444 | } |
445 | work_done++; | ||
446 | budget--; | ||
462 | card->stats.rx_packets++; | 447 | card->stats.rx_packets++; |
463 | card->stats.rx_bytes += len; | 448 | card->stats.rx_bytes += len; |
464 | } | 449 | } |
450 | return work_done; | ||
451 | } | ||
452 | |||
453 | static int qeth_l2_poll(struct napi_struct *napi, int budget) | ||
454 | { | ||
455 | struct qeth_card *card = container_of(napi, struct qeth_card, napi); | ||
456 | int work_done = 0; | ||
457 | struct qeth_qdio_buffer *buffer; | ||
458 | int done; | ||
459 | int new_budget = budget; | ||
460 | |||
461 | if (card->options.performance_stats) { | ||
462 | card->perf_stats.inbound_cnt++; | ||
463 | card->perf_stats.inbound_start_time = qeth_get_micros(); | ||
464 | } | ||
465 | |||
466 | while (1) { | ||
467 | if (!card->rx.b_count) { | ||
468 | card->rx.qdio_err = 0; | ||
469 | card->rx.b_count = qdio_get_next_buffers( | ||
470 | card->data.ccwdev, 0, &card->rx.b_index, | ||
471 | &card->rx.qdio_err); | ||
472 | if (card->rx.b_count <= 0) { | ||
473 | card->rx.b_count = 0; | ||
474 | break; | ||
475 | } | ||
476 | card->rx.b_element = | ||
477 | &card->qdio.in_q->bufs[card->rx.b_index] | ||
478 | .buffer->element[0]; | ||
479 | card->rx.e_offset = 0; | ||
480 | } | ||
481 | |||
482 | while (card->rx.b_count) { | ||
483 | buffer = &card->qdio.in_q->bufs[card->rx.b_index]; | ||
484 | if (!(card->rx.qdio_err && | ||
485 | qeth_check_qdio_errors(card, buffer->buffer, | ||
486 | card->rx.qdio_err, "qinerr"))) | ||
487 | work_done += qeth_l2_process_inbound_buffer( | ||
488 | card, new_budget, &done); | ||
489 | else | ||
490 | done = 1; | ||
491 | |||
492 | if (done) { | ||
493 | if (card->options.performance_stats) | ||
494 | card->perf_stats.bufs_rec++; | ||
495 | qeth_put_buffer_pool_entry(card, | ||
496 | buffer->pool_entry); | ||
497 | qeth_queue_input_buffer(card, card->rx.b_index); | ||
498 | card->rx.b_count--; | ||
499 | if (card->rx.b_count) { | ||
500 | card->rx.b_index = | ||
501 | (card->rx.b_index + 1) % | ||
502 | QDIO_MAX_BUFFERS_PER_Q; | ||
503 | card->rx.b_element = | ||
504 | &card->qdio.in_q | ||
505 | ->bufs[card->rx.b_index] | ||
506 | .buffer->element[0]; | ||
507 | card->rx.e_offset = 0; | ||
508 | } | ||
509 | } | ||
510 | |||
511 | if (work_done >= budget) | ||
512 | goto out; | ||
513 | else | ||
514 | new_budget = budget - work_done; | ||
515 | } | ||
516 | } | ||
517 | |||
518 | napi_complete(napi); | ||
519 | if (qdio_start_irq(card->data.ccwdev, 0)) | ||
520 | napi_schedule(&card->napi); | ||
521 | out: | ||
522 | if (card->options.performance_stats) | ||
523 | card->perf_stats.inbound_time += qeth_get_micros() - | ||
524 | card->perf_stats.inbound_start_time; | ||
525 | return work_done; | ||
465 | } | 526 | } |
466 | 527 | ||
467 | static int qeth_l2_send_setdelmac(struct qeth_card *card, __u8 *mac, | 528 | static int qeth_l2_send_setdelmac(struct qeth_card *card, __u8 *mac, |
@@ -497,13 +558,13 @@ static int qeth_l2_send_setmac_cb(struct qeth_card *card, | |||
497 | case IPA_RC_L2_DUP_LAYER3_MAC: | 558 | case IPA_RC_L2_DUP_LAYER3_MAC: |
498 | dev_warn(&card->gdev->dev, | 559 | dev_warn(&card->gdev->dev, |
499 | "MAC address %pM already exists\n", | 560 | "MAC address %pM already exists\n", |
500 | card->dev->dev_addr); | 561 | cmd->data.setdelmac.mac); |
501 | break; | 562 | break; |
502 | case IPA_RC_L2_MAC_NOT_AUTH_BY_HYP: | 563 | case IPA_RC_L2_MAC_NOT_AUTH_BY_HYP: |
503 | case IPA_RC_L2_MAC_NOT_AUTH_BY_ADP: | 564 | case IPA_RC_L2_MAC_NOT_AUTH_BY_ADP: |
504 | dev_warn(&card->gdev->dev, | 565 | dev_warn(&card->gdev->dev, |
505 | "MAC address %pM is not authorized\n", | 566 | "MAC address %pM is not authorized\n", |
506 | card->dev->dev_addr); | 567 | cmd->data.setdelmac.mac); |
507 | break; | 568 | break; |
508 | default: | 569 | default: |
509 | break; | 570 | break; |
@@ -629,7 +690,7 @@ static void qeth_l2_set_multicast_list(struct net_device *dev) | |||
629 | if (qeth_threads_running(card, QETH_RECOVER_THREAD) && | 690 | if (qeth_threads_running(card, QETH_RECOVER_THREAD) && |
630 | (card->state != CARD_STATE_UP)) | 691 | (card->state != CARD_STATE_UP)) |
631 | return; | 692 | return; |
632 | qeth_l2_del_all_mc(card); | 693 | qeth_l2_del_all_mc(card, 1); |
633 | spin_lock_bh(&card->mclock); | 694 | spin_lock_bh(&card->mclock); |
634 | netdev_for_each_mc_addr(ha, dev) | 695 | netdev_for_each_mc_addr(ha, dev) |
635 | qeth_l2_add_mc(card, ha->addr, 0); | 696 | qeth_l2_add_mc(card, ha->addr, 0); |
@@ -755,51 +816,14 @@ tx_drop: | |||
755 | return NETDEV_TX_OK; | 816 | return NETDEV_TX_OK; |
756 | } | 817 | } |
757 | 818 | ||
758 | static void qeth_l2_qdio_input_handler(struct ccw_device *ccwdev, | 819 | static int __qeth_l2_open(struct net_device *dev) |
759 | unsigned int qdio_err, unsigned int queue, | ||
760 | int first_element, int count, unsigned long card_ptr) | ||
761 | { | ||
762 | struct net_device *net_dev; | ||
763 | struct qeth_card *card; | ||
764 | struct qeth_qdio_buffer *buffer; | ||
765 | int index; | ||
766 | int i; | ||
767 | |||
768 | card = (struct qeth_card *) card_ptr; | ||
769 | net_dev = card->dev; | ||
770 | if (card->options.performance_stats) { | ||
771 | card->perf_stats.inbound_cnt++; | ||
772 | card->perf_stats.inbound_start_time = qeth_get_micros(); | ||
773 | } | ||
774 | if (qdio_err & QDIO_ERROR_ACTIVATE_CHECK_CONDITION) { | ||
775 | QETH_CARD_TEXT(card, 1, "qdinchk"); | ||
776 | QETH_CARD_TEXT_(card, 1, "%04X%04X", first_element, | ||
777 | count); | ||
778 | QETH_CARD_TEXT_(card, 1, "%04X", queue); | ||
779 | qeth_schedule_recovery(card); | ||
780 | return; | ||
781 | } | ||
782 | for (i = first_element; i < (first_element + count); ++i) { | ||
783 | index = i % QDIO_MAX_BUFFERS_PER_Q; | ||
784 | buffer = &card->qdio.in_q->bufs[index]; | ||
785 | if (!(qdio_err && | ||
786 | qeth_check_qdio_errors(card, buffer->buffer, qdio_err, | ||
787 | "qinerr"))) | ||
788 | qeth_l2_process_inbound_buffer(card, buffer, index); | ||
789 | /* clear buffer and give back to hardware */ | ||
790 | qeth_put_buffer_pool_entry(card, buffer->pool_entry); | ||
791 | qeth_queue_input_buffer(card, index); | ||
792 | } | ||
793 | if (card->options.performance_stats) | ||
794 | card->perf_stats.inbound_time += qeth_get_micros() - | ||
795 | card->perf_stats.inbound_start_time; | ||
796 | } | ||
797 | |||
798 | static int qeth_l2_open(struct net_device *dev) | ||
799 | { | 820 | { |
800 | struct qeth_card *card = dev->ml_priv; | 821 | struct qeth_card *card = dev->ml_priv; |
822 | int rc = 0; | ||
801 | 823 | ||
802 | QETH_CARD_TEXT(card, 4, "qethopen"); | 824 | QETH_CARD_TEXT(card, 4, "qethopen"); |
825 | if (card->state == CARD_STATE_UP) | ||
826 | return rc; | ||
803 | if (card->state != CARD_STATE_SOFTSETUP) | 827 | if (card->state != CARD_STATE_SOFTSETUP) |
804 | return -ENODEV; | 828 | return -ENODEV; |
805 | 829 | ||
@@ -812,11 +836,25 @@ static int qeth_l2_open(struct net_device *dev) | |||
812 | card->state = CARD_STATE_UP; | 836 | card->state = CARD_STATE_UP; |
813 | netif_start_queue(dev); | 837 | netif_start_queue(dev); |
814 | 838 | ||
815 | if (!card->lan_online && netif_carrier_ok(dev)) | 839 | if (qdio_stop_irq(card->data.ccwdev, 0) >= 0) { |
816 | netif_carrier_off(dev); | 840 | napi_enable(&card->napi); |
817 | return 0; | 841 | napi_schedule(&card->napi); |
842 | } else | ||
843 | rc = -EIO; | ||
844 | return rc; | ||
818 | } | 845 | } |
819 | 846 | ||
847 | static int qeth_l2_open(struct net_device *dev) | ||
848 | { | ||
849 | struct qeth_card *card = dev->ml_priv; | ||
850 | |||
851 | QETH_CARD_TEXT(card, 5, "qethope_"); | ||
852 | if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) { | ||
853 | QETH_CARD_TEXT(card, 3, "openREC"); | ||
854 | return -ERESTARTSYS; | ||
855 | } | ||
856 | return __qeth_l2_open(dev); | ||
857 | } | ||
820 | 858 | ||
821 | static int qeth_l2_stop(struct net_device *dev) | 859 | static int qeth_l2_stop(struct net_device *dev) |
822 | { | 860 | { |
@@ -824,8 +862,10 @@ static int qeth_l2_stop(struct net_device *dev) | |||
824 | 862 | ||
825 | QETH_CARD_TEXT(card, 4, "qethstop"); | 863 | QETH_CARD_TEXT(card, 4, "qethstop"); |
826 | netif_tx_disable(dev); | 864 | netif_tx_disable(dev); |
827 | if (card->state == CARD_STATE_UP) | 865 | if (card->state == CARD_STATE_UP) { |
828 | card->state = CARD_STATE_SOFTSETUP; | 866 | card->state = CARD_STATE_SOFTSETUP; |
867 | napi_disable(&card->napi); | ||
868 | } | ||
829 | return 0; | 869 | return 0; |
830 | } | 870 | } |
831 | 871 | ||
@@ -836,8 +876,10 @@ static int qeth_l2_probe_device(struct ccwgroup_device *gdev) | |||
836 | INIT_LIST_HEAD(&card->vid_list); | 876 | INIT_LIST_HEAD(&card->vid_list); |
837 | INIT_LIST_HEAD(&card->mc_list); | 877 | INIT_LIST_HEAD(&card->mc_list); |
838 | card->options.layer2 = 1; | 878 | card->options.layer2 = 1; |
879 | card->info.hwtrap = 0; | ||
880 | card->discipline.start_poll = qeth_qdio_start_poll; | ||
839 | card->discipline.input_handler = (qdio_handler_t *) | 881 | card->discipline.input_handler = (qdio_handler_t *) |
840 | qeth_l2_qdio_input_handler; | 882 | qeth_qdio_input_handler; |
841 | card->discipline.output_handler = (qdio_handler_t *) | 883 | card->discipline.output_handler = (qdio_handler_t *) |
842 | qeth_qdio_output_handler; | 884 | qeth_qdio_output_handler; |
843 | card->discipline.recover = qeth_l2_recover; | 885 | card->discipline.recover = qeth_l2_recover; |
@@ -851,10 +893,8 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev) | |||
851 | qeth_set_allowed_threads(card, 0, 1); | 893 | qeth_set_allowed_threads(card, 0, 1); |
852 | wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0); | 894 | wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0); |
853 | 895 | ||
854 | if (cgdev->state == CCWGROUP_ONLINE) { | 896 | if (cgdev->state == CCWGROUP_ONLINE) |
855 | card->use_hard_stop = 1; | ||
856 | qeth_l2_set_offline(cgdev); | 897 | qeth_l2_set_offline(cgdev); |
857 | } | ||
858 | 898 | ||
859 | if (card->dev) { | 899 | if (card->dev) { |
860 | unregister_netdev(card->dev); | 900 | unregister_netdev(card->dev); |
@@ -923,6 +963,7 @@ static int qeth_l2_setup_netdev(struct qeth_card *card) | |||
923 | card->info.broadcast_capable = 1; | 963 | card->info.broadcast_capable = 1; |
924 | qeth_l2_request_initial_mac(card); | 964 | qeth_l2_request_initial_mac(card); |
925 | SET_NETDEV_DEV(card->dev, &card->gdev->dev); | 965 | SET_NETDEV_DEV(card->dev, &card->gdev->dev); |
966 | netif_napi_add(card->dev, &card->napi, qeth_l2_poll, QETH_NAPI_WEIGHT); | ||
926 | return register_netdev(card->dev); | 967 | return register_netdev(card->dev); |
927 | } | 968 | } |
928 | 969 | ||
@@ -954,7 +995,15 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
954 | if (card->info.type != QETH_CARD_TYPE_OSN) | 995 | if (card->info.type != QETH_CARD_TYPE_OSN) |
955 | qeth_l2_send_setmac(card, &card->dev->dev_addr[0]); | 996 | qeth_l2_send_setmac(card, &card->dev->dev_addr[0]); |
956 | 997 | ||
998 | if (qeth_is_diagass_supported(card, QETH_DIAGS_CMD_TRAP)) { | ||
999 | if (card->info.hwtrap && | ||
1000 | qeth_hw_trap(card, QETH_DIAGS_TRAP_ARM)) | ||
1001 | card->info.hwtrap = 0; | ||
1002 | } else | ||
1003 | card->info.hwtrap = 0; | ||
1004 | |||
957 | card->state = CARD_STATE_HARDSETUP; | 1005 | card->state = CARD_STATE_HARDSETUP; |
1006 | memset(&card->rx, 0, sizeof(struct qeth_rx)); | ||
958 | qeth_print_status_message(card); | 1007 | qeth_print_status_message(card); |
959 | 1008 | ||
960 | /* softsetup */ | 1009 | /* softsetup */ |
@@ -967,13 +1016,14 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
967 | dev_warn(&card->gdev->dev, | 1016 | dev_warn(&card->gdev->dev, |
968 | "The LAN is offline\n"); | 1017 | "The LAN is offline\n"); |
969 | card->lan_online = 0; | 1018 | card->lan_online = 0; |
970 | goto out; | 1019 | goto contin; |
971 | } | 1020 | } |
972 | rc = -ENODEV; | 1021 | rc = -ENODEV; |
973 | goto out_remove; | 1022 | goto out_remove; |
974 | } else | 1023 | } else |
975 | card->lan_online = 1; | 1024 | card->lan_online = 1; |
976 | 1025 | ||
1026 | contin: | ||
977 | if ((card->info.type == QETH_CARD_TYPE_OSD) || | 1027 | if ((card->info.type == QETH_CARD_TYPE_OSD) || |
978 | (card->info.type == QETH_CARD_TYPE_OSX)) | 1028 | (card->info.type == QETH_CARD_TYPE_OSX)) |
979 | /* configure isolation level */ | 1029 | /* configure isolation level */ |
@@ -981,7 +1031,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
981 | 1031 | ||
982 | if (card->info.type != QETH_CARD_TYPE_OSN && | 1032 | if (card->info.type != QETH_CARD_TYPE_OSN && |
983 | card->info.type != QETH_CARD_TYPE_OSM) | 1033 | card->info.type != QETH_CARD_TYPE_OSM) |
984 | qeth_l2_process_vlans(card, 0); | 1034 | qeth_l2_process_vlans(card); |
985 | 1035 | ||
986 | netif_tx_disable(card->dev); | 1036 | netif_tx_disable(card->dev); |
987 | 1037 | ||
@@ -992,13 +1042,16 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
992 | goto out_remove; | 1042 | goto out_remove; |
993 | } | 1043 | } |
994 | card->state = CARD_STATE_SOFTSETUP; | 1044 | card->state = CARD_STATE_SOFTSETUP; |
995 | netif_carrier_on(card->dev); | 1045 | if (card->lan_online) |
1046 | netif_carrier_on(card->dev); | ||
1047 | else | ||
1048 | netif_carrier_off(card->dev); | ||
996 | 1049 | ||
997 | qeth_set_allowed_threads(card, 0xffffffff, 0); | 1050 | qeth_set_allowed_threads(card, 0xffffffff, 0); |
998 | if (recover_flag == CARD_STATE_RECOVER) { | 1051 | if (recover_flag == CARD_STATE_RECOVER) { |
999 | if (recovery_mode && | 1052 | if (recovery_mode && |
1000 | card->info.type != QETH_CARD_TYPE_OSN) { | 1053 | card->info.type != QETH_CARD_TYPE_OSN) { |
1001 | qeth_l2_open(card->dev); | 1054 | __qeth_l2_open(card->dev); |
1002 | } else { | 1055 | } else { |
1003 | rtnl_lock(); | 1056 | rtnl_lock(); |
1004 | dev_open(card->dev); | 1057 | dev_open(card->dev); |
@@ -1009,13 +1062,11 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
1009 | } | 1062 | } |
1010 | /* let user_space know that device is online */ | 1063 | /* let user_space know that device is online */ |
1011 | kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE); | 1064 | kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE); |
1012 | out: | ||
1013 | mutex_unlock(&card->conf_mutex); | 1065 | mutex_unlock(&card->conf_mutex); |
1014 | mutex_unlock(&card->discipline_mutex); | 1066 | mutex_unlock(&card->discipline_mutex); |
1015 | return 0; | 1067 | return 0; |
1016 | 1068 | ||
1017 | out_remove: | 1069 | out_remove: |
1018 | card->use_hard_stop = 1; | ||
1019 | qeth_l2_stop_card(card, 0); | 1070 | qeth_l2_stop_card(card, 0); |
1020 | ccw_device_set_offline(CARD_DDEV(card)); | 1071 | ccw_device_set_offline(CARD_DDEV(card)); |
1021 | ccw_device_set_offline(CARD_WDEV(card)); | 1072 | ccw_device_set_offline(CARD_WDEV(card)); |
@@ -1049,6 +1100,10 @@ static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev, | |||
1049 | if (card->dev && netif_carrier_ok(card->dev)) | 1100 | if (card->dev && netif_carrier_ok(card->dev)) |
1050 | netif_carrier_off(card->dev); | 1101 | netif_carrier_off(card->dev); |
1051 | recover_flag = card->state; | 1102 | recover_flag = card->state; |
1103 | if ((!recovery_mode && card->info.hwtrap) || card->info.hwtrap == 2) { | ||
1104 | qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); | ||
1105 | card->info.hwtrap = 1; | ||
1106 | } | ||
1052 | qeth_l2_stop_card(card, recovery_mode); | 1107 | qeth_l2_stop_card(card, recovery_mode); |
1053 | rc = ccw_device_set_offline(CARD_DDEV(card)); | 1108 | rc = ccw_device_set_offline(CARD_DDEV(card)); |
1054 | rc2 = ccw_device_set_offline(CARD_WDEV(card)); | 1109 | rc2 = ccw_device_set_offline(CARD_WDEV(card)); |
@@ -1083,12 +1138,8 @@ static int qeth_l2_recover(void *ptr) | |||
1083 | QETH_CARD_TEXT(card, 2, "recover2"); | 1138 | QETH_CARD_TEXT(card, 2, "recover2"); |
1084 | dev_warn(&card->gdev->dev, | 1139 | dev_warn(&card->gdev->dev, |
1085 | "A recovery process has been started for the device\n"); | 1140 | "A recovery process has been started for the device\n"); |
1086 | card->use_hard_stop = 1; | ||
1087 | __qeth_l2_set_offline(card->gdev, 1); | 1141 | __qeth_l2_set_offline(card->gdev, 1); |
1088 | rc = __qeth_l2_set_online(card->gdev, 1); | 1142 | rc = __qeth_l2_set_online(card->gdev, 1); |
1089 | /* don't run another scheduled recovery */ | ||
1090 | qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD); | ||
1091 | qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD); | ||
1092 | if (!rc) | 1143 | if (!rc) |
1093 | dev_info(&card->gdev->dev, | 1144 | dev_info(&card->gdev->dev, |
1094 | "Device successfully recovered!\n"); | 1145 | "Device successfully recovered!\n"); |
@@ -1099,6 +1150,8 @@ static int qeth_l2_recover(void *ptr) | |||
1099 | dev_warn(&card->gdev->dev, "The qeth device driver " | 1150 | dev_warn(&card->gdev->dev, "The qeth device driver " |
1100 | "failed to recover an error on the device\n"); | 1151 | "failed to recover an error on the device\n"); |
1101 | } | 1152 | } |
1153 | qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD); | ||
1154 | qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD); | ||
1102 | return 0; | 1155 | return 0; |
1103 | } | 1156 | } |
1104 | 1157 | ||
@@ -1116,6 +1169,8 @@ static void __exit qeth_l2_exit(void) | |||
1116 | static void qeth_l2_shutdown(struct ccwgroup_device *gdev) | 1169 | static void qeth_l2_shutdown(struct ccwgroup_device *gdev) |
1117 | { | 1170 | { |
1118 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); | 1171 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); |
1172 | if ((gdev->state == CCWGROUP_ONLINE) && card->info.hwtrap) | ||
1173 | qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); | ||
1119 | qeth_qdio_clear_card(card, 0); | 1174 | qeth_qdio_clear_card(card, 0); |
1120 | qeth_clear_qdio_buffers(card); | 1175 | qeth_clear_qdio_buffers(card); |
1121 | } | 1176 | } |
@@ -1131,7 +1186,8 @@ static int qeth_l2_pm_suspend(struct ccwgroup_device *gdev) | |||
1131 | if (gdev->state == CCWGROUP_OFFLINE) | 1186 | if (gdev->state == CCWGROUP_OFFLINE) |
1132 | return 0; | 1187 | return 0; |
1133 | if (card->state == CARD_STATE_UP) { | 1188 | if (card->state == CARD_STATE_UP) { |
1134 | card->use_hard_stop = 1; | 1189 | if (card->info.hwtrap) |
1190 | qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); | ||
1135 | __qeth_l2_set_offline(card->gdev, 1); | 1191 | __qeth_l2_set_offline(card->gdev, 1); |
1136 | } else | 1192 | } else |
1137 | __qeth_l2_set_offline(card->gdev, 0); | 1193 | __qeth_l2_set_offline(card->gdev, 0); |
diff --git a/drivers/s390/net/qeth_l3.h b/drivers/s390/net/qeth_l3.h index e705b27ec7dc..14a43aeb0c2a 100644 --- a/drivers/s390/net/qeth_l3.h +++ b/drivers/s390/net/qeth_l3.h | |||
@@ -62,8 +62,6 @@ void qeth_l3_del_vipa(struct qeth_card *, enum qeth_prot_versions, const u8 *); | |||
62 | int qeth_l3_add_rxip(struct qeth_card *, enum qeth_prot_versions, const u8 *); | 62 | int qeth_l3_add_rxip(struct qeth_card *, enum qeth_prot_versions, const u8 *); |
63 | void qeth_l3_del_rxip(struct qeth_card *card, enum qeth_prot_versions, | 63 | void qeth_l3_del_rxip(struct qeth_card *card, enum qeth_prot_versions, |
64 | const u8 *); | 64 | const u8 *); |
65 | int qeth_l3_set_large_send(struct qeth_card *, enum qeth_large_send_types); | ||
66 | int qeth_l3_set_rx_csum(struct qeth_card *, enum qeth_checksum_types); | ||
67 | int qeth_l3_is_addr_covered_by_ipato(struct qeth_card *, struct qeth_ipaddr *); | 65 | int qeth_l3_is_addr_covered_by_ipato(struct qeth_card *, struct qeth_ipaddr *); |
68 | 66 | ||
69 | #endif /* __QETH_L3_H__ */ | 67 | #endif /* __QETH_L3_H__ */ |
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index e22ae248f613..fd69da3fa6b4 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c | |||
@@ -30,6 +30,7 @@ | |||
30 | 30 | ||
31 | #include "qeth_l3.h" | 31 | #include "qeth_l3.h" |
32 | 32 | ||
33 | |||
33 | static int qeth_l3_set_offline(struct ccwgroup_device *); | 34 | static int qeth_l3_set_offline(struct ccwgroup_device *); |
34 | static int qeth_l3_recover(void *); | 35 | static int qeth_l3_recover(void *); |
35 | static int qeth_l3_stop(struct net_device *); | 36 | static int qeth_l3_stop(struct net_device *); |
@@ -42,33 +43,6 @@ static int qeth_l3_deregister_addr_entry(struct qeth_card *, | |||
42 | static int __qeth_l3_set_online(struct ccwgroup_device *, int); | 43 | static int __qeth_l3_set_online(struct ccwgroup_device *, int); |
43 | static int __qeth_l3_set_offline(struct ccwgroup_device *, int); | 44 | static int __qeth_l3_set_offline(struct ccwgroup_device *, int); |
44 | 45 | ||
45 | int qeth_l3_set_large_send(struct qeth_card *card, | ||
46 | enum qeth_large_send_types type) | ||
47 | { | ||
48 | int rc = 0; | ||
49 | |||
50 | card->options.large_send = type; | ||
51 | if (card->dev == NULL) | ||
52 | return 0; | ||
53 | |||
54 | if (card->options.large_send == QETH_LARGE_SEND_TSO) { | ||
55 | if (qeth_is_supported(card, IPA_OUTBOUND_TSO)) { | ||
56 | card->dev->features |= NETIF_F_TSO | NETIF_F_SG | | ||
57 | NETIF_F_IP_CSUM; | ||
58 | } else { | ||
59 | card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG | | ||
60 | NETIF_F_IP_CSUM); | ||
61 | card->options.large_send = QETH_LARGE_SEND_NO; | ||
62 | rc = -EOPNOTSUPP; | ||
63 | } | ||
64 | } else { | ||
65 | card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG | | ||
66 | NETIF_F_IP_CSUM); | ||
67 | card->options.large_send = QETH_LARGE_SEND_NO; | ||
68 | } | ||
69 | return rc; | ||
70 | } | ||
71 | |||
72 | static int qeth_l3_isxdigit(char *buf) | 46 | static int qeth_l3_isxdigit(char *buf) |
73 | { | 47 | { |
74 | while (*buf) { | 48 | while (*buf) { |
@@ -103,12 +77,7 @@ int qeth_l3_string_to_ipaddr4(const char *buf, __u8 *addr) | |||
103 | 77 | ||
104 | void qeth_l3_ipaddr6_to_string(const __u8 *addr, char *buf) | 78 | void qeth_l3_ipaddr6_to_string(const __u8 *addr, char *buf) |
105 | { | 79 | { |
106 | sprintf(buf, "%02x%02x:%02x%02x:%02x%02x:%02x%02x" | 80 | sprintf(buf, "%pI6", addr); |
107 | ":%02x%02x:%02x%02x:%02x%02x:%02x%02x", | ||
108 | addr[0], addr[1], addr[2], addr[3], | ||
109 | addr[4], addr[5], addr[6], addr[7], | ||
110 | addr[8], addr[9], addr[10], addr[11], | ||
111 | addr[12], addr[13], addr[14], addr[15]); | ||
112 | } | 81 | } |
113 | 82 | ||
114 | int qeth_l3_string_to_ipaddr6(const char *buf, __u8 *addr) | 83 | int qeth_l3_string_to_ipaddr6(const char *buf, __u8 *addr) |
@@ -460,8 +429,11 @@ static void qeth_l3_set_ip_addr_list(struct qeth_card *card) | |||
460 | QETH_CARD_TEXT(card, 2, "sdiplist"); | 429 | QETH_CARD_TEXT(card, 2, "sdiplist"); |
461 | QETH_CARD_HEX(card, 2, &card, sizeof(void *)); | 430 | QETH_CARD_HEX(card, 2, &card, sizeof(void *)); |
462 | 431 | ||
463 | if (card->options.sniffer) | 432 | if ((card->state != CARD_STATE_UP && |
433 | card->state != CARD_STATE_SOFTSETUP) || card->options.sniffer) { | ||
464 | return; | 434 | return; |
435 | } | ||
436 | |||
465 | spin_lock_irqsave(&card->ip_lock, flags); | 437 | spin_lock_irqsave(&card->ip_lock, flags); |
466 | tbd_list = card->ip_tbd_list; | 438 | tbd_list = card->ip_tbd_list; |
467 | card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_ATOMIC); | 439 | card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_ATOMIC); |
@@ -511,8 +483,7 @@ static void qeth_l3_set_ip_addr_list(struct qeth_card *card) | |||
511 | kfree(tbd_list); | 483 | kfree(tbd_list); |
512 | } | 484 | } |
513 | 485 | ||
514 | static void qeth_l3_clear_ip_list(struct qeth_card *card, int clean, | 486 | static void qeth_l3_clear_ip_list(struct qeth_card *card, int recover) |
515 | int recover) | ||
516 | { | 487 | { |
517 | struct qeth_ipaddr *addr, *tmp; | 488 | struct qeth_ipaddr *addr, *tmp; |
518 | unsigned long flags; | 489 | unsigned long flags; |
@@ -531,11 +502,6 @@ static void qeth_l3_clear_ip_list(struct qeth_card *card, int clean, | |||
531 | addr = list_entry(card->ip_list.next, | 502 | addr = list_entry(card->ip_list.next, |
532 | struct qeth_ipaddr, entry); | 503 | struct qeth_ipaddr, entry); |
533 | list_del_init(&addr->entry); | 504 | list_del_init(&addr->entry); |
534 | if (clean) { | ||
535 | spin_unlock_irqrestore(&card->ip_lock, flags); | ||
536 | qeth_l3_deregister_addr_entry(card, addr); | ||
537 | spin_lock_irqsave(&card->ip_lock, flags); | ||
538 | } | ||
539 | if (!recover || addr->is_multicast) { | 505 | if (!recover || addr->is_multicast) { |
540 | kfree(addr); | 506 | kfree(addr); |
541 | continue; | 507 | continue; |
@@ -1311,39 +1277,6 @@ static int qeth_l3_start_ipa_multicast(struct qeth_card *card) | |||
1311 | return rc; | 1277 | return rc; |
1312 | } | 1278 | } |
1313 | 1279 | ||
1314 | static int qeth_l3_query_ipassists_cb(struct qeth_card *card, | ||
1315 | struct qeth_reply *reply, unsigned long data) | ||
1316 | { | ||
1317 | struct qeth_ipa_cmd *cmd; | ||
1318 | |||
1319 | QETH_DBF_TEXT(SETUP, 2, "qipasscb"); | ||
1320 | |||
1321 | cmd = (struct qeth_ipa_cmd *) data; | ||
1322 | if (cmd->hdr.prot_version == QETH_PROT_IPV4) { | ||
1323 | card->options.ipa4.supported_funcs = cmd->hdr.ipa_supported; | ||
1324 | card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled; | ||
1325 | } else { | ||
1326 | card->options.ipa6.supported_funcs = cmd->hdr.ipa_supported; | ||
1327 | card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled; | ||
1328 | } | ||
1329 | QETH_DBF_TEXT(SETUP, 2, "suppenbl"); | ||
1330 | QETH_DBF_TEXT_(SETUP, 2, "%x", cmd->hdr.ipa_supported); | ||
1331 | QETH_DBF_TEXT_(SETUP, 2, "%x", cmd->hdr.ipa_enabled); | ||
1332 | return 0; | ||
1333 | } | ||
1334 | |||
1335 | static int qeth_l3_query_ipassists(struct qeth_card *card, | ||
1336 | enum qeth_prot_versions prot) | ||
1337 | { | ||
1338 | int rc; | ||
1339 | struct qeth_cmd_buffer *iob; | ||
1340 | |||
1341 | QETH_DBF_TEXT_(SETUP, 2, "qipassi%i", prot); | ||
1342 | iob = qeth_get_ipacmd_buffer(card, IPA_CMD_QIPASSIST, prot); | ||
1343 | rc = qeth_send_ipa_cmd(card, iob, qeth_l3_query_ipassists_cb, NULL); | ||
1344 | return rc; | ||
1345 | } | ||
1346 | |||
1347 | #ifdef CONFIG_QETH_IPV6 | 1280 | #ifdef CONFIG_QETH_IPV6 |
1348 | static int qeth_l3_softsetup_ipv6(struct qeth_card *card) | 1281 | static int qeth_l3_softsetup_ipv6(struct qeth_card *card) |
1349 | { | 1282 | { |
@@ -1354,7 +1287,7 @@ static int qeth_l3_softsetup_ipv6(struct qeth_card *card) | |||
1354 | if (card->info.type == QETH_CARD_TYPE_IQD) | 1287 | if (card->info.type == QETH_CARD_TYPE_IQD) |
1355 | goto out; | 1288 | goto out; |
1356 | 1289 | ||
1357 | rc = qeth_l3_query_ipassists(card, QETH_PROT_IPV6); | 1290 | rc = qeth_query_ipassists(card, QETH_PROT_IPV6); |
1358 | if (rc) { | 1291 | if (rc) { |
1359 | dev_err(&card->gdev->dev, | 1292 | dev_err(&card->gdev->dev, |
1360 | "Activating IPv6 support for %s failed\n", | 1293 | "Activating IPv6 support for %s failed\n", |
@@ -1479,68 +1412,38 @@ static int qeth_l3_send_checksum_command(struct qeth_card *card) | |||
1479 | return 0; | 1412 | return 0; |
1480 | } | 1413 | } |
1481 | 1414 | ||
1482 | int qeth_l3_set_rx_csum(struct qeth_card *card, | 1415 | int qeth_l3_set_rx_csum(struct qeth_card *card, int on) |
1483 | enum qeth_checksum_types csum_type) | ||
1484 | { | 1416 | { |
1485 | int rc = 0; | 1417 | int rc = 0; |
1486 | 1418 | ||
1487 | if (card->options.checksum_type == HW_CHECKSUMMING) { | 1419 | if (on) { |
1488 | if ((csum_type != HW_CHECKSUMMING) && | 1420 | rc = qeth_l3_send_checksum_command(card); |
1489 | (card->state != CARD_STATE_DOWN)) { | 1421 | if (rc) |
1490 | rc = qeth_l3_send_simple_setassparms(card, | 1422 | return -EIO; |
1491 | IPA_INBOUND_CHECKSUM, IPA_CMD_ASS_STOP, 0); | 1423 | dev_info(&card->gdev->dev, |
1492 | if (rc) | 1424 | "HW Checksumming (inbound) enabled\n"); |
1493 | return -EIO; | ||
1494 | } | ||
1495 | } else { | 1425 | } else { |
1496 | if (csum_type == HW_CHECKSUMMING) { | 1426 | rc = qeth_l3_send_simple_setassparms(card, |
1497 | if (card->state != CARD_STATE_DOWN) { | 1427 | IPA_INBOUND_CHECKSUM, IPA_CMD_ASS_STOP, 0); |
1498 | if (!qeth_is_supported(card, | 1428 | if (rc) |
1499 | IPA_INBOUND_CHECKSUM)) | 1429 | return -EIO; |
1500 | return -EPERM; | ||
1501 | rc = qeth_l3_send_checksum_command(card); | ||
1502 | if (rc) | ||
1503 | return -EIO; | ||
1504 | } | ||
1505 | } | ||
1506 | } | 1430 | } |
1507 | card->options.checksum_type = csum_type; | 1431 | |
1508 | return rc; | 1432 | return 0; |
1509 | } | 1433 | } |
1510 | 1434 | ||
1511 | static int qeth_l3_start_ipa_checksum(struct qeth_card *card) | 1435 | static int qeth_l3_start_ipa_checksum(struct qeth_card *card) |
1512 | { | 1436 | { |
1513 | int rc = 0; | ||
1514 | |||
1515 | QETH_CARD_TEXT(card, 3, "strtcsum"); | 1437 | QETH_CARD_TEXT(card, 3, "strtcsum"); |
1516 | 1438 | ||
1517 | if (card->options.checksum_type == NO_CHECKSUMMING) { | 1439 | if (card->dev->features & NETIF_F_RXCSUM) { |
1518 | dev_info(&card->gdev->dev, | 1440 | rtnl_lock(); |
1519 | "Using no checksumming on %s.\n", | 1441 | /* force set_features call */ |
1520 | QETH_CARD_IFNAME(card)); | 1442 | card->dev->features &= ~NETIF_F_RXCSUM; |
1521 | return 0; | 1443 | netdev_update_features(card->dev); |
1522 | } | 1444 | rtnl_unlock(); |
1523 | if (card->options.checksum_type == SW_CHECKSUMMING) { | ||
1524 | dev_info(&card->gdev->dev, | ||
1525 | "Using SW checksumming on %s.\n", | ||
1526 | QETH_CARD_IFNAME(card)); | ||
1527 | return 0; | ||
1528 | } | ||
1529 | if (!qeth_is_supported(card, IPA_INBOUND_CHECKSUM)) { | ||
1530 | dev_info(&card->gdev->dev, | ||
1531 | "Inbound HW Checksumming not " | ||
1532 | "supported on %s,\ncontinuing " | ||
1533 | "using Inbound SW Checksumming\n", | ||
1534 | QETH_CARD_IFNAME(card)); | ||
1535 | card->options.checksum_type = SW_CHECKSUMMING; | ||
1536 | return 0; | ||
1537 | } | 1445 | } |
1538 | rc = qeth_l3_send_checksum_command(card); | 1446 | return 0; |
1539 | if (!rc) | ||
1540 | dev_info(&card->gdev->dev, | ||
1541 | "HW Checksumming (inbound) enabled\n"); | ||
1542 | |||
1543 | return rc; | ||
1544 | } | 1447 | } |
1545 | 1448 | ||
1546 | static int qeth_l3_start_ipa_tx_checksum(struct qeth_card *card) | 1449 | static int qeth_l3_start_ipa_tx_checksum(struct qeth_card *card) |
@@ -1587,10 +1490,8 @@ static int qeth_l3_start_ipa_tso(struct qeth_card *card) | |||
1587 | dev_info(&card->gdev->dev, | 1490 | dev_info(&card->gdev->dev, |
1588 | "Outbound TSO enabled\n"); | 1491 | "Outbound TSO enabled\n"); |
1589 | } | 1492 | } |
1590 | if (rc && (card->options.large_send == QETH_LARGE_SEND_TSO)) { | 1493 | if (rc) |
1591 | card->options.large_send = QETH_LARGE_SEND_NO; | 1494 | card->dev->features &= ~NETIF_F_TSO; |
1592 | card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG); | ||
1593 | } | ||
1594 | return rc; | 1495 | return rc; |
1595 | } | 1496 | } |
1596 | 1497 | ||
@@ -1612,29 +1513,6 @@ static int qeth_l3_start_ipassists(struct qeth_card *card) | |||
1612 | return 0; | 1513 | return 0; |
1613 | } | 1514 | } |
1614 | 1515 | ||
1615 | static int qeth_l3_put_unique_id(struct qeth_card *card) | ||
1616 | { | ||
1617 | |||
1618 | int rc = 0; | ||
1619 | struct qeth_cmd_buffer *iob; | ||
1620 | struct qeth_ipa_cmd *cmd; | ||
1621 | |||
1622 | QETH_CARD_TEXT(card, 2, "puniqeid"); | ||
1623 | |||
1624 | if ((card->info.unique_id & UNIQUE_ID_NOT_BY_CARD) == | ||
1625 | UNIQUE_ID_NOT_BY_CARD) | ||
1626 | return -1; | ||
1627 | iob = qeth_get_ipacmd_buffer(card, IPA_CMD_DESTROY_ADDR, | ||
1628 | QETH_PROT_IPV6); | ||
1629 | cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); | ||
1630 | *((__u16 *) &cmd->data.create_destroy_addr.unique_id[6]) = | ||
1631 | card->info.unique_id; | ||
1632 | memcpy(&cmd->data.create_destroy_addr.unique_id[0], | ||
1633 | card->dev->dev_addr, OSA_ADDR_LEN); | ||
1634 | rc = qeth_send_ipa_cmd(card, iob, NULL, NULL); | ||
1635 | return rc; | ||
1636 | } | ||
1637 | |||
1638 | static int qeth_l3_iqd_read_initial_mac_cb(struct qeth_card *card, | 1516 | static int qeth_l3_iqd_read_initial_mac_cb(struct qeth_card *card, |
1639 | struct qeth_reply *reply, unsigned long data) | 1517 | struct qeth_reply *reply, unsigned long data) |
1640 | { | 1518 | { |
@@ -1801,7 +1679,8 @@ static void qeth_l3_add_mc(struct qeth_card *card, struct in_device *in4_dev) | |||
1801 | char buf[MAX_ADDR_LEN]; | 1679 | char buf[MAX_ADDR_LEN]; |
1802 | 1680 | ||
1803 | QETH_CARD_TEXT(card, 4, "addmc"); | 1681 | QETH_CARD_TEXT(card, 4, "addmc"); |
1804 | for (im4 = in4_dev->mc_list; im4; im4 = im4->next) { | 1682 | for (im4 = rcu_dereference(in4_dev->mc_list); im4 != NULL; |
1683 | im4 = rcu_dereference(im4->next_rcu)) { | ||
1805 | qeth_l3_get_mac_for_ipm(im4->multiaddr, buf, in4_dev->dev); | 1684 | qeth_l3_get_mac_for_ipm(im4->multiaddr, buf, in4_dev->dev); |
1806 | ipm = qeth_l3_get_addr_buffer(QETH_PROT_IPV4); | 1685 | ipm = qeth_l3_get_addr_buffer(QETH_PROT_IPV4); |
1807 | if (!ipm) | 1686 | if (!ipm) |
@@ -1825,7 +1704,7 @@ static void qeth_l3_add_vlan_mc(struct qeth_card *card) | |||
1825 | return; | 1704 | return; |
1826 | 1705 | ||
1827 | vg = card->vlangrp; | 1706 | vg = card->vlangrp; |
1828 | for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { | 1707 | for (i = 0; i < VLAN_N_VID; i++) { |
1829 | struct net_device *netdev = vlan_group_get_device(vg, i); | 1708 | struct net_device *netdev = vlan_group_get_device(vg, i); |
1830 | if (netdev == NULL || | 1709 | if (netdev == NULL || |
1831 | !(netdev->flags & IFF_UP)) | 1710 | !(netdev->flags & IFF_UP)) |
@@ -1833,9 +1712,9 @@ static void qeth_l3_add_vlan_mc(struct qeth_card *card) | |||
1833 | in_dev = in_dev_get(netdev); | 1712 | in_dev = in_dev_get(netdev); |
1834 | if (!in_dev) | 1713 | if (!in_dev) |
1835 | continue; | 1714 | continue; |
1836 | read_lock(&in_dev->mc_list_lock); | 1715 | rcu_read_lock(); |
1837 | qeth_l3_add_mc(card, in_dev); | 1716 | qeth_l3_add_mc(card, in_dev); |
1838 | read_unlock(&in_dev->mc_list_lock); | 1717 | rcu_read_unlock(); |
1839 | in_dev_put(in_dev); | 1718 | in_dev_put(in_dev); |
1840 | } | 1719 | } |
1841 | } | 1720 | } |
@@ -1848,10 +1727,10 @@ static void qeth_l3_add_multicast_ipv4(struct qeth_card *card) | |||
1848 | in4_dev = in_dev_get(card->dev); | 1727 | in4_dev = in_dev_get(card->dev); |
1849 | if (in4_dev == NULL) | 1728 | if (in4_dev == NULL) |
1850 | return; | 1729 | return; |
1851 | read_lock(&in4_dev->mc_list_lock); | 1730 | rcu_read_lock(); |
1852 | qeth_l3_add_mc(card, in4_dev); | 1731 | qeth_l3_add_mc(card, in4_dev); |
1853 | qeth_l3_add_vlan_mc(card); | 1732 | qeth_l3_add_vlan_mc(card); |
1854 | read_unlock(&in4_dev->mc_list_lock); | 1733 | rcu_read_unlock(); |
1855 | in_dev_put(in4_dev); | 1734 | in_dev_put(in4_dev); |
1856 | } | 1735 | } |
1857 | 1736 | ||
@@ -1888,7 +1767,7 @@ static void qeth_l3_add_vlan_mc6(struct qeth_card *card) | |||
1888 | return; | 1767 | return; |
1889 | 1768 | ||
1890 | vg = card->vlangrp; | 1769 | vg = card->vlangrp; |
1891 | for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { | 1770 | for (i = 0; i < VLAN_N_VID; i++) { |
1892 | struct net_device *netdev = vlan_group_get_device(vg, i); | 1771 | struct net_device *netdev = vlan_group_get_device(vg, i); |
1893 | if (netdev == NULL || | 1772 | if (netdev == NULL || |
1894 | !(netdev->flags & IFF_UP)) | 1773 | !(netdev->flags & IFF_UP)) |
@@ -2018,13 +1897,14 @@ static void qeth_l3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) | |||
2018 | qeth_l3_set_multicast_list(card->dev); | 1897 | qeth_l3_set_multicast_list(card->dev); |
2019 | } | 1898 | } |
2020 | 1899 | ||
2021 | static inline __u16 qeth_l3_rebuild_skb(struct qeth_card *card, | 1900 | static inline int qeth_l3_rebuild_skb(struct qeth_card *card, |
2022 | struct sk_buff *skb, struct qeth_hdr *hdr) | 1901 | struct sk_buff *skb, struct qeth_hdr *hdr, |
1902 | unsigned short *vlan_id) | ||
2023 | { | 1903 | { |
2024 | unsigned short vlan_id = 0; | ||
2025 | __be16 prot; | 1904 | __be16 prot; |
2026 | struct iphdr *ip_hdr; | 1905 | struct iphdr *ip_hdr; |
2027 | unsigned char tg_addr[MAX_ADDR_LEN]; | 1906 | unsigned char tg_addr[MAX_ADDR_LEN]; |
1907 | int is_vlan = 0; | ||
2028 | 1908 | ||
2029 | if (!(hdr->hdr.l3.flags & QETH_HDR_PASSTHRU)) { | 1909 | if (!(hdr->hdr.l3.flags & QETH_HDR_PASSTHRU)) { |
2030 | prot = htons((hdr->hdr.l3.flags & QETH_HDR_IPV6)? ETH_P_IPV6 : | 1910 | prot = htons((hdr->hdr.l3.flags & QETH_HDR_IPV6)? ETH_P_IPV6 : |
@@ -2087,18 +1967,12 @@ static inline __u16 qeth_l3_rebuild_skb(struct qeth_card *card, | |||
2087 | 1967 | ||
2088 | if (hdr->hdr.l3.ext_flags & | 1968 | if (hdr->hdr.l3.ext_flags & |
2089 | (QETH_HDR_EXT_VLAN_FRAME | QETH_HDR_EXT_INCLUDE_VLAN_TAG)) { | 1969 | (QETH_HDR_EXT_VLAN_FRAME | QETH_HDR_EXT_INCLUDE_VLAN_TAG)) { |
2090 | vlan_id = (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_VLAN_FRAME)? | 1970 | *vlan_id = (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_VLAN_FRAME) ? |
2091 | hdr->hdr.l3.vlan_id : *((u16 *)&hdr->hdr.l3.dest_addr[12]); | 1971 | hdr->hdr.l3.vlan_id : *((u16 *)&hdr->hdr.l3.dest_addr[12]); |
1972 | is_vlan = 1; | ||
2092 | } | 1973 | } |
2093 | 1974 | ||
2094 | switch (card->options.checksum_type) { | 1975 | if (card->dev->features & NETIF_F_RXCSUM) { |
2095 | case SW_CHECKSUMMING: | ||
2096 | skb->ip_summed = CHECKSUM_NONE; | ||
2097 | break; | ||
2098 | case NO_CHECKSUMMING: | ||
2099 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
2100 | break; | ||
2101 | case HW_CHECKSUMMING: | ||
2102 | if ((hdr->hdr.l3.ext_flags & | 1976 | if ((hdr->hdr.l3.ext_flags & |
2103 | (QETH_HDR_EXT_CSUM_HDR_REQ | | 1977 | (QETH_HDR_EXT_CSUM_HDR_REQ | |
2104 | QETH_HDR_EXT_CSUM_TRANSP_REQ)) == | 1978 | QETH_HDR_EXT_CSUM_TRANSP_REQ)) == |
@@ -2107,56 +1981,47 @@ static inline __u16 qeth_l3_rebuild_skb(struct qeth_card *card, | |||
2107 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 1981 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
2108 | else | 1982 | else |
2109 | skb->ip_summed = CHECKSUM_NONE; | 1983 | skb->ip_summed = CHECKSUM_NONE; |
2110 | } | 1984 | } else |
1985 | skb->ip_summed = CHECKSUM_NONE; | ||
2111 | 1986 | ||
2112 | return vlan_id; | 1987 | return is_vlan; |
2113 | } | 1988 | } |
2114 | 1989 | ||
2115 | static void qeth_l3_process_inbound_buffer(struct qeth_card *card, | 1990 | static int qeth_l3_process_inbound_buffer(struct qeth_card *card, |
2116 | struct qeth_qdio_buffer *buf, int index) | 1991 | int budget, int *done) |
2117 | { | 1992 | { |
2118 | struct qdio_buffer_element *element; | 1993 | int work_done = 0; |
2119 | struct sk_buff *skb; | 1994 | struct sk_buff *skb; |
2120 | struct qeth_hdr *hdr; | 1995 | struct qeth_hdr *hdr; |
2121 | int offset; | ||
2122 | __u16 vlan_tag = 0; | 1996 | __u16 vlan_tag = 0; |
1997 | int is_vlan; | ||
2123 | unsigned int len; | 1998 | unsigned int len; |
2124 | /* get first element of current buffer */ | ||
2125 | element = (struct qdio_buffer_element *)&buf->buffer->element[0]; | ||
2126 | offset = 0; | ||
2127 | if (card->options.performance_stats) | ||
2128 | card->perf_stats.bufs_rec++; | ||
2129 | while ((skb = qeth_core_get_next_skb(card, buf->buffer, &element, | ||
2130 | &offset, &hdr))) { | ||
2131 | skb->dev = card->dev; | ||
2132 | /* is device UP ? */ | ||
2133 | if (!(card->dev->flags & IFF_UP)) { | ||
2134 | dev_kfree_skb_any(skb); | ||
2135 | continue; | ||
2136 | } | ||
2137 | 1999 | ||
2000 | *done = 0; | ||
2001 | BUG_ON(!budget); | ||
2002 | while (budget) { | ||
2003 | skb = qeth_core_get_next_skb(card, | ||
2004 | card->qdio.in_q->bufs[card->rx.b_index].buffer, | ||
2005 | &card->rx.b_element, &card->rx.e_offset, &hdr); | ||
2006 | if (!skb) { | ||
2007 | *done = 1; | ||
2008 | break; | ||
2009 | } | ||
2010 | skb->dev = card->dev; | ||
2138 | switch (hdr->hdr.l3.id) { | 2011 | switch (hdr->hdr.l3.id) { |
2139 | case QETH_HEADER_TYPE_LAYER3: | 2012 | case QETH_HEADER_TYPE_LAYER3: |
2140 | vlan_tag = qeth_l3_rebuild_skb(card, skb, hdr); | 2013 | is_vlan = qeth_l3_rebuild_skb(card, skb, hdr, |
2014 | &vlan_tag); | ||
2141 | len = skb->len; | 2015 | len = skb->len; |
2142 | if (vlan_tag && !card->options.sniffer) | 2016 | if (is_vlan && !card->options.sniffer) |
2143 | if (card->vlangrp) | 2017 | vlan_gro_receive(&card->napi, card->vlangrp, |
2144 | vlan_hwaccel_rx(skb, card->vlangrp, | 2018 | vlan_tag, skb); |
2145 | vlan_tag); | ||
2146 | else { | ||
2147 | dev_kfree_skb_any(skb); | ||
2148 | continue; | ||
2149 | } | ||
2150 | else | 2019 | else |
2151 | netif_rx(skb); | 2020 | napi_gro_receive(&card->napi, skb); |
2152 | break; | 2021 | break; |
2153 | case QETH_HEADER_TYPE_LAYER2: /* for HiperSockets sniffer */ | 2022 | case QETH_HEADER_TYPE_LAYER2: /* for HiperSockets sniffer */ |
2154 | skb->pkt_type = PACKET_HOST; | 2023 | skb->pkt_type = PACKET_HOST; |
2155 | skb->protocol = eth_type_trans(skb, skb->dev); | 2024 | skb->protocol = eth_type_trans(skb, skb->dev); |
2156 | if (card->options.checksum_type == NO_CHECKSUMMING) | ||
2157 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
2158 | else | ||
2159 | skb->ip_summed = CHECKSUM_NONE; | ||
2160 | len = skb->len; | 2025 | len = skb->len; |
2161 | netif_receive_skb(skb); | 2026 | netif_receive_skb(skb); |
2162 | break; | 2027 | break; |
@@ -2166,10 +2031,87 @@ static void qeth_l3_process_inbound_buffer(struct qeth_card *card, | |||
2166 | QETH_DBF_HEX(CTRL, 3, hdr, QETH_DBF_CTRL_LEN); | 2031 | QETH_DBF_HEX(CTRL, 3, hdr, QETH_DBF_CTRL_LEN); |
2167 | continue; | 2032 | continue; |
2168 | } | 2033 | } |
2169 | 2034 | work_done++; | |
2035 | budget--; | ||
2170 | card->stats.rx_packets++; | 2036 | card->stats.rx_packets++; |
2171 | card->stats.rx_bytes += len; | 2037 | card->stats.rx_bytes += len; |
2172 | } | 2038 | } |
2039 | return work_done; | ||
2040 | } | ||
2041 | |||
2042 | static int qeth_l3_poll(struct napi_struct *napi, int budget) | ||
2043 | { | ||
2044 | struct qeth_card *card = container_of(napi, struct qeth_card, napi); | ||
2045 | int work_done = 0; | ||
2046 | struct qeth_qdio_buffer *buffer; | ||
2047 | int done; | ||
2048 | int new_budget = budget; | ||
2049 | |||
2050 | if (card->options.performance_stats) { | ||
2051 | card->perf_stats.inbound_cnt++; | ||
2052 | card->perf_stats.inbound_start_time = qeth_get_micros(); | ||
2053 | } | ||
2054 | |||
2055 | while (1) { | ||
2056 | if (!card->rx.b_count) { | ||
2057 | card->rx.qdio_err = 0; | ||
2058 | card->rx.b_count = qdio_get_next_buffers( | ||
2059 | card->data.ccwdev, 0, &card->rx.b_index, | ||
2060 | &card->rx.qdio_err); | ||
2061 | if (card->rx.b_count <= 0) { | ||
2062 | card->rx.b_count = 0; | ||
2063 | break; | ||
2064 | } | ||
2065 | card->rx.b_element = | ||
2066 | &card->qdio.in_q->bufs[card->rx.b_index] | ||
2067 | .buffer->element[0]; | ||
2068 | card->rx.e_offset = 0; | ||
2069 | } | ||
2070 | |||
2071 | while (card->rx.b_count) { | ||
2072 | buffer = &card->qdio.in_q->bufs[card->rx.b_index]; | ||
2073 | if (!(card->rx.qdio_err && | ||
2074 | qeth_check_qdio_errors(card, buffer->buffer, | ||
2075 | card->rx.qdio_err, "qinerr"))) | ||
2076 | work_done += qeth_l3_process_inbound_buffer( | ||
2077 | card, new_budget, &done); | ||
2078 | else | ||
2079 | done = 1; | ||
2080 | |||
2081 | if (done) { | ||
2082 | if (card->options.performance_stats) | ||
2083 | card->perf_stats.bufs_rec++; | ||
2084 | qeth_put_buffer_pool_entry(card, | ||
2085 | buffer->pool_entry); | ||
2086 | qeth_queue_input_buffer(card, card->rx.b_index); | ||
2087 | card->rx.b_count--; | ||
2088 | if (card->rx.b_count) { | ||
2089 | card->rx.b_index = | ||
2090 | (card->rx.b_index + 1) % | ||
2091 | QDIO_MAX_BUFFERS_PER_Q; | ||
2092 | card->rx.b_element = | ||
2093 | &card->qdio.in_q | ||
2094 | ->bufs[card->rx.b_index] | ||
2095 | .buffer->element[0]; | ||
2096 | card->rx.e_offset = 0; | ||
2097 | } | ||
2098 | } | ||
2099 | |||
2100 | if (work_done >= budget) | ||
2101 | goto out; | ||
2102 | else | ||
2103 | new_budget = budget - work_done; | ||
2104 | } | ||
2105 | } | ||
2106 | |||
2107 | napi_complete(napi); | ||
2108 | if (qdio_start_irq(card->data.ccwdev, 0)) | ||
2109 | napi_schedule(&card->napi); | ||
2110 | out: | ||
2111 | if (card->options.performance_stats) | ||
2112 | card->perf_stats.inbound_time += qeth_get_micros() - | ||
2113 | card->perf_stats.inbound_start_time; | ||
2114 | return work_done; | ||
2173 | } | 2115 | } |
2174 | 2116 | ||
2175 | static int qeth_l3_verify_vlan_dev(struct net_device *dev, | 2117 | static int qeth_l3_verify_vlan_dev(struct net_device *dev, |
@@ -2183,7 +2125,7 @@ static int qeth_l3_verify_vlan_dev(struct net_device *dev, | |||
2183 | if (!vg) | 2125 | if (!vg) |
2184 | return rc; | 2126 | return rc; |
2185 | 2127 | ||
2186 | for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { | 2128 | for (i = 0; i < VLAN_N_VID; i++) { |
2187 | if (vlan_group_get_device(vg, i) == dev) { | 2129 | if (vlan_group_get_device(vg, i) == dev) { |
2188 | rc = QETH_VLAN_CARD; | 2130 | rc = QETH_VLAN_CARD; |
2189 | break; | 2131 | break; |
@@ -2255,25 +2197,14 @@ static int qeth_l3_stop_card(struct qeth_card *card, int recovery_mode) | |||
2255 | dev_close(card->dev); | 2197 | dev_close(card->dev); |
2256 | rtnl_unlock(); | 2198 | rtnl_unlock(); |
2257 | } | 2199 | } |
2258 | if (!card->use_hard_stop) { | ||
2259 | rc = qeth_send_stoplan(card); | ||
2260 | if (rc) | ||
2261 | QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc); | ||
2262 | } | ||
2263 | card->state = CARD_STATE_SOFTSETUP; | 2200 | card->state = CARD_STATE_SOFTSETUP; |
2264 | } | 2201 | } |
2265 | if (card->state == CARD_STATE_SOFTSETUP) { | 2202 | if (card->state == CARD_STATE_SOFTSETUP) { |
2266 | qeth_l3_clear_ip_list(card, !card->use_hard_stop, 1); | 2203 | qeth_l3_clear_ip_list(card, 1); |
2267 | qeth_clear_ipacmd_list(card); | 2204 | qeth_clear_ipacmd_list(card); |
2268 | card->state = CARD_STATE_HARDSETUP; | 2205 | card->state = CARD_STATE_HARDSETUP; |
2269 | } | 2206 | } |
2270 | if (card->state == CARD_STATE_HARDSETUP) { | 2207 | if (card->state == CARD_STATE_HARDSETUP) { |
2271 | if (!card->use_hard_stop && | ||
2272 | (card->info.type != QETH_CARD_TYPE_IQD)) { | ||
2273 | rc = qeth_l3_put_unique_id(card); | ||
2274 | if (rc) | ||
2275 | QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc); | ||
2276 | } | ||
2277 | qeth_qdio_clear_card(card, 0); | 2208 | qeth_qdio_clear_card(card, 0); |
2278 | qeth_clear_qdio_buffers(card); | 2209 | qeth_clear_qdio_buffers(card); |
2279 | qeth_clear_working_pool_list(card); | 2210 | qeth_clear_working_pool_list(card); |
@@ -2283,7 +2214,6 @@ static int qeth_l3_stop_card(struct qeth_card *card, int recovery_mode) | |||
2283 | qeth_clear_cmd_buffers(&card->read); | 2214 | qeth_clear_cmd_buffers(&card->read); |
2284 | qeth_clear_cmd_buffers(&card->write); | 2215 | qeth_clear_cmd_buffers(&card->write); |
2285 | } | 2216 | } |
2286 | card->use_hard_stop = 0; | ||
2287 | return rc; | 2217 | return rc; |
2288 | } | 2218 | } |
2289 | 2219 | ||
@@ -2390,22 +2320,46 @@ static int qeth_l3_arp_set_no_entries(struct qeth_card *card, int no_entries) | |||
2390 | return rc; | 2320 | return rc; |
2391 | } | 2321 | } |
2392 | 2322 | ||
2393 | static void qeth_l3_copy_arp_entries_stripped(struct qeth_arp_query_info *qinfo, | 2323 | static __u32 get_arp_entry_size(struct qeth_card *card, |
2394 | struct qeth_arp_query_data *qdata, int entry_size, | 2324 | struct qeth_arp_query_data *qdata, |
2395 | int uentry_size) | 2325 | struct qeth_arp_entrytype *type, __u8 strip_entries) |
2396 | { | 2326 | { |
2397 | char *entry_ptr; | 2327 | __u32 rc; |
2398 | char *uentry_ptr; | 2328 | __u8 is_hsi; |
2399 | int i; | ||
2400 | 2329 | ||
2401 | entry_ptr = (char *)&qdata->data; | 2330 | is_hsi = qdata->reply_bits == 5; |
2402 | uentry_ptr = (char *)(qinfo->udata + qinfo->udata_offset); | 2331 | if (type->ip == QETHARP_IP_ADDR_V4) { |
2403 | for (i = 0; i < qdata->no_entries; ++i) { | 2332 | QETH_CARD_TEXT(card, 4, "arpev4"); |
2404 | /* strip off 32 bytes "media specific information" */ | 2333 | if (strip_entries) { |
2405 | memcpy(uentry_ptr, (entry_ptr + 32), entry_size - 32); | 2334 | rc = is_hsi ? sizeof(struct qeth_arp_qi_entry5_short) : |
2406 | entry_ptr += entry_size; | 2335 | sizeof(struct qeth_arp_qi_entry7_short); |
2407 | uentry_ptr += uentry_size; | 2336 | } else { |
2337 | rc = is_hsi ? sizeof(struct qeth_arp_qi_entry5) : | ||
2338 | sizeof(struct qeth_arp_qi_entry7); | ||
2339 | } | ||
2340 | } else if (type->ip == QETHARP_IP_ADDR_V6) { | ||
2341 | QETH_CARD_TEXT(card, 4, "arpev6"); | ||
2342 | if (strip_entries) { | ||
2343 | rc = is_hsi ? | ||
2344 | sizeof(struct qeth_arp_qi_entry5_short_ipv6) : | ||
2345 | sizeof(struct qeth_arp_qi_entry7_short_ipv6); | ||
2346 | } else { | ||
2347 | rc = is_hsi ? | ||
2348 | sizeof(struct qeth_arp_qi_entry5_ipv6) : | ||
2349 | sizeof(struct qeth_arp_qi_entry7_ipv6); | ||
2350 | } | ||
2351 | } else { | ||
2352 | QETH_CARD_TEXT(card, 4, "arpinv"); | ||
2353 | rc = 0; | ||
2408 | } | 2354 | } |
2355 | |||
2356 | return rc; | ||
2357 | } | ||
2358 | |||
2359 | static int arpentry_matches_prot(struct qeth_arp_entrytype *type, __u16 prot) | ||
2360 | { | ||
2361 | return (type->ip == QETHARP_IP_ADDR_V4 && prot == QETH_PROT_IPV4) || | ||
2362 | (type->ip == QETHARP_IP_ADDR_V6 && prot == QETH_PROT_IPV6); | ||
2409 | } | 2363 | } |
2410 | 2364 | ||
2411 | static int qeth_l3_arp_query_cb(struct qeth_card *card, | 2365 | static int qeth_l3_arp_query_cb(struct qeth_card *card, |
@@ -2414,72 +2368,77 @@ static int qeth_l3_arp_query_cb(struct qeth_card *card, | |||
2414 | struct qeth_ipa_cmd *cmd; | 2368 | struct qeth_ipa_cmd *cmd; |
2415 | struct qeth_arp_query_data *qdata; | 2369 | struct qeth_arp_query_data *qdata; |
2416 | struct qeth_arp_query_info *qinfo; | 2370 | struct qeth_arp_query_info *qinfo; |
2417 | int entry_size; | ||
2418 | int uentry_size; | ||
2419 | int i; | 2371 | int i; |
2372 | int e; | ||
2373 | int entrybytes_done; | ||
2374 | int stripped_bytes; | ||
2375 | __u8 do_strip_entries; | ||
2420 | 2376 | ||
2421 | QETH_CARD_TEXT(card, 4, "arpquecb"); | 2377 | QETH_CARD_TEXT(card, 3, "arpquecb"); |
2422 | 2378 | ||
2423 | qinfo = (struct qeth_arp_query_info *) reply->param; | 2379 | qinfo = (struct qeth_arp_query_info *) reply->param; |
2424 | cmd = (struct qeth_ipa_cmd *) data; | 2380 | cmd = (struct qeth_ipa_cmd *) data; |
2381 | QETH_CARD_TEXT_(card, 4, "%i", cmd->hdr.prot_version); | ||
2425 | if (cmd->hdr.return_code) { | 2382 | if (cmd->hdr.return_code) { |
2426 | QETH_CARD_TEXT_(card, 4, "qaer1%i", cmd->hdr.return_code); | 2383 | QETH_CARD_TEXT(card, 4, "arpcberr"); |
2384 | QETH_CARD_TEXT_(card, 4, "%i", cmd->hdr.return_code); | ||
2427 | return 0; | 2385 | return 0; |
2428 | } | 2386 | } |
2429 | if (cmd->data.setassparms.hdr.return_code) { | 2387 | if (cmd->data.setassparms.hdr.return_code) { |
2430 | cmd->hdr.return_code = cmd->data.setassparms.hdr.return_code; | 2388 | cmd->hdr.return_code = cmd->data.setassparms.hdr.return_code; |
2431 | QETH_CARD_TEXT_(card, 4, "qaer2%i", cmd->hdr.return_code); | 2389 | QETH_CARD_TEXT(card, 4, "setaperr"); |
2390 | QETH_CARD_TEXT_(card, 4, "%i", cmd->hdr.return_code); | ||
2432 | return 0; | 2391 | return 0; |
2433 | } | 2392 | } |
2434 | qdata = &cmd->data.setassparms.data.query_arp; | 2393 | qdata = &cmd->data.setassparms.data.query_arp; |
2435 | switch (qdata->reply_bits) { | ||
2436 | case 5: | ||
2437 | uentry_size = entry_size = sizeof(struct qeth_arp_qi_entry5); | ||
2438 | if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES) | ||
2439 | uentry_size = sizeof(struct qeth_arp_qi_entry5_short); | ||
2440 | break; | ||
2441 | case 7: | ||
2442 | /* fall through to default */ | ||
2443 | default: | ||
2444 | /* tr is the same as eth -> entry7 */ | ||
2445 | uentry_size = entry_size = sizeof(struct qeth_arp_qi_entry7); | ||
2446 | if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES) | ||
2447 | uentry_size = sizeof(struct qeth_arp_qi_entry7_short); | ||
2448 | break; | ||
2449 | } | ||
2450 | /* check if there is enough room in userspace */ | ||
2451 | if ((qinfo->udata_len - qinfo->udata_offset) < | ||
2452 | qdata->no_entries * uentry_size){ | ||
2453 | QETH_CARD_TEXT_(card, 4, "qaer3%i", -ENOMEM); | ||
2454 | cmd->hdr.return_code = -ENOMEM; | ||
2455 | goto out_error; | ||
2456 | } | ||
2457 | QETH_CARD_TEXT_(card, 4, "anore%i", | ||
2458 | cmd->data.setassparms.hdr.number_of_replies); | ||
2459 | QETH_CARD_TEXT_(card, 4, "aseqn%i", cmd->data.setassparms.hdr.seq_no); | ||
2460 | QETH_CARD_TEXT_(card, 4, "anoen%i", qdata->no_entries); | 2394 | QETH_CARD_TEXT_(card, 4, "anoen%i", qdata->no_entries); |
2461 | 2395 | ||
2462 | if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES) { | 2396 | do_strip_entries = (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES) > 0; |
2463 | /* strip off "media specific information" */ | 2397 | stripped_bytes = do_strip_entries ? QETH_QARP_MEDIASPECIFIC_BYTES : 0; |
2464 | qeth_l3_copy_arp_entries_stripped(qinfo, qdata, entry_size, | 2398 | entrybytes_done = 0; |
2465 | uentry_size); | 2399 | for (e = 0; e < qdata->no_entries; ++e) { |
2466 | } else | 2400 | char *cur_entry; |
2467 | /*copy entries to user buffer*/ | 2401 | __u32 esize; |
2468 | memcpy(qinfo->udata + qinfo->udata_offset, | 2402 | struct qeth_arp_entrytype *etype; |
2469 | (char *)&qdata->data, qdata->no_entries*uentry_size); | 2403 | |
2404 | cur_entry = &qdata->data + entrybytes_done; | ||
2405 | etype = &((struct qeth_arp_qi_entry5 *) cur_entry)->type; | ||
2406 | if (!arpentry_matches_prot(etype, cmd->hdr.prot_version)) { | ||
2407 | QETH_CARD_TEXT(card, 4, "pmis"); | ||
2408 | QETH_CARD_TEXT_(card, 4, "%i", etype->ip); | ||
2409 | break; | ||
2410 | } | ||
2411 | esize = get_arp_entry_size(card, qdata, etype, | ||
2412 | do_strip_entries); | ||
2413 | QETH_CARD_TEXT_(card, 5, "esz%i", esize); | ||
2414 | if (!esize) | ||
2415 | break; | ||
2416 | |||
2417 | if ((qinfo->udata_len - qinfo->udata_offset) < esize) { | ||
2418 | QETH_CARD_TEXT_(card, 4, "qaer3%i", -ENOMEM); | ||
2419 | cmd->hdr.return_code = -ENOMEM; | ||
2420 | goto out_error; | ||
2421 | } | ||
2470 | 2422 | ||
2471 | qinfo->no_entries += qdata->no_entries; | 2423 | memcpy(qinfo->udata + qinfo->udata_offset, |
2472 | qinfo->udata_offset += (qdata->no_entries*uentry_size); | 2424 | &qdata->data + entrybytes_done + stripped_bytes, |
2425 | esize); | ||
2426 | entrybytes_done += esize + stripped_bytes; | ||
2427 | qinfo->udata_offset += esize; | ||
2428 | ++qinfo->no_entries; | ||
2429 | } | ||
2473 | /* check if all replies received ... */ | 2430 | /* check if all replies received ... */ |
2474 | if (cmd->data.setassparms.hdr.seq_no < | 2431 | if (cmd->data.setassparms.hdr.seq_no < |
2475 | cmd->data.setassparms.hdr.number_of_replies) | 2432 | cmd->data.setassparms.hdr.number_of_replies) |
2476 | return 1; | 2433 | return 1; |
2434 | QETH_CARD_TEXT_(card, 4, "nove%i", qinfo->no_entries); | ||
2477 | memcpy(qinfo->udata, &qinfo->no_entries, 4); | 2435 | memcpy(qinfo->udata, &qinfo->no_entries, 4); |
2478 | /* keep STRIP_ENTRIES flag so the user program can distinguish | 2436 | /* keep STRIP_ENTRIES flag so the user program can distinguish |
2479 | * stripped entries from normal ones */ | 2437 | * stripped entries from normal ones */ |
2480 | if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES) | 2438 | if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES) |
2481 | qdata->reply_bits |= QETH_QARP_STRIP_ENTRIES; | 2439 | qdata->reply_bits |= QETH_QARP_STRIP_ENTRIES; |
2482 | memcpy(qinfo->udata + QETH_QARP_MASK_OFFSET, &qdata->reply_bits, 2); | 2440 | memcpy(qinfo->udata + QETH_QARP_MASK_OFFSET, &qdata->reply_bits, 2); |
2441 | QETH_CARD_TEXT_(card, 4, "rc%i", 0); | ||
2483 | return 0; | 2442 | return 0; |
2484 | out_error: | 2443 | out_error: |
2485 | i = 0; | 2444 | i = 0; |
@@ -2502,45 +2461,86 @@ static int qeth_l3_send_ipa_arp_cmd(struct qeth_card *card, | |||
2502 | reply_cb, reply_param); | 2461 | reply_cb, reply_param); |
2503 | } | 2462 | } |
2504 | 2463 | ||
2505 | static int qeth_l3_arp_query(struct qeth_card *card, char __user *udata) | 2464 | static int qeth_l3_query_arp_cache_info(struct qeth_card *card, |
2465 | enum qeth_prot_versions prot, | ||
2466 | struct qeth_arp_query_info *qinfo) | ||
2506 | { | 2467 | { |
2507 | struct qeth_cmd_buffer *iob; | 2468 | struct qeth_cmd_buffer *iob; |
2508 | struct qeth_arp_query_info qinfo = {0, }; | 2469 | struct qeth_ipa_cmd *cmd; |
2509 | int tmp; | 2470 | int tmp; |
2510 | int rc; | 2471 | int rc; |
2511 | 2472 | ||
2473 | QETH_CARD_TEXT_(card, 3, "qarpipv%i", prot); | ||
2474 | |||
2475 | iob = qeth_l3_get_setassparms_cmd(card, IPA_ARP_PROCESSING, | ||
2476 | IPA_CMD_ASS_ARP_QUERY_INFO, | ||
2477 | sizeof(struct qeth_arp_query_data) - sizeof(char), | ||
2478 | prot); | ||
2479 | cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); | ||
2480 | cmd->data.setassparms.data.query_arp.request_bits = 0x000F; | ||
2481 | cmd->data.setassparms.data.query_arp.reply_bits = 0; | ||
2482 | cmd->data.setassparms.data.query_arp.no_entries = 0; | ||
2483 | rc = qeth_l3_send_ipa_arp_cmd(card, iob, | ||
2484 | QETH_SETASS_BASE_LEN+QETH_ARP_CMD_LEN, | ||
2485 | qeth_l3_arp_query_cb, (void *)qinfo); | ||
2486 | if (rc) { | ||
2487 | tmp = rc; | ||
2488 | QETH_DBF_MESSAGE(2, | ||
2489 | "Error while querying ARP cache on %s: %s " | ||
2490 | "(0x%x/%d)\n", QETH_CARD_IFNAME(card), | ||
2491 | qeth_l3_arp_get_error_cause(&rc), tmp, tmp); | ||
2492 | } | ||
2493 | |||
2494 | return rc; | ||
2495 | } | ||
2496 | |||
2497 | static int qeth_l3_arp_query(struct qeth_card *card, char __user *udata) | ||
2498 | { | ||
2499 | struct qeth_arp_query_info qinfo = {0, }; | ||
2500 | int rc; | ||
2501 | |||
2512 | QETH_CARD_TEXT(card, 3, "arpquery"); | 2502 | QETH_CARD_TEXT(card, 3, "arpquery"); |
2513 | 2503 | ||
2514 | if (!qeth_is_supported(card,/*IPA_QUERY_ARP_ADDR_INFO*/ | 2504 | if (!qeth_is_supported(card,/*IPA_QUERY_ARP_ADDR_INFO*/ |
2515 | IPA_ARP_PROCESSING)) { | 2505 | IPA_ARP_PROCESSING)) { |
2516 | return -EOPNOTSUPP; | 2506 | QETH_CARD_TEXT(card, 3, "arpqnsup"); |
2507 | rc = -EOPNOTSUPP; | ||
2508 | goto out; | ||
2517 | } | 2509 | } |
2518 | /* get size of userspace buffer and mask_bits -> 6 bytes */ | 2510 | /* get size of userspace buffer and mask_bits -> 6 bytes */ |
2519 | if (copy_from_user(&qinfo, udata, 6)) | 2511 | if (copy_from_user(&qinfo, udata, 6)) { |
2520 | return -EFAULT; | 2512 | rc = -EFAULT; |
2513 | goto out; | ||
2514 | } | ||
2521 | qinfo.udata = kzalloc(qinfo.udata_len, GFP_KERNEL); | 2515 | qinfo.udata = kzalloc(qinfo.udata_len, GFP_KERNEL); |
2522 | if (!qinfo.udata) | 2516 | if (!qinfo.udata) { |
2523 | return -ENOMEM; | 2517 | rc = -ENOMEM; |
2518 | goto out; | ||
2519 | } | ||
2524 | qinfo.udata_offset = QETH_QARP_ENTRIES_OFFSET; | 2520 | qinfo.udata_offset = QETH_QARP_ENTRIES_OFFSET; |
2525 | iob = qeth_l3_get_setassparms_cmd(card, IPA_ARP_PROCESSING, | 2521 | rc = qeth_l3_query_arp_cache_info(card, QETH_PROT_IPV4, &qinfo); |
2526 | IPA_CMD_ASS_ARP_QUERY_INFO, | ||
2527 | sizeof(int), QETH_PROT_IPV4); | ||
2528 | |||
2529 | rc = qeth_l3_send_ipa_arp_cmd(card, iob, | ||
2530 | QETH_SETASS_BASE_LEN+QETH_ARP_CMD_LEN, | ||
2531 | qeth_l3_arp_query_cb, (void *)&qinfo); | ||
2532 | if (rc) { | 2522 | if (rc) { |
2533 | tmp = rc; | ||
2534 | QETH_DBF_MESSAGE(2, "Error while querying ARP cache on %s: %s " | ||
2535 | "(0x%x/%d)\n", QETH_CARD_IFNAME(card), | ||
2536 | qeth_l3_arp_get_error_cause(&rc), tmp, tmp); | ||
2537 | if (copy_to_user(udata, qinfo.udata, 4)) | 2523 | if (copy_to_user(udata, qinfo.udata, 4)) |
2538 | rc = -EFAULT; | 2524 | rc = -EFAULT; |
2525 | goto free_and_out; | ||
2539 | } else { | 2526 | } else { |
2540 | if (copy_to_user(udata, qinfo.udata, qinfo.udata_len)) | 2527 | #ifdef CONFIG_QETH_IPV6 |
2528 | if (qinfo.mask_bits & QETH_QARP_WITH_IPV6) { | ||
2529 | /* fails in case of GuestLAN QDIO mode */ | ||
2530 | qeth_l3_query_arp_cache_info(card, QETH_PROT_IPV6, | ||
2531 | &qinfo); | ||
2532 | } | ||
2533 | #endif | ||
2534 | if (copy_to_user(udata, qinfo.udata, qinfo.udata_len)) { | ||
2535 | QETH_CARD_TEXT(card, 4, "qactf"); | ||
2541 | rc = -EFAULT; | 2536 | rc = -EFAULT; |
2537 | goto free_and_out; | ||
2538 | } | ||
2539 | QETH_CARD_TEXT_(card, 4, "qacts"); | ||
2542 | } | 2540 | } |
2541 | free_and_out: | ||
2543 | kfree(qinfo.udata); | 2542 | kfree(qinfo.udata); |
2543 | out: | ||
2544 | return rc; | 2544 | return rc; |
2545 | } | 2545 | } |
2546 | 2546 | ||
@@ -2859,7 +2859,9 @@ static inline void qeth_l3_hdr_csum(struct qeth_card *card, | |||
2859 | */ | 2859 | */ |
2860 | if (iph->protocol == IPPROTO_UDP) | 2860 | if (iph->protocol == IPPROTO_UDP) |
2861 | hdr->hdr.l3.ext_flags |= QETH_HDR_EXT_UDP; | 2861 | hdr->hdr.l3.ext_flags |= QETH_HDR_EXT_UDP; |
2862 | hdr->hdr.l3.ext_flags |= QETH_HDR_EXT_CSUM_TRANSP_REQ; | 2862 | hdr->hdr.l3.ext_flags |= QETH_HDR_EXT_CSUM_TRANSP_REQ | |
2863 | QETH_HDR_EXT_CSUM_HDR_REQ; | ||
2864 | iph->check = 0; | ||
2863 | if (card->options.performance_stats) | 2865 | if (card->options.performance_stats) |
2864 | card->perf_stats.tx_csum++; | 2866 | card->perf_stats.tx_csum++; |
2865 | } | 2867 | } |
@@ -2874,6 +2876,7 @@ static void qeth_tso_fill_header(struct qeth_card *card, | |||
2874 | 2876 | ||
2875 | /*fix header to TSO values ...*/ | 2877 | /*fix header to TSO values ...*/ |
2876 | hdr->hdr.hdr.l3.id = QETH_HEADER_TYPE_TSO; | 2878 | hdr->hdr.hdr.l3.id = QETH_HEADER_TYPE_TSO; |
2879 | hdr->hdr.hdr.l3.length = skb->len - sizeof(struct qeth_hdr_tso); | ||
2877 | /*set values which are fix for the first approach ...*/ | 2880 | /*set values which are fix for the first approach ...*/ |
2878 | hdr->ext.hdr_tot_len = (__u16) sizeof(struct qeth_hdr_ext_tso); | 2881 | hdr->ext.hdr_tot_len = (__u16) sizeof(struct qeth_hdr_ext_tso); |
2879 | hdr->ext.imb_hdr_no = 1; | 2882 | hdr->ext.imb_hdr_no = 1; |
@@ -2923,7 +2926,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
2923 | struct qeth_qdio_out_q *queue = card->qdio.out_qs | 2926 | struct qeth_qdio_out_q *queue = card->qdio.out_qs |
2924 | [qeth_get_priority_queue(card, skb, ipv, cast_type)]; | 2927 | [qeth_get_priority_queue(card, skb, ipv, cast_type)]; |
2925 | int tx_bytes = skb->len; | 2928 | int tx_bytes = skb->len; |
2926 | enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO; | 2929 | bool large_send; |
2927 | int data_offset = -1; | 2930 | int data_offset = -1; |
2928 | int nr_frags; | 2931 | int nr_frags; |
2929 | 2932 | ||
@@ -2945,8 +2948,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
2945 | card->perf_stats.outbound_start_time = qeth_get_micros(); | 2948 | card->perf_stats.outbound_start_time = qeth_get_micros(); |
2946 | } | 2949 | } |
2947 | 2950 | ||
2948 | if (skb_is_gso(skb)) | 2951 | large_send = skb_is_gso(skb); |
2949 | large_send = card->options.large_send; | ||
2950 | 2952 | ||
2951 | if ((card->info.type == QETH_CARD_TYPE_IQD) && (!large_send) && | 2953 | if ((card->info.type == QETH_CARD_TYPE_IQD) && (!large_send) && |
2952 | (skb_shinfo(skb)->nr_frags == 0)) { | 2954 | (skb_shinfo(skb)->nr_frags == 0)) { |
@@ -2975,7 +2977,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
2975 | skb_pull(new_skb, ETH_HLEN); | 2977 | skb_pull(new_skb, ETH_HLEN); |
2976 | } | 2978 | } |
2977 | 2979 | ||
2978 | if (ipv == 6 && card->vlangrp && | 2980 | if (ipv != 4 && card->vlangrp && |
2979 | vlan_tx_tag_present(new_skb)) { | 2981 | vlan_tx_tag_present(new_skb)) { |
2980 | skb_push(new_skb, VLAN_HLEN); | 2982 | skb_push(new_skb, VLAN_HLEN); |
2981 | skb_copy_to_linear_data(new_skb, new_skb->data + 4, 4); | 2983 | skb_copy_to_linear_data(new_skb, new_skb->data + 4, 4); |
@@ -2995,7 +2997,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
2995 | /* fix hardware limitation: as long as we do not have sbal | 2997 | /* fix hardware limitation: as long as we do not have sbal |
2996 | * chaining we can not send long frag lists | 2998 | * chaining we can not send long frag lists |
2997 | */ | 2999 | */ |
2998 | if (large_send == QETH_LARGE_SEND_TSO) { | 3000 | if (large_send) { |
2999 | if (qeth_l3_tso_elements(new_skb) + 1 > 16) { | 3001 | if (qeth_l3_tso_elements(new_skb) + 1 > 16) { |
3000 | if (skb_linearize(new_skb)) | 3002 | if (skb_linearize(new_skb)) |
3001 | goto tx_drop; | 3003 | goto tx_drop; |
@@ -3004,8 +3006,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
3004 | } | 3006 | } |
3005 | } | 3007 | } |
3006 | 3008 | ||
3007 | if ((large_send == QETH_LARGE_SEND_TSO) && | 3009 | if (large_send && (cast_type == RTN_UNSPEC)) { |
3008 | (cast_type == RTN_UNSPEC)) { | ||
3009 | hdr = (struct qeth_hdr *)skb_push(new_skb, | 3010 | hdr = (struct qeth_hdr *)skb_push(new_skb, |
3010 | sizeof(struct qeth_hdr_tso)); | 3011 | sizeof(struct qeth_hdr_tso)); |
3011 | memset(hdr, 0, sizeof(struct qeth_hdr_tso)); | 3012 | memset(hdr, 0, sizeof(struct qeth_hdr_tso)); |
@@ -3040,7 +3041,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
3040 | 3041 | ||
3041 | if (card->info.type != QETH_CARD_TYPE_IQD) { | 3042 | if (card->info.type != QETH_CARD_TYPE_IQD) { |
3042 | int len; | 3043 | int len; |
3043 | if (large_send == QETH_LARGE_SEND_TSO) | 3044 | if (large_send) |
3044 | len = ((unsigned long)tcp_hdr(new_skb) + | 3045 | len = ((unsigned long)tcp_hdr(new_skb) + |
3045 | tcp_hdr(new_skb)->doff * 4) - | 3046 | tcp_hdr(new_skb)->doff * 4) - |
3046 | (unsigned long)new_skb->data; | 3047 | (unsigned long)new_skb->data; |
@@ -3061,7 +3062,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
3061 | if (new_skb != skb) | 3062 | if (new_skb != skb) |
3062 | dev_kfree_skb_any(skb); | 3063 | dev_kfree_skb_any(skb); |
3063 | if (card->options.performance_stats) { | 3064 | if (card->options.performance_stats) { |
3064 | if (large_send != QETH_LARGE_SEND_NO) { | 3065 | if (large_send) { |
3065 | card->perf_stats.large_send_bytes += tx_bytes; | 3066 | card->perf_stats.large_send_bytes += tx_bytes; |
3066 | card->perf_stats.large_send_cnt++; | 3067 | card->perf_stats.large_send_cnt++; |
3067 | } | 3068 | } |
@@ -3100,92 +3101,89 @@ tx_drop: | |||
3100 | return NETDEV_TX_OK; | 3101 | return NETDEV_TX_OK; |
3101 | } | 3102 | } |
3102 | 3103 | ||
3103 | static int qeth_l3_open(struct net_device *dev) | 3104 | static int __qeth_l3_open(struct net_device *dev) |
3104 | { | 3105 | { |
3105 | struct qeth_card *card = dev->ml_priv; | 3106 | struct qeth_card *card = dev->ml_priv; |
3107 | int rc = 0; | ||
3106 | 3108 | ||
3107 | QETH_CARD_TEXT(card, 4, "qethopen"); | 3109 | QETH_CARD_TEXT(card, 4, "qethopen"); |
3110 | if (card->state == CARD_STATE_UP) | ||
3111 | return rc; | ||
3108 | if (card->state != CARD_STATE_SOFTSETUP) | 3112 | if (card->state != CARD_STATE_SOFTSETUP) |
3109 | return -ENODEV; | 3113 | return -ENODEV; |
3110 | card->data.state = CH_STATE_UP; | 3114 | card->data.state = CH_STATE_UP; |
3111 | card->state = CARD_STATE_UP; | 3115 | card->state = CARD_STATE_UP; |
3112 | netif_start_queue(dev); | 3116 | netif_start_queue(dev); |
3113 | 3117 | ||
3114 | if (!card->lan_online && netif_carrier_ok(dev)) | 3118 | if (qdio_stop_irq(card->data.ccwdev, 0) >= 0) { |
3115 | netif_carrier_off(dev); | 3119 | napi_enable(&card->napi); |
3116 | return 0; | 3120 | napi_schedule(&card->napi); |
3121 | } else | ||
3122 | rc = -EIO; | ||
3123 | return rc; | ||
3117 | } | 3124 | } |
3118 | 3125 | ||
3119 | static int qeth_l3_stop(struct net_device *dev) | 3126 | static int qeth_l3_open(struct net_device *dev) |
3120 | { | 3127 | { |
3121 | struct qeth_card *card = dev->ml_priv; | 3128 | struct qeth_card *card = dev->ml_priv; |
3122 | 3129 | ||
3123 | QETH_CARD_TEXT(card, 4, "qethstop"); | 3130 | QETH_CARD_TEXT(card, 5, "qethope_"); |
3124 | netif_tx_disable(dev); | 3131 | if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) { |
3125 | if (card->state == CARD_STATE_UP) | 3132 | QETH_CARD_TEXT(card, 3, "openREC"); |
3126 | card->state = CARD_STATE_SOFTSETUP; | 3133 | return -ERESTARTSYS; |
3127 | return 0; | 3134 | } |
3135 | return __qeth_l3_open(dev); | ||
3128 | } | 3136 | } |
3129 | 3137 | ||
3130 | static u32 qeth_l3_ethtool_get_rx_csum(struct net_device *dev) | 3138 | static int qeth_l3_stop(struct net_device *dev) |
3131 | { | 3139 | { |
3132 | struct qeth_card *card = dev->ml_priv; | 3140 | struct qeth_card *card = dev->ml_priv; |
3133 | 3141 | ||
3134 | return (card->options.checksum_type == HW_CHECKSUMMING); | 3142 | QETH_CARD_TEXT(card, 4, "qethstop"); |
3143 | netif_tx_disable(dev); | ||
3144 | if (card->state == CARD_STATE_UP) { | ||
3145 | card->state = CARD_STATE_SOFTSETUP; | ||
3146 | napi_disable(&card->napi); | ||
3147 | } | ||
3148 | return 0; | ||
3135 | } | 3149 | } |
3136 | 3150 | ||
3137 | static int qeth_l3_ethtool_set_rx_csum(struct net_device *dev, u32 data) | 3151 | static u32 qeth_l3_fix_features(struct net_device *dev, u32 features) |
3138 | { | 3152 | { |
3139 | struct qeth_card *card = dev->ml_priv; | 3153 | struct qeth_card *card = dev->ml_priv; |
3140 | enum qeth_checksum_types csum_type; | ||
3141 | 3154 | ||
3142 | if (data) | 3155 | if (!qeth_is_supported(card, IPA_OUTBOUND_CHECKSUM)) |
3143 | csum_type = HW_CHECKSUMMING; | 3156 | features &= ~NETIF_F_IP_CSUM; |
3144 | else | 3157 | if (!qeth_is_supported(card, IPA_OUTBOUND_TSO)) |
3145 | csum_type = SW_CHECKSUMMING; | 3158 | features &= ~NETIF_F_TSO; |
3159 | if (!qeth_is_supported(card, IPA_INBOUND_CHECKSUM)) | ||
3160 | features &= ~NETIF_F_RXCSUM; | ||
3146 | 3161 | ||
3147 | return qeth_l3_set_rx_csum(card, csum_type); | 3162 | return features; |
3148 | } | 3163 | } |
3149 | 3164 | ||
3150 | static int qeth_l3_ethtool_set_tso(struct net_device *dev, u32 data) | 3165 | static int qeth_l3_set_features(struct net_device *dev, u32 features) |
3151 | { | 3166 | { |
3152 | struct qeth_card *card = dev->ml_priv; | 3167 | struct qeth_card *card = dev->ml_priv; |
3153 | int rc = 0; | 3168 | u32 changed = dev->features ^ features; |
3169 | int err; | ||
3154 | 3170 | ||
3155 | if (data) { | 3171 | if (!(changed & NETIF_F_RXCSUM)) |
3156 | rc = qeth_l3_set_large_send(card, QETH_LARGE_SEND_TSO); | 3172 | return 0; |
3157 | } else { | ||
3158 | dev->features &= ~NETIF_F_TSO; | ||
3159 | card->options.large_send = QETH_LARGE_SEND_NO; | ||
3160 | } | ||
3161 | return rc; | ||
3162 | } | ||
3163 | 3173 | ||
3164 | static int qeth_l3_ethtool_set_tx_csum(struct net_device *dev, u32 data) | 3174 | if (card->state == CARD_STATE_DOWN || |
3165 | { | 3175 | card->state == CARD_STATE_RECOVER) |
3166 | struct qeth_card *card = dev->ml_priv; | 3176 | return 0; |
3167 | 3177 | ||
3168 | if (data) { | 3178 | err = qeth_l3_set_rx_csum(card, features & NETIF_F_RXCSUM); |
3169 | if (qeth_is_supported(card, IPA_OUTBOUND_CHECKSUM)) | 3179 | if (err) |
3170 | dev->features |= NETIF_F_IP_CSUM; | 3180 | dev->features = features ^ NETIF_F_RXCSUM; |
3171 | else | ||
3172 | return -EPERM; | ||
3173 | } else | ||
3174 | dev->features &= ~NETIF_F_IP_CSUM; | ||
3175 | 3181 | ||
3176 | return 0; | 3182 | return err; |
3177 | } | 3183 | } |
3178 | 3184 | ||
3179 | static const struct ethtool_ops qeth_l3_ethtool_ops = { | 3185 | static const struct ethtool_ops qeth_l3_ethtool_ops = { |
3180 | .get_link = ethtool_op_get_link, | 3186 | .get_link = ethtool_op_get_link, |
3181 | .get_tx_csum = ethtool_op_get_tx_csum, | ||
3182 | .set_tx_csum = qeth_l3_ethtool_set_tx_csum, | ||
3183 | .get_rx_csum = qeth_l3_ethtool_get_rx_csum, | ||
3184 | .set_rx_csum = qeth_l3_ethtool_set_rx_csum, | ||
3185 | .get_sg = ethtool_op_get_sg, | ||
3186 | .set_sg = ethtool_op_set_sg, | ||
3187 | .get_tso = ethtool_op_get_tso, | ||
3188 | .set_tso = qeth_l3_ethtool_set_tso, | ||
3189 | .get_strings = qeth_core_get_strings, | 3187 | .get_strings = qeth_core_get_strings, |
3190 | .get_ethtool_stats = qeth_core_get_ethtool_stats, | 3188 | .get_ethtool_stats = qeth_core_get_ethtool_stats, |
3191 | .get_sset_count = qeth_core_get_sset_count, | 3189 | .get_sset_count = qeth_core_get_sset_count, |
@@ -3226,6 +3224,8 @@ static const struct net_device_ops qeth_l3_netdev_ops = { | |||
3226 | .ndo_set_multicast_list = qeth_l3_set_multicast_list, | 3224 | .ndo_set_multicast_list = qeth_l3_set_multicast_list, |
3227 | .ndo_do_ioctl = qeth_l3_do_ioctl, | 3225 | .ndo_do_ioctl = qeth_l3_do_ioctl, |
3228 | .ndo_change_mtu = qeth_change_mtu, | 3226 | .ndo_change_mtu = qeth_change_mtu, |
3227 | .ndo_fix_features = qeth_l3_fix_features, | ||
3228 | .ndo_set_features = qeth_l3_set_features, | ||
3229 | .ndo_vlan_rx_register = qeth_l3_vlan_rx_register, | 3229 | .ndo_vlan_rx_register = qeth_l3_vlan_rx_register, |
3230 | .ndo_vlan_rx_add_vid = qeth_l3_vlan_rx_add_vid, | 3230 | .ndo_vlan_rx_add_vid = qeth_l3_vlan_rx_add_vid, |
3231 | .ndo_vlan_rx_kill_vid = qeth_l3_vlan_rx_kill_vid, | 3231 | .ndo_vlan_rx_kill_vid = qeth_l3_vlan_rx_kill_vid, |
@@ -3241,6 +3241,8 @@ static const struct net_device_ops qeth_l3_osa_netdev_ops = { | |||
3241 | .ndo_set_multicast_list = qeth_l3_set_multicast_list, | 3241 | .ndo_set_multicast_list = qeth_l3_set_multicast_list, |
3242 | .ndo_do_ioctl = qeth_l3_do_ioctl, | 3242 | .ndo_do_ioctl = qeth_l3_do_ioctl, |
3243 | .ndo_change_mtu = qeth_change_mtu, | 3243 | .ndo_change_mtu = qeth_change_mtu, |
3244 | .ndo_fix_features = qeth_l3_fix_features, | ||
3245 | .ndo_set_features = qeth_l3_set_features, | ||
3244 | .ndo_vlan_rx_register = qeth_l3_vlan_rx_register, | 3246 | .ndo_vlan_rx_register = qeth_l3_vlan_rx_register, |
3245 | .ndo_vlan_rx_add_vid = qeth_l3_vlan_rx_add_vid, | 3247 | .ndo_vlan_rx_add_vid = qeth_l3_vlan_rx_add_vid, |
3246 | .ndo_vlan_rx_kill_vid = qeth_l3_vlan_rx_kill_vid, | 3248 | .ndo_vlan_rx_kill_vid = qeth_l3_vlan_rx_kill_vid, |
@@ -3271,6 +3273,12 @@ static int qeth_l3_setup_netdev(struct qeth_card *card) | |||
3271 | if (!(card->info.unique_id & UNIQUE_ID_NOT_BY_CARD)) | 3273 | if (!(card->info.unique_id & UNIQUE_ID_NOT_BY_CARD)) |
3272 | card->dev->dev_id = card->info.unique_id & | 3274 | card->dev->dev_id = card->info.unique_id & |
3273 | 0xffff; | 3275 | 0xffff; |
3276 | if (!card->info.guestlan) { | ||
3277 | card->dev->hw_features = NETIF_F_SG | | ||
3278 | NETIF_F_RXCSUM | NETIF_F_IP_CSUM | | ||
3279 | NETIF_F_TSO; | ||
3280 | card->dev->features = NETIF_F_RXCSUM; | ||
3281 | } | ||
3274 | } | 3282 | } |
3275 | } else if (card->info.type == QETH_CARD_TYPE_IQD) { | 3283 | } else if (card->info.type == QETH_CARD_TYPE_IQD) { |
3276 | card->dev = alloc_netdev(0, "hsi%d", ether_setup); | 3284 | card->dev = alloc_netdev(0, "hsi%d", ether_setup); |
@@ -3293,57 +3301,20 @@ static int qeth_l3_setup_netdev(struct qeth_card *card) | |||
3293 | card->dev->gso_max_size = 15 * PAGE_SIZE; | 3301 | card->dev->gso_max_size = 15 * PAGE_SIZE; |
3294 | 3302 | ||
3295 | SET_NETDEV_DEV(card->dev, &card->gdev->dev); | 3303 | SET_NETDEV_DEV(card->dev, &card->gdev->dev); |
3304 | netif_napi_add(card->dev, &card->napi, qeth_l3_poll, QETH_NAPI_WEIGHT); | ||
3296 | return register_netdev(card->dev); | 3305 | return register_netdev(card->dev); |
3297 | } | 3306 | } |
3298 | 3307 | ||
3299 | static void qeth_l3_qdio_input_handler(struct ccw_device *ccwdev, | ||
3300 | unsigned int qdio_err, unsigned int queue, int first_element, | ||
3301 | int count, unsigned long card_ptr) | ||
3302 | { | ||
3303 | struct net_device *net_dev; | ||
3304 | struct qeth_card *card; | ||
3305 | struct qeth_qdio_buffer *buffer; | ||
3306 | int index; | ||
3307 | int i; | ||
3308 | |||
3309 | card = (struct qeth_card *) card_ptr; | ||
3310 | net_dev = card->dev; | ||
3311 | if (card->options.performance_stats) { | ||
3312 | card->perf_stats.inbound_cnt++; | ||
3313 | card->perf_stats.inbound_start_time = qeth_get_micros(); | ||
3314 | } | ||
3315 | if (qdio_err & QDIO_ERROR_ACTIVATE_CHECK_CONDITION) { | ||
3316 | QETH_CARD_TEXT(card, 1, "qdinchk"); | ||
3317 | QETH_CARD_TEXT_(card, 1, "%04X%04X", | ||
3318 | first_element, count); | ||
3319 | QETH_CARD_TEXT_(card, 1, "%04X", queue); | ||
3320 | qeth_schedule_recovery(card); | ||
3321 | return; | ||
3322 | } | ||
3323 | for (i = first_element; i < (first_element + count); ++i) { | ||
3324 | index = i % QDIO_MAX_BUFFERS_PER_Q; | ||
3325 | buffer = &card->qdio.in_q->bufs[index]; | ||
3326 | if (!(qdio_err && | ||
3327 | qeth_check_qdio_errors(card, buffer->buffer, | ||
3328 | qdio_err, "qinerr"))) | ||
3329 | qeth_l3_process_inbound_buffer(card, buffer, index); | ||
3330 | /* clear buffer and give back to hardware */ | ||
3331 | qeth_put_buffer_pool_entry(card, buffer->pool_entry); | ||
3332 | qeth_queue_input_buffer(card, index); | ||
3333 | } | ||
3334 | if (card->options.performance_stats) | ||
3335 | card->perf_stats.inbound_time += qeth_get_micros() - | ||
3336 | card->perf_stats.inbound_start_time; | ||
3337 | } | ||
3338 | |||
3339 | static int qeth_l3_probe_device(struct ccwgroup_device *gdev) | 3308 | static int qeth_l3_probe_device(struct ccwgroup_device *gdev) |
3340 | { | 3309 | { |
3341 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); | 3310 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); |
3342 | 3311 | ||
3343 | qeth_l3_create_device_attributes(&gdev->dev); | 3312 | qeth_l3_create_device_attributes(&gdev->dev); |
3344 | card->options.layer2 = 0; | 3313 | card->options.layer2 = 0; |
3314 | card->info.hwtrap = 0; | ||
3315 | card->discipline.start_poll = qeth_qdio_start_poll; | ||
3345 | card->discipline.input_handler = (qdio_handler_t *) | 3316 | card->discipline.input_handler = (qdio_handler_t *) |
3346 | qeth_l3_qdio_input_handler; | 3317 | qeth_qdio_input_handler; |
3347 | card->discipline.output_handler = (qdio_handler_t *) | 3318 | card->discipline.output_handler = (qdio_handler_t *) |
3348 | qeth_qdio_output_handler; | 3319 | qeth_qdio_output_handler; |
3349 | card->discipline.recover = qeth_l3_recover; | 3320 | card->discipline.recover = qeth_l3_recover; |
@@ -3359,17 +3330,15 @@ static void qeth_l3_remove_device(struct ccwgroup_device *cgdev) | |||
3359 | qeth_set_allowed_threads(card, 0, 1); | 3330 | qeth_set_allowed_threads(card, 0, 1); |
3360 | wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0); | 3331 | wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0); |
3361 | 3332 | ||
3362 | if (cgdev->state == CCWGROUP_ONLINE) { | 3333 | if (cgdev->state == CCWGROUP_ONLINE) |
3363 | card->use_hard_stop = 1; | ||
3364 | qeth_l3_set_offline(cgdev); | 3334 | qeth_l3_set_offline(cgdev); |
3365 | } | ||
3366 | 3335 | ||
3367 | if (card->dev) { | 3336 | if (card->dev) { |
3368 | unregister_netdev(card->dev); | 3337 | unregister_netdev(card->dev); |
3369 | card->dev = NULL; | 3338 | card->dev = NULL; |
3370 | } | 3339 | } |
3371 | 3340 | ||
3372 | qeth_l3_clear_ip_list(card, 0, 0); | 3341 | qeth_l3_clear_ip_list(card, 0); |
3373 | qeth_l3_clear_ipato_list(card); | 3342 | qeth_l3_clear_ipato_list(card); |
3374 | return; | 3343 | return; |
3375 | } | 3344 | } |
@@ -3394,14 +3363,20 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
3394 | goto out_remove; | 3363 | goto out_remove; |
3395 | } | 3364 | } |
3396 | 3365 | ||
3397 | qeth_l3_query_ipassists(card, QETH_PROT_IPV4); | ||
3398 | |||
3399 | if (!card->dev && qeth_l3_setup_netdev(card)) { | 3366 | if (!card->dev && qeth_l3_setup_netdev(card)) { |
3400 | rc = -ENODEV; | 3367 | rc = -ENODEV; |
3401 | goto out_remove; | 3368 | goto out_remove; |
3402 | } | 3369 | } |
3403 | 3370 | ||
3371 | if (qeth_is_diagass_supported(card, QETH_DIAGS_CMD_TRAP)) { | ||
3372 | if (card->info.hwtrap && | ||
3373 | qeth_hw_trap(card, QETH_DIAGS_TRAP_ARM)) | ||
3374 | card->info.hwtrap = 0; | ||
3375 | } else | ||
3376 | card->info.hwtrap = 0; | ||
3377 | |||
3404 | card->state = CARD_STATE_HARDSETUP; | 3378 | card->state = CARD_STATE_HARDSETUP; |
3379 | memset(&card->rx, 0, sizeof(struct qeth_rx)); | ||
3405 | qeth_print_status_message(card); | 3380 | qeth_print_status_message(card); |
3406 | 3381 | ||
3407 | /* softsetup */ | 3382 | /* softsetup */ |
@@ -3414,13 +3389,14 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
3414 | dev_warn(&card->gdev->dev, | 3389 | dev_warn(&card->gdev->dev, |
3415 | "The LAN is offline\n"); | 3390 | "The LAN is offline\n"); |
3416 | card->lan_online = 0; | 3391 | card->lan_online = 0; |
3417 | goto out; | 3392 | goto contin; |
3418 | } | 3393 | } |
3419 | rc = -ENODEV; | 3394 | rc = -ENODEV; |
3420 | goto out_remove; | 3395 | goto out_remove; |
3421 | } else | 3396 | } else |
3422 | card->lan_online = 1; | 3397 | card->lan_online = 1; |
3423 | 3398 | ||
3399 | contin: | ||
3424 | rc = qeth_l3_setadapter_parms(card); | 3400 | rc = qeth_l3_setadapter_parms(card); |
3425 | if (rc) | 3401 | if (rc) |
3426 | QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc); | 3402 | QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc); |
@@ -3428,7 +3404,6 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
3428 | rc = qeth_l3_start_ipassists(card); | 3404 | rc = qeth_l3_start_ipassists(card); |
3429 | if (rc) | 3405 | if (rc) |
3430 | QETH_DBF_TEXT_(SETUP, 2, "3err%d", rc); | 3406 | QETH_DBF_TEXT_(SETUP, 2, "3err%d", rc); |
3431 | qeth_l3_set_large_send(card, card->options.large_send); | ||
3432 | rc = qeth_l3_setrouting_v4(card); | 3407 | rc = qeth_l3_setrouting_v4(card); |
3433 | if (rc) | 3408 | if (rc) |
3434 | QETH_DBF_TEXT_(SETUP, 2, "4err%d", rc); | 3409 | QETH_DBF_TEXT_(SETUP, 2, "4err%d", rc); |
@@ -3445,13 +3420,16 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
3445 | goto out_remove; | 3420 | goto out_remove; |
3446 | } | 3421 | } |
3447 | card->state = CARD_STATE_SOFTSETUP; | 3422 | card->state = CARD_STATE_SOFTSETUP; |
3448 | netif_carrier_on(card->dev); | ||
3449 | 3423 | ||
3450 | qeth_set_allowed_threads(card, 0xffffffff, 0); | 3424 | qeth_set_allowed_threads(card, 0xffffffff, 0); |
3451 | qeth_l3_set_ip_addr_list(card); | 3425 | qeth_l3_set_ip_addr_list(card); |
3426 | if (card->lan_online) | ||
3427 | netif_carrier_on(card->dev); | ||
3428 | else | ||
3429 | netif_carrier_off(card->dev); | ||
3452 | if (recover_flag == CARD_STATE_RECOVER) { | 3430 | if (recover_flag == CARD_STATE_RECOVER) { |
3453 | if (recovery_mode) | 3431 | if (recovery_mode) |
3454 | qeth_l3_open(card->dev); | 3432 | __qeth_l3_open(card->dev); |
3455 | else { | 3433 | else { |
3456 | rtnl_lock(); | 3434 | rtnl_lock(); |
3457 | dev_open(card->dev); | 3435 | dev_open(card->dev); |
@@ -3461,12 +3439,10 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
3461 | } | 3439 | } |
3462 | /* let user_space know that device is online */ | 3440 | /* let user_space know that device is online */ |
3463 | kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE); | 3441 | kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE); |
3464 | out: | ||
3465 | mutex_unlock(&card->conf_mutex); | 3442 | mutex_unlock(&card->conf_mutex); |
3466 | mutex_unlock(&card->discipline_mutex); | 3443 | mutex_unlock(&card->discipline_mutex); |
3467 | return 0; | 3444 | return 0; |
3468 | out_remove: | 3445 | out_remove: |
3469 | card->use_hard_stop = 1; | ||
3470 | qeth_l3_stop_card(card, 0); | 3446 | qeth_l3_stop_card(card, 0); |
3471 | ccw_device_set_offline(CARD_DDEV(card)); | 3447 | ccw_device_set_offline(CARD_DDEV(card)); |
3472 | ccw_device_set_offline(CARD_WDEV(card)); | 3448 | ccw_device_set_offline(CARD_WDEV(card)); |
@@ -3500,6 +3476,10 @@ static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev, | |||
3500 | if (card->dev && netif_carrier_ok(card->dev)) | 3476 | if (card->dev && netif_carrier_ok(card->dev)) |
3501 | netif_carrier_off(card->dev); | 3477 | netif_carrier_off(card->dev); |
3502 | recover_flag = card->state; | 3478 | recover_flag = card->state; |
3479 | if ((!recovery_mode && card->info.hwtrap) || card->info.hwtrap == 2) { | ||
3480 | qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); | ||
3481 | card->info.hwtrap = 1; | ||
3482 | } | ||
3503 | qeth_l3_stop_card(card, recovery_mode); | 3483 | qeth_l3_stop_card(card, recovery_mode); |
3504 | rc = ccw_device_set_offline(CARD_DDEV(card)); | 3484 | rc = ccw_device_set_offline(CARD_DDEV(card)); |
3505 | rc2 = ccw_device_set_offline(CARD_WDEV(card)); | 3485 | rc2 = ccw_device_set_offline(CARD_WDEV(card)); |
@@ -3535,12 +3515,8 @@ static int qeth_l3_recover(void *ptr) | |||
3535 | QETH_CARD_TEXT(card, 2, "recover2"); | 3515 | QETH_CARD_TEXT(card, 2, "recover2"); |
3536 | dev_warn(&card->gdev->dev, | 3516 | dev_warn(&card->gdev->dev, |
3537 | "A recovery process has been started for the device\n"); | 3517 | "A recovery process has been started for the device\n"); |
3538 | card->use_hard_stop = 1; | ||
3539 | __qeth_l3_set_offline(card->gdev, 1); | 3518 | __qeth_l3_set_offline(card->gdev, 1); |
3540 | rc = __qeth_l3_set_online(card->gdev, 1); | 3519 | rc = __qeth_l3_set_online(card->gdev, 1); |
3541 | /* don't run another scheduled recovery */ | ||
3542 | qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD); | ||
3543 | qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD); | ||
3544 | if (!rc) | 3520 | if (!rc) |
3545 | dev_info(&card->gdev->dev, | 3521 | dev_info(&card->gdev->dev, |
3546 | "Device successfully recovered!\n"); | 3522 | "Device successfully recovered!\n"); |
@@ -3551,13 +3527,16 @@ static int qeth_l3_recover(void *ptr) | |||
3551 | dev_warn(&card->gdev->dev, "The qeth device driver " | 3527 | dev_warn(&card->gdev->dev, "The qeth device driver " |
3552 | "failed to recover an error on the device\n"); | 3528 | "failed to recover an error on the device\n"); |
3553 | } | 3529 | } |
3530 | qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD); | ||
3531 | qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD); | ||
3554 | return 0; | 3532 | return 0; |
3555 | } | 3533 | } |
3556 | 3534 | ||
3557 | static void qeth_l3_shutdown(struct ccwgroup_device *gdev) | 3535 | static void qeth_l3_shutdown(struct ccwgroup_device *gdev) |
3558 | { | 3536 | { |
3559 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); | 3537 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); |
3560 | qeth_l3_clear_ip_list(card, 0, 0); | 3538 | if ((gdev->state == CCWGROUP_ONLINE) && card->info.hwtrap) |
3539 | qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); | ||
3561 | qeth_qdio_clear_card(card, 0); | 3540 | qeth_qdio_clear_card(card, 0); |
3562 | qeth_clear_qdio_buffers(card); | 3541 | qeth_clear_qdio_buffers(card); |
3563 | } | 3542 | } |
@@ -3573,7 +3552,8 @@ static int qeth_l3_pm_suspend(struct ccwgroup_device *gdev) | |||
3573 | if (gdev->state == CCWGROUP_OFFLINE) | 3552 | if (gdev->state == CCWGROUP_OFFLINE) |
3574 | return 0; | 3553 | return 0; |
3575 | if (card->state == CARD_STATE_UP) { | 3554 | if (card->state == CARD_STATE_UP) { |
3576 | card->use_hard_stop = 1; | 3555 | if (card->info.hwtrap) |
3556 | qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); | ||
3577 | __qeth_l3_set_offline(card->gdev, 1); | 3557 | __qeth_l3_set_offline(card->gdev, 1); |
3578 | } else | 3558 | } else |
3579 | __qeth_l3_set_offline(card->gdev, 0); | 3559 | __qeth_l3_set_offline(card->gdev, 0); |
diff --git a/drivers/s390/net/qeth_l3_sys.c b/drivers/s390/net/qeth_l3_sys.c index 67cfa68dcf1b..cd99210296e2 100644 --- a/drivers/s390/net/qeth_l3_sys.c +++ b/drivers/s390/net/qeth_l3_sys.c | |||
@@ -15,16 +15,6 @@ | |||
15 | #define QETH_DEVICE_ATTR(_id, _name, _mode, _show, _store) \ | 15 | #define QETH_DEVICE_ATTR(_id, _name, _mode, _show, _store) \ |
16 | struct device_attribute dev_attr_##_id = __ATTR(_name, _mode, _show, _store) | 16 | struct device_attribute dev_attr_##_id = __ATTR(_name, _mode, _show, _store) |
17 | 17 | ||
18 | static const char *qeth_l3_get_checksum_str(struct qeth_card *card) | ||
19 | { | ||
20 | if (card->options.checksum_type == SW_CHECKSUMMING) | ||
21 | return "sw"; | ||
22 | else if (card->options.checksum_type == HW_CHECKSUMMING) | ||
23 | return "hw"; | ||
24 | else | ||
25 | return "no"; | ||
26 | } | ||
27 | |||
28 | static ssize_t qeth_l3_dev_route_show(struct qeth_card *card, | 18 | static ssize_t qeth_l3_dev_route_show(struct qeth_card *card, |
29 | struct qeth_routing_info *route, char *buf) | 19 | struct qeth_routing_info *route, char *buf) |
30 | { | 20 | { |
@@ -295,51 +285,6 @@ out: | |||
295 | static DEVICE_ATTR(canonical_macaddr, 0644, qeth_l3_dev_canonical_macaddr_show, | 285 | static DEVICE_ATTR(canonical_macaddr, 0644, qeth_l3_dev_canonical_macaddr_show, |
296 | qeth_l3_dev_canonical_macaddr_store); | 286 | qeth_l3_dev_canonical_macaddr_store); |
297 | 287 | ||
298 | static ssize_t qeth_l3_dev_checksum_show(struct device *dev, | ||
299 | struct device_attribute *attr, char *buf) | ||
300 | { | ||
301 | struct qeth_card *card = dev_get_drvdata(dev); | ||
302 | |||
303 | if (!card) | ||
304 | return -EINVAL; | ||
305 | |||
306 | return sprintf(buf, "%s checksumming\n", | ||
307 | qeth_l3_get_checksum_str(card)); | ||
308 | } | ||
309 | |||
310 | static ssize_t qeth_l3_dev_checksum_store(struct device *dev, | ||
311 | struct device_attribute *attr, const char *buf, size_t count) | ||
312 | { | ||
313 | struct qeth_card *card = dev_get_drvdata(dev); | ||
314 | enum qeth_checksum_types csum_type; | ||
315 | char *tmp; | ||
316 | int rc = 0; | ||
317 | |||
318 | if (!card) | ||
319 | return -EINVAL; | ||
320 | |||
321 | mutex_lock(&card->conf_mutex); | ||
322 | tmp = strsep((char **) &buf, "\n"); | ||
323 | if (!strcmp(tmp, "sw_checksumming")) | ||
324 | csum_type = SW_CHECKSUMMING; | ||
325 | else if (!strcmp(tmp, "hw_checksumming")) | ||
326 | csum_type = HW_CHECKSUMMING; | ||
327 | else if (!strcmp(tmp, "no_checksumming")) | ||
328 | csum_type = NO_CHECKSUMMING; | ||
329 | else { | ||
330 | rc = -EINVAL; | ||
331 | goto out; | ||
332 | } | ||
333 | |||
334 | rc = qeth_l3_set_rx_csum(card, csum_type); | ||
335 | out: | ||
336 | mutex_unlock(&card->conf_mutex); | ||
337 | return rc ? rc : count; | ||
338 | } | ||
339 | |||
340 | static DEVICE_ATTR(checksumming, 0644, qeth_l3_dev_checksum_show, | ||
341 | qeth_l3_dev_checksum_store); | ||
342 | |||
343 | static ssize_t qeth_l3_dev_sniffer_show(struct device *dev, | 288 | static ssize_t qeth_l3_dev_sniffer_show(struct device *dev, |
344 | struct device_attribute *attr, char *buf) | 289 | struct device_attribute *attr, char *buf) |
345 | { | 290 | { |
@@ -402,61 +347,13 @@ out: | |||
402 | static DEVICE_ATTR(sniffer, 0644, qeth_l3_dev_sniffer_show, | 347 | static DEVICE_ATTR(sniffer, 0644, qeth_l3_dev_sniffer_show, |
403 | qeth_l3_dev_sniffer_store); | 348 | qeth_l3_dev_sniffer_store); |
404 | 349 | ||
405 | static ssize_t qeth_l3_dev_large_send_show(struct device *dev, | ||
406 | struct device_attribute *attr, char *buf) | ||
407 | { | ||
408 | struct qeth_card *card = dev_get_drvdata(dev); | ||
409 | |||
410 | if (!card) | ||
411 | return -EINVAL; | ||
412 | |||
413 | switch (card->options.large_send) { | ||
414 | case QETH_LARGE_SEND_NO: | ||
415 | return sprintf(buf, "%s\n", "no"); | ||
416 | case QETH_LARGE_SEND_TSO: | ||
417 | return sprintf(buf, "%s\n", "TSO"); | ||
418 | default: | ||
419 | return sprintf(buf, "%s\n", "N/A"); | ||
420 | } | ||
421 | } | ||
422 | |||
423 | static ssize_t qeth_l3_dev_large_send_store(struct device *dev, | ||
424 | struct device_attribute *attr, const char *buf, size_t count) | ||
425 | { | ||
426 | struct qeth_card *card = dev_get_drvdata(dev); | ||
427 | enum qeth_large_send_types type; | ||
428 | int rc = 0; | ||
429 | char *tmp; | ||
430 | |||
431 | if (!card) | ||
432 | return -EINVAL; | ||
433 | tmp = strsep((char **) &buf, "\n"); | ||
434 | if (!strcmp(tmp, "no")) | ||
435 | type = QETH_LARGE_SEND_NO; | ||
436 | else if (!strcmp(tmp, "TSO")) | ||
437 | type = QETH_LARGE_SEND_TSO; | ||
438 | else | ||
439 | return -EINVAL; | ||
440 | |||
441 | mutex_lock(&card->conf_mutex); | ||
442 | if (card->options.large_send != type) | ||
443 | rc = qeth_l3_set_large_send(card, type); | ||
444 | mutex_unlock(&card->conf_mutex); | ||
445 | return rc ? rc : count; | ||
446 | } | ||
447 | |||
448 | static DEVICE_ATTR(large_send, 0644, qeth_l3_dev_large_send_show, | ||
449 | qeth_l3_dev_large_send_store); | ||
450 | |||
451 | static struct attribute *qeth_l3_device_attrs[] = { | 350 | static struct attribute *qeth_l3_device_attrs[] = { |
452 | &dev_attr_route4.attr, | 351 | &dev_attr_route4.attr, |
453 | &dev_attr_route6.attr, | 352 | &dev_attr_route6.attr, |
454 | &dev_attr_fake_broadcast.attr, | 353 | &dev_attr_fake_broadcast.attr, |
455 | &dev_attr_broadcast_mode.attr, | 354 | &dev_attr_broadcast_mode.attr, |
456 | &dev_attr_canonical_macaddr.attr, | 355 | &dev_attr_canonical_macaddr.attr, |
457 | &dev_attr_checksumming.attr, | ||
458 | &dev_attr_sniffer.attr, | 356 | &dev_attr_sniffer.attr, |
459 | &dev_attr_large_send.attr, | ||
460 | NULL, | 357 | NULL, |
461 | }; | 358 | }; |
462 | 359 | ||
diff --git a/drivers/s390/net/smsgiucv.c b/drivers/s390/net/smsgiucv.c index 65e1cf104943..207b7d742443 100644 --- a/drivers/s390/net/smsgiucv.c +++ b/drivers/s390/net/smsgiucv.c | |||
@@ -60,7 +60,7 @@ static struct iucv_handler smsg_handler = { | |||
60 | static int smsg_path_pending(struct iucv_path *path, u8 ipvmid[8], | 60 | static int smsg_path_pending(struct iucv_path *path, u8 ipvmid[8], |
61 | u8 ipuser[16]) | 61 | u8 ipuser[16]) |
62 | { | 62 | { |
63 | if (strncmp(ipvmid, "*MSG ", sizeof(ipvmid)) != 0) | 63 | if (strncmp(ipvmid, "*MSG ", 8) != 0) |
64 | return -EINVAL; | 64 | return -EINVAL; |
65 | /* Path pending from *MSG. */ | 65 | /* Path pending from *MSG. */ |
66 | return iucv_path_accept(path, &smsg_handler, "SMSGIUCV ", NULL); | 66 | return iucv_path_accept(path, &smsg_handler, "SMSGIUCV ", NULL); |