@@ -515,7 +515,9 @@ static int __qeth_issue_next_read(struct qeth_card *card)
515
515
516
516
QETH_CARD_TEXT (card , 6 , "noirqpnd" );
517
517
rc = ccw_device_start (channel -> ccwdev , ccw , (addr_t ) iob , 0 , 0 );
518
- if (rc ) {
518
+ if (!rc ) {
519
+ channel -> active_cmd = iob ;
520
+ } else {
519
521
QETH_DBF_MESSAGE (2 , "error %i on device %x when starting next read ccw!\n" ,
520
522
rc , CARD_DEVID (card ));
521
523
atomic_set (& channel -> irq_pending , 0 );
@@ -986,8 +988,21 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
986
988
QETH_CARD_TEXT (card , 5 , "data" );
987
989
}
988
990
989
- if (qeth_intparm_is_iob (intparm ))
990
- iob = (struct qeth_cmd_buffer * ) __va ((addr_t )intparm );
991
+ if (intparm == 0 ) {
992
+ QETH_CARD_TEXT (card , 5 , "irqunsol" );
993
+ } else if ((addr_t )intparm != (addr_t )channel -> active_cmd ) {
994
+ QETH_CARD_TEXT (card , 5 , "irqunexp" );
995
+
996
+ dev_err (& cdev -> dev ,
997
+ "Received IRQ with intparm %lx, expected %px\n" ,
998
+ intparm , channel -> active_cmd );
999
+ if (channel -> active_cmd )
1000
+ qeth_cancel_cmd (channel -> active_cmd , - EIO );
1001
+ } else {
1002
+ iob = (struct qeth_cmd_buffer * ) (addr_t )intparm ;
1003
+ }
1004
+
1005
+ channel -> active_cmd = NULL ;
991
1006
992
1007
rc = qeth_check_irb_error (card , cdev , irb );
993
1008
if (rc ) {
@@ -1007,15 +1022,10 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
1007
1022
if (irb -> scsw .cmd .fctl & (SCSW_FCTL_HALT_FUNC ))
1008
1023
channel -> state = CH_STATE_HALTED ;
1009
1024
1010
- if (intparm == QETH_CLEAR_CHANNEL_PARM ) {
1011
- QETH_CARD_TEXT (card , 6 , "clrchpar" );
1012
- /* we don't have to handle this further */
1013
- intparm = 0 ;
1014
- }
1015
- if (intparm == QETH_HALT_CHANNEL_PARM ) {
1016
- QETH_CARD_TEXT (card , 6 , "hltchpar" );
1017
- /* we don't have to handle this further */
1018
- intparm = 0 ;
1025
+ if (iob && (irb -> scsw .cmd .fctl & (SCSW_FCTL_CLEAR_FUNC |
1026
+ SCSW_FCTL_HALT_FUNC ))) {
1027
+ qeth_cancel_cmd (iob , - ECANCELED );
1028
+ iob = NULL ;
1019
1029
}
1020
1030
1021
1031
cstat = irb -> scsw .cmd .cstat ;
@@ -1408,7 +1418,7 @@ static int qeth_clear_channel(struct qeth_card *card,
1408
1418
1409
1419
QETH_CARD_TEXT (card , 3 , "clearch" );
1410
1420
spin_lock_irq (get_ccwdev_lock (channel -> ccwdev ));
1411
- rc = ccw_device_clear (channel -> ccwdev , QETH_CLEAR_CHANNEL_PARM );
1421
+ rc = ccw_device_clear (channel -> ccwdev , ( addr_t ) channel -> active_cmd );
1412
1422
spin_unlock_irq (get_ccwdev_lock (channel -> ccwdev ));
1413
1423
1414
1424
if (rc )
@@ -1430,7 +1440,7 @@ static int qeth_halt_channel(struct qeth_card *card,
1430
1440
1431
1441
QETH_CARD_TEXT (card , 3 , "haltch" );
1432
1442
spin_lock_irq (get_ccwdev_lock (channel -> ccwdev ));
1433
- rc = ccw_device_halt (channel -> ccwdev , QETH_HALT_CHANNEL_PARM );
1443
+ rc = ccw_device_halt (channel -> ccwdev , ( addr_t ) channel -> active_cmd );
1434
1444
spin_unlock_irq (get_ccwdev_lock (channel -> ccwdev ));
1435
1445
1436
1446
if (rc )
@@ -1444,6 +1454,25 @@ static int qeth_halt_channel(struct qeth_card *card,
1444
1454
return 0 ;
1445
1455
}
1446
1456
1457
+ int qeth_stop_channel (struct qeth_channel * channel )
1458
+ {
1459
+ struct ccw_device * cdev = channel -> ccwdev ;
1460
+ int rc ;
1461
+
1462
+ rc = ccw_device_set_offline (cdev );
1463
+
1464
+ spin_lock_irq (get_ccwdev_lock (cdev ));
1465
+ if (channel -> active_cmd ) {
1466
+ dev_err (& cdev -> dev , "Stopped channel while cmd %px was still active\n" ,
1467
+ channel -> active_cmd );
1468
+ channel -> active_cmd = NULL ;
1469
+ }
1470
+ spin_unlock_irq (get_ccwdev_lock (cdev ));
1471
+
1472
+ return rc ;
1473
+ }
1474
+ EXPORT_SYMBOL_GPL (qeth_stop_channel );
1475
+
1447
1476
static int qeth_halt_channels (struct qeth_card * card )
1448
1477
{
1449
1478
int rc1 = 0 , rc2 = 0 , rc3 = 0 ;
@@ -1746,6 +1775,8 @@ static int qeth_send_control_data(struct qeth_card *card,
1746
1775
spin_lock_irq (get_ccwdev_lock (channel -> ccwdev ));
1747
1776
rc = ccw_device_start_timeout (channel -> ccwdev , __ccw_from_cmd (iob ),
1748
1777
(addr_t ) iob , 0 , 0 , timeout );
1778
+ if (!rc )
1779
+ channel -> active_cmd = iob ;
1749
1780
spin_unlock_irq (get_ccwdev_lock (channel -> ccwdev ));
1750
1781
if (rc ) {
1751
1782
QETH_DBF_MESSAGE (2 , "qeth_send_control_data on device %x: ccw_device_start rc = %i\n" ,
@@ -4667,12 +4698,12 @@ EXPORT_SYMBOL_GPL(qeth_vm_request_mac);
4667
4698
4668
4699
static void qeth_determine_capabilities (struct qeth_card * card )
4669
4700
{
4701
+ struct qeth_channel * channel = & card -> data ;
4702
+ struct ccw_device * ddev = channel -> ccwdev ;
4670
4703
int rc ;
4671
- struct ccw_device * ddev ;
4672
4704
int ddev_offline = 0 ;
4673
4705
4674
4706
QETH_CARD_TEXT (card , 2 , "detcapab" );
4675
- ddev = CARD_DDEV (card );
4676
4707
if (!ddev -> online ) {
4677
4708
ddev_offline = 1 ;
4678
4709
rc = ccw_device_set_online (ddev );
@@ -4711,7 +4742,7 @@ static void qeth_determine_capabilities(struct qeth_card *card)
4711
4742
4712
4743
out_offline :
4713
4744
if (ddev_offline == 1 )
4714
- ccw_device_set_offline ( ddev );
4745
+ qeth_stop_channel ( channel );
4715
4746
out :
4716
4747
return ;
4717
4748
}
@@ -4911,9 +4942,9 @@ int qeth_core_hardsetup_card(struct qeth_card *card, bool *carrier_ok)
4911
4942
QETH_DBF_MESSAGE (2 , "Retrying to do IDX activates on device %x.\n" ,
4912
4943
CARD_DEVID (card ));
4913
4944
rc = qeth_qdio_clear_card (card , !IS_IQD (card ));
4914
- ccw_device_set_offline ( CARD_DDEV ( card ) );
4915
- ccw_device_set_offline ( CARD_WDEV ( card ) );
4916
- ccw_device_set_offline ( CARD_RDEV ( card ) );
4945
+ qeth_stop_channel ( & card -> data );
4946
+ qeth_stop_channel ( & card -> write );
4947
+ qeth_stop_channel ( & card -> read );
4917
4948
qdio_free (CARD_DDEV (card ));
4918
4949
rc = ccw_device_set_online (CARD_RDEV (card ));
4919
4950
if (rc )
@@ -5028,27 +5059,15 @@ int qeth_core_hardsetup_card(struct qeth_card *card, bool *carrier_ok)
5028
5059
}
5029
5060
EXPORT_SYMBOL_GPL (qeth_core_hardsetup_card );
5030
5061
5031
- static void qeth_create_skb_frag (struct qdio_buffer_element * element ,
5032
- struct sk_buff * skb , int offset , int data_len )
5062
+ static void qeth_create_skb_frag (struct sk_buff * skb , char * data , int data_len )
5033
5063
{
5034
- struct page * page = virt_to_page (element -> addr );
5064
+ struct page * page = virt_to_page (data );
5035
5065
unsigned int next_frag ;
5036
5066
5037
- /* first fill the linear space */
5038
- if (!skb -> len ) {
5039
- unsigned int linear = min (data_len , skb_tailroom (skb ));
5040
-
5041
- skb_put_data (skb , element -> addr + offset , linear );
5042
- data_len -= linear ;
5043
- if (!data_len )
5044
- return ;
5045
- offset += linear ;
5046
- /* fall through to add page frag for remaining data */
5047
- }
5048
-
5049
5067
next_frag = skb_shinfo (skb )-> nr_frags ;
5050
5068
get_page (page );
5051
- skb_add_rx_frag (skb , next_frag , page , offset , data_len , data_len );
5069
+ skb_add_rx_frag (skb , next_frag , page , offset_in_page (data ), data_len ,
5070
+ data_len );
5052
5071
}
5053
5072
5054
5073
static inline int qeth_is_last_sbale (struct qdio_buffer_element * sbale )
@@ -5063,13 +5082,12 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card,
5063
5082
{
5064
5083
struct qdio_buffer_element * element = * __element ;
5065
5084
struct qdio_buffer * buffer = qethbuffer -> buffer ;
5085
+ unsigned int linear_len = 0 ;
5066
5086
int offset = * __offset ;
5067
5087
bool use_rx_sg = false;
5068
5088
unsigned int headroom ;
5069
5089
struct sk_buff * skb ;
5070
5090
int skb_len = 0 ;
5071
- void * data_ptr ;
5072
- int data_len ;
5073
5091
5074
5092
next_packet :
5075
5093
/* qeth_hdr must not cross element boundaries */
@@ -5082,29 +5100,41 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card,
5082
5100
* hdr = element -> addr + offset ;
5083
5101
5084
5102
offset += sizeof (struct qeth_hdr );
5103
+ skb = NULL ;
5104
+
5085
5105
switch ((* hdr )-> hdr .l2 .id ) {
5086
5106
case QETH_HEADER_TYPE_LAYER2 :
5087
5107
skb_len = (* hdr )-> hdr .l2 .pkt_length ;
5108
+ linear_len = ETH_HLEN ;
5088
5109
headroom = 0 ;
5089
5110
break ;
5090
5111
case QETH_HEADER_TYPE_LAYER3 :
5091
5112
skb_len = (* hdr )-> hdr .l3 .length ;
5092
5113
if (!IS_LAYER3 (card )) {
5093
5114
QETH_CARD_STAT_INC (card , rx_dropped_notsupp );
5094
- skb = NULL ;
5095
5115
goto walk_packet ;
5096
5116
}
5097
5117
5118
+ if ((* hdr )-> hdr .l3 .flags & QETH_HDR_PASSTHRU ) {
5119
+ linear_len = ETH_HLEN ;
5120
+ headroom = 0 ;
5121
+ break ;
5122
+ }
5123
+
5124
+ if ((* hdr )-> hdr .l3 .flags & QETH_HDR_IPV6 )
5125
+ linear_len = sizeof (struct ipv6hdr );
5126
+ else
5127
+ linear_len = sizeof (struct iphdr );
5098
5128
headroom = ETH_HLEN ;
5099
5129
break ;
5100
5130
case QETH_HEADER_TYPE_OSN :
5101
5131
skb_len = (* hdr )-> hdr .osn .pdu_length ;
5102
5132
if (!IS_OSN (card )) {
5103
5133
QETH_CARD_STAT_INC (card , rx_dropped_notsupp );
5104
- skb = NULL ;
5105
5134
goto walk_packet ;
5106
5135
}
5107
5136
5137
+ linear_len = skb_len ;
5108
5138
headroom = sizeof (struct qeth_hdr );
5109
5139
break ;
5110
5140
default :
@@ -5117,8 +5147,10 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card,
5117
5147
return NULL ;
5118
5148
}
5119
5149
5120
- if (!skb_len )
5121
- return NULL ;
5150
+ if (skb_len < linear_len ) {
5151
+ QETH_CARD_STAT_INC (card , rx_dropped_runt );
5152
+ goto walk_packet ;
5153
+ }
5122
5154
5123
5155
use_rx_sg = (card -> options .cq == QETH_CQ_ENABLED ) ||
5124
5156
((skb_len >= card -> options .rx_sg_cb ) &&
@@ -5130,9 +5162,9 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card,
5130
5162
skb = qethbuffer -> rx_skb ;
5131
5163
qethbuffer -> rx_skb = NULL ;
5132
5164
} else {
5133
- unsigned int linear = ( use_rx_sg ) ? QETH_RX_PULL_LEN : skb_len ;
5134
-
5135
- skb = napi_alloc_skb (& card -> napi , linear + headroom );
5165
+ if (! use_rx_sg )
5166
+ linear_len = skb_len ;
5167
+ skb = napi_alloc_skb (& card -> napi , linear_len + headroom );
5136
5168
}
5137
5169
5138
5170
if (!skb )
@@ -5141,18 +5173,32 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card,
5141
5173
skb_reserve (skb , headroom );
5142
5174
5143
5175
walk_packet :
5144
- data_ptr = element -> addr + offset ;
5145
5176
while (skb_len ) {
5146
- data_len = min (skb_len , (int )(element -> length - offset ));
5177
+ int data_len = min (skb_len , (int )(element -> length - offset ));
5178
+ char * data = element -> addr + offset ;
5179
+
5180
+ skb_len -= data_len ;
5181
+ offset += data_len ;
5147
5182
5183
+ /* Extract data from current element: */
5148
5184
if (skb && data_len ) {
5149
- if (use_rx_sg )
5150
- qeth_create_skb_frag (element , skb , offset ,
5151
- data_len );
5152
- else
5153
- skb_put_data (skb , data_ptr , data_len );
5185
+ if (linear_len ) {
5186
+ unsigned int copy_len ;
5187
+
5188
+ copy_len = min_t (unsigned int , linear_len ,
5189
+ data_len );
5190
+
5191
+ skb_put_data (skb , data , copy_len );
5192
+ linear_len -= copy_len ;
5193
+ data_len -= copy_len ;
5194
+ data += copy_len ;
5195
+ }
5196
+
5197
+ if (data_len )
5198
+ qeth_create_skb_frag (skb , data , data_len );
5154
5199
}
5155
- skb_len -= data_len ;
5200
+
5201
+ /* Step forward to next element: */
5156
5202
if (skb_len ) {
5157
5203
if (qeth_is_last_sbale (element )) {
5158
5204
QETH_CARD_TEXT (card , 4 , "unexeob" );
@@ -5166,9 +5212,6 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card,
5166
5212
}
5167
5213
element ++ ;
5168
5214
offset = 0 ;
5169
- data_ptr = element -> addr ;
5170
- } else {
5171
- offset += data_len ;
5172
5215
}
5173
5216
}
5174
5217
@@ -6268,7 +6311,8 @@ void qeth_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
6268
6311
card -> stats .rx_frame_errors +
6269
6312
card -> stats .rx_fifo_errors ;
6270
6313
stats -> rx_dropped = card -> stats .rx_dropped_nomem +
6271
- card -> stats .rx_dropped_notsupp ;
6314
+ card -> stats .rx_dropped_notsupp +
6315
+ card -> stats .rx_dropped_runt ;
6272
6316
stats -> multicast = card -> stats .rx_multicast ;
6273
6317
stats -> rx_length_errors = card -> stats .rx_length_errors ;
6274
6318
stats -> rx_frame_errors = card -> stats .rx_frame_errors ;
0 commit comments