diff options
Diffstat (limited to 'drivers/s390/net/qeth_core_main.c')
| -rw-r--r-- | drivers/s390/net/qeth_core_main.c | 57 | 
1 files changed, 43 insertions, 14 deletions
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index e783644a210..6811dd529f4 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -287,8 +287,15 @@ int qeth_set_large_send(struct qeth_card *card,  	card->options.large_send = type;  	switch (card->options.large_send) {  	case QETH_LARGE_SEND_EDDP: -		card->dev->features |= NETIF_F_TSO | NETIF_F_SG | +		if (card->info.type != QETH_CARD_TYPE_IQD) { +			card->dev->features |= NETIF_F_TSO | NETIF_F_SG |  					NETIF_F_HW_CSUM; +		} else { +			card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG | +						NETIF_F_HW_CSUM); +			card->options.large_send = QETH_LARGE_SEND_NO; +			rc = -EOPNOTSUPP; +		}  		break;  	case QETH_LARGE_SEND_TSO:  		if (qeth_is_supported(card, IPA_OUTBOUND_TSO)) { @@ -572,6 +579,10 @@ static void qeth_send_control_data_cb(struct qeth_channel *channel,  	card = CARD_FROM_CDEV(channel->ccwdev);  	if (qeth_check_idx_response(iob->data)) {  		qeth_clear_ipacmd_list(card); +		if (((iob->data[2] & 0xc0) == 0xc0) && iob->data[4] == 0xf6) +			dev_err(&card->gdev->dev, +				"The qeth device is not configured " +				"for the OSI layer required by z/VM\n");  		qeth_schedule_recovery(card);  		goto out;  	} @@ -1072,7 +1083,6 @@ static void qeth_set_intial_options(struct qeth_card *card)  	card->options.macaddr_mode = QETH_TR_MACADDR_NONCANONICAL;  	card->options.fake_broadcast = 0;  	card->options.add_hhlen = DEFAULT_ADD_HHLEN; -	card->options.fake_ll = 0;  	card->options.performance_stats = 0;  	card->options.rx_sg_cb = QETH_RX_SG_CB;  } @@ -1682,6 +1692,7 @@ int qeth_send_control_data(struct qeth_card *card, int len,  	unsigned long flags;  	struct qeth_reply *reply = NULL;  	unsigned long timeout; +	struct qeth_ipa_cmd *cmd;  	QETH_DBF_TEXT(TRACE, 2, "sendctl"); @@ -1728,17 +1739,34 @@ int qeth_send_control_data(struct qeth_card *card, int len,  		wake_up(&card->wait_q);  		return rc;  	} -	while (!atomic_read(&reply->received)) { -		if (time_after(jiffies, timeout)) { -			spin_lock_irqsave(&reply->card->lock, flags); -			list_del_init(&reply->list); -			spin_unlock_irqrestore(&reply->card->lock, flags); -			reply->rc = -ETIME; -			atomic_inc(&reply->received); -			wake_up(&reply->wait_q); -		} -		cpu_relax(); -	}; + +	/* we have only one long running ipassist, since we can ensure +	   process context of this command we can sleep */ +	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); +	if ((cmd->hdr.command == IPA_CMD_SETIP) && +	    (cmd->hdr.prot_version == QETH_PROT_IPV4)) { +		if (!wait_event_timeout(reply->wait_q, +		    atomic_read(&reply->received), timeout)) +			goto time_err; +	} else { +		while (!atomic_read(&reply->received)) { +			if (time_after(jiffies, timeout)) +				goto time_err; +			cpu_relax(); +		}; +	} + +	rc = reply->rc; +	qeth_put_reply(reply); +	return rc; + +time_err: +	spin_lock_irqsave(&reply->card->lock, flags); +	list_del_init(&reply->list); +	spin_unlock_irqrestore(&reply->card->lock, flags); +	reply->rc = -ETIME; +	atomic_inc(&reply->received); +	wake_up(&reply->wait_q);  	rc = reply->rc;  	qeth_put_reply(reply);  	return rc; @@ -2250,7 +2278,8 @@ void qeth_print_status_message(struct qeth_card *card)  		}  		/* fallthrough */  	case QETH_CARD_TYPE_IQD: -		if (card->info.guestlan) { +		if ((card->info.guestlan) || +		    (card->info.mcl_level[0] & 0x80)) {  			card->info.mcl_level[0] = (char) _ebcasc[(__u8)  				card->info.mcl_level[0]];  			card->info.mcl_level[1] = (char) _ebcasc[(__u8)  | 
