forked from mirrors/linux
		
	 4b7ae12216
			
		
	
	
		4b7ae12216
		
	
	
	
	
		
			
			Error propagation from cmd callbacks currently works in a way where
qeth_send_control_data_cb() picks the raw HW code from the response,
and the cmd's originator later translates this into an errno.
The callback itself only returns 0 ("done") or 1 ("expect more data").
This is
1. limiting, as the only means for the callback to report an internal
error is to invent pseudo HW codes (such as IPA_RC_ENOMEM), that
the originator then needs to understand. For non-IPA callbacks, we
even provide a separate field in the IO buffer metadata (iob->rc) so
the callback can pass back a return value.
2. fragile, as the originator must take care to not translate any errno
that is returned by qeth's own IO code paths (eg -ENOMEM). Also, any
originator that forgets to translate the HW codes potentially passes
garbage back to its caller. For instance, see
commit 2aa4867198 ("s390/qeth: translate SETVLAN/DELVLAN errors").
Introduce a new model where all HW error translation is done within the
callback, and the callback returns
>  0, if it expects more data (as before)
== 0, on success
<  0, with an errno
Start off with converting all callbacks to the new model that either
a) pass back pseudo HW codes, or b) have a dependency on a specific
HW error code. Also convert c) the one callback that uses iob->rc, and
d) qeth_setadpparms_change_macaddr_cb() so that it can pass back an
error back to qeth_l2_request_initial_mac() even when the cmd itself
was successful.
The old model remains supported: if the callback returns 0, we still
propagate the response's HW error code back to the originator.
Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
		
	
			
		
			
				
	
	
		
			264 lines
		
	
	
	
		
			9.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			264 lines
		
	
	
	
		
			9.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| // SPDX-License-Identifier: GPL-2.0
 | |
| /*
 | |
|  *    Copyright IBM Corp. 2007
 | |
|  *    Author(s): Frank Pavlic <fpavlic@de.ibm.com>,
 | |
|  *		 Thomas Spatzier <tspat@de.ibm.com>,
 | |
|  *		 Frank Blaschka <frank.blaschka@de.ibm.com>
 | |
|  */
 | |
| 
 | |
| #include <linux/module.h>
 | |
| #include <asm/cio.h>
 | |
| #include "qeth_core_mpc.h"
 | |
| 
 | |
| unsigned char IDX_ACTIVATE_READ[] = {
 | |
| 	0x00, 0x00, 0x80, 0x00,  0x00, 0x00, 0x00, 0x00,
 | |
| 	0x19, 0x01, 0x01, 0x80,  0x00, 0x00, 0x00, 0x00,
 | |
| 	0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0xc8, 0xc1,
 | |
| 	0xd3, 0xd3, 0xd6, 0xd3,  0xc5, 0x40, 0x00, 0x00,
 | |
| 	0x00, 0x00
 | |
| };
 | |
| 
 | |
| unsigned char IDX_ACTIVATE_WRITE[] = {
 | |
| 	0x00, 0x00, 0x80, 0x00,  0x00, 0x00, 0x00, 0x00,
 | |
| 	0x15, 0x01, 0x01, 0x80,  0x00, 0x00, 0x00, 0x00,
 | |
| 	0xff, 0xff, 0x00, 0x00,  0x00, 0x00, 0xc8, 0xc1,
 | |
| 	0xd3, 0xd3, 0xd6, 0xd3,  0xc5, 0x40, 0x00, 0x00,
 | |
| 	0x00, 0x00
 | |
| };
 | |
| 
 | |
| unsigned char CM_ENABLE[] = {
 | |
| 	0x00, 0xe0, 0x00, 0x00,  0x00, 0x00, 0x00, 0x01,
 | |
| 	0x00, 0x00, 0x00, 0x14,  0x00, 0x00, 0x00, 0x63,
 | |
| 	0x10, 0x00, 0x00, 0x01,
 | |
| 	0x00, 0x00, 0x00, 0x00,
 | |
| 	0x81, 0x7e, 0x00, 0x01,  0x00, 0x00, 0x00, 0x00,
 | |
| 	0x00, 0x00, 0x00, 0x00,  0x00, 0x24, 0x00, 0x23,
 | |
| 	0x00, 0x00, 0x23, 0x05,  0x00, 0x00, 0x00, 0x00,
 | |
| 	0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
 | |
| 	0x01, 0x00, 0x00, 0x23,  0x00, 0x00, 0x00, 0x40,
 | |
| 	0x00, 0x0c, 0x41, 0x02,  0x00, 0x17, 0x00, 0x00,
 | |
| 	0x00, 0x00, 0x00, 0x00,
 | |
| 	0x00, 0x0b, 0x04, 0x01,
 | |
| 	0x7e, 0x04, 0x05, 0x00,  0x01, 0x01, 0x0f,
 | |
| 	0x00,
 | |
| 	0x0c, 0x04, 0x02, 0xff,  0xff, 0xff, 0xff, 0xff,
 | |
| 	0xff, 0xff, 0xff
 | |
| };
 | |
| 
 | |
| unsigned char CM_SETUP[] = {
 | |
| 	0x00, 0xe0, 0x00, 0x00,  0x00, 0x00, 0x00, 0x02,
 | |
| 	0x00, 0x00, 0x00, 0x14,  0x00, 0x00, 0x00, 0x64,
 | |
| 	0x10, 0x00, 0x00, 0x01,
 | |
| 	0x00, 0x00, 0x00, 0x00,
 | |
| 	0x81, 0x7e, 0x00, 0x01,  0x00, 0x00, 0x00, 0x00,
 | |
| 	0x00, 0x00, 0x00, 0x00,  0x00, 0x24, 0x00, 0x24,
 | |
| 	0x00, 0x00, 0x24, 0x05,  0x00, 0x00, 0x00, 0x00,
 | |
| 	0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
 | |
| 	0x01, 0x00, 0x00, 0x24,  0x00, 0x00, 0x00, 0x40,
 | |
| 	0x00, 0x0c, 0x41, 0x04,  0x00, 0x18, 0x00, 0x00,
 | |
| 	0x00, 0x00, 0x00, 0x00,
 | |
| 	0x00, 0x09, 0x04, 0x04,
 | |
| 	0x05, 0x00, 0x01, 0x01,  0x11,
 | |
| 	0x00, 0x09, 0x04,
 | |
| 	0x05, 0x05, 0x00, 0x00,  0x00, 0x00,
 | |
| 	0x00, 0x06,
 | |
| 	0x04, 0x06, 0xc8, 0x00
 | |
| };
 | |
| 
 | |
| unsigned char ULP_ENABLE[] = {
 | |
| 	0x00, 0xe0, 0x00, 0x00,  0x00, 0x00, 0x00, 0x03,
 | |
| 	0x00, 0x00, 0x00, 0x14,  0x00, 0x00, 0x00, 0x6b,
 | |
| 	0x10, 0x00, 0x00, 0x01,
 | |
| 	0x00, 0x00, 0x00, 0x00,
 | |
| 	0x41, 0x7e, 0x00, 0x01,  0x00, 0x00, 0x00, 0x01,
 | |
| 	0x00, 0x00, 0x00, 0x00,  0x00, 0x24, 0x00, 0x2b,
 | |
| 	0x00, 0x00, 0x2b, 0x05,  0x20, 0x01, 0x00, 0x00,
 | |
| 	0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
 | |
| 	0x01, 0x00, 0x00, 0x2b,  0x00, 0x00, 0x00, 0x40,
 | |
| 	0x00, 0x0c, 0x41, 0x02,  0x00, 0x1f, 0x00, 0x00,
 | |
| 	0x00, 0x00, 0x00, 0x00,
 | |
| 	0x00, 0x0b, 0x04, 0x01,
 | |
| 	0x03, 0x04, 0x05, 0x00,  0x01, 0x01, 0x12,
 | |
| 	0x00,
 | |
| 	0x14, 0x04, 0x0a, 0x00,  0x20, 0x00, 0x00, 0xff,
 | |
| 	0xff, 0x00, 0x08, 0xc8,  0xe8, 0xc4, 0xf1, 0xc7,
 | |
| 	0xf1, 0x00, 0x00
 | |
| };
 | |
| 
 | |
| unsigned char ULP_SETUP[] = {
 | |
| 	0x00, 0xe0, 0x00, 0x00,  0x00, 0x00, 0x00, 0x04,
 | |
| 	0x00, 0x00, 0x00, 0x14,  0x00, 0x00, 0x00, 0x6c,
 | |
| 	0x10, 0x00, 0x00, 0x01,
 | |
| 	0x00, 0x00, 0x00, 0x00,
 | |
| 	0x41, 0x7e, 0x00, 0x01,  0x00, 0x00, 0x00, 0x02,
 | |
| 	0x00, 0x00, 0x00, 0x01,  0x00, 0x24, 0x00, 0x2c,
 | |
| 	0x00, 0x00, 0x2c, 0x05,  0x20, 0x01, 0x00, 0x00,
 | |
| 	0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
 | |
| 	0x01, 0x00, 0x00, 0x2c,  0x00, 0x00, 0x00, 0x40,
 | |
| 	0x00, 0x0c, 0x41, 0x04,  0x00, 0x20, 0x00, 0x00,
 | |
| 	0x00, 0x00, 0x00, 0x00,
 | |
| 	0x00, 0x09, 0x04, 0x04,
 | |
| 	0x05, 0x00, 0x01, 0x01,  0x14,
 | |
| 	0x00, 0x09, 0x04,
 | |
| 	0x05, 0x05, 0x30, 0x01,  0x00, 0x00,
 | |
| 	0x00, 0x06,
 | |
| 	0x04, 0x06, 0x40, 0x00,
 | |
| 	0x00, 0x08, 0x04, 0x0b,
 | |
| 	0x00, 0x00, 0x00, 0x00
 | |
| };
 | |
| 
 | |
| unsigned char DM_ACT[] = {
 | |
| 	0x00, 0xe0, 0x00, 0x00,  0x00, 0x00, 0x00, 0x05,
 | |
| 	0x00, 0x00, 0x00, 0x14,  0x00, 0x00, 0x00, 0x55,
 | |
| 	0x10, 0x00, 0x00, 0x01,
 | |
| 	0x00, 0x00, 0x00, 0x00,
 | |
| 	0x41, 0x7e, 0x00, 0x01,  0x00, 0x00, 0x00, 0x03,
 | |
| 	0x00, 0x00, 0x00, 0x02,  0x00, 0x24, 0x00, 0x15,
 | |
| 	0x00, 0x00, 0x2c, 0x05,  0x20, 0x01, 0x00, 0x00,
 | |
| 	0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
 | |
| 	0x01, 0x00, 0x00, 0x15,  0x00, 0x00, 0x00, 0x40,
 | |
| 	0x00, 0x0c, 0x43, 0x60,  0x00, 0x09, 0x00, 0x00,
 | |
| 	0x00, 0x00, 0x00, 0x00,
 | |
| 	0x00, 0x09, 0x04, 0x04,
 | |
| 	0x05, 0x40, 0x01, 0x01,  0x00
 | |
| };
 | |
| 
 | |
| unsigned char IPA_PDU_HEADER[] = {
 | |
| 	0x00, 0xe0, 0x00, 0x00,  0x77, 0x77, 0x77, 0x77,
 | |
| 	0x00, 0x00, 0x00, 0x14,  0x00, 0x00, 0x00, 0x00,
 | |
| 	0x10, 0x00, 0x00, 0x01,  0x00, 0x00, 0x00, 0x00,
 | |
| 	0xc1, 0x03, 0x00, 0x01,  0x00, 0x00, 0x00, 0x00,
 | |
| 	0x00, 0x00, 0x00, 0x00,  0x00, 0x24, 0x00, 0x00,
 | |
| 	0x00, 0x00, 0x00, 0x05,  0x77, 0x77, 0x77, 0x77,
 | |
| 	0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
 | |
| 	0x01, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x40,
 | |
| };
 | |
| 
 | |
| struct ipa_rc_msg {
 | |
| 	enum qeth_ipa_return_codes rc;
 | |
| 	const char *msg;
 | |
| };
 | |
| 
 | |
| static const struct ipa_rc_msg qeth_ipa_rc_msg[] = {
 | |
| 	{IPA_RC_SUCCESS,		"success"},
 | |
| 	{IPA_RC_NOTSUPP,		"Command not supported"},
 | |
| 	{IPA_RC_IP_TABLE_FULL,		"Add Addr IP Table Full - ipv6"},
 | |
| 	{IPA_RC_UNKNOWN_ERROR,		"IPA command failed - reason unknown"},
 | |
| 	{IPA_RC_UNSUPPORTED_COMMAND,	"Command not supported"},
 | |
| 	{IPA_RC_VNICC_OOSEQ,		"Command issued out of sequence"},
 | |
| 	{IPA_RC_INVALID_FORMAT,		"invalid format or length"},
 | |
| 	{IPA_RC_DUP_IPV6_REMOTE, "ipv6 address already registered remote"},
 | |
| 	{IPA_RC_SBP_IQD_NOT_CONFIGURED,	"Not configured for bridgeport"},
 | |
| 	{IPA_RC_DUP_IPV6_HOME,		"ipv6 address already registered"},
 | |
| 	{IPA_RC_UNREGISTERED_ADDR,	"Address not registered"},
 | |
| 	{IPA_RC_NO_ID_AVAILABLE,	"No identifiers available"},
 | |
| 	{IPA_RC_ID_NOT_FOUND,		"Identifier not found"},
 | |
| 	{IPA_RC_SBP_IQD_ANO_DEV_PRIMARY, "Primary bridgeport exists already"},
 | |
| 	{IPA_RC_SBP_IQD_CURRENT_SECOND,	"Bridgeport is currently secondary"},
 | |
| 	{IPA_RC_SBP_IQD_LIMIT_SECOND, "Limit of secondary bridgeports reached"},
 | |
| 	{IPA_RC_INVALID_IP_VERSION,	"IP version incorrect"},
 | |
| 	{IPA_RC_SBP_IQD_CURRENT_PRIMARY, "Bridgeport is currently primary"},
 | |
| 	{IPA_RC_LAN_FRAME_MISMATCH,	"LAN and frame mismatch"},
 | |
| 	{IPA_RC_SBP_IQD_NO_QDIO_QUEUES,	"QDIO queues not established"},
 | |
| 	{IPA_RC_L2_UNSUPPORTED_CMD,	"Unsupported layer 2 command"},
 | |
| 	{IPA_RC_L2_DUP_MAC,		"Duplicate MAC address"},
 | |
| 	{IPA_RC_L2_ADDR_TABLE_FULL,	"Layer2 address table full"},
 | |
| 	{IPA_RC_L2_DUP_LAYER3_MAC,	"Duplicate with layer 3 MAC"},
 | |
| 	{IPA_RC_L2_GMAC_NOT_FOUND,	"GMAC not found"},
 | |
| 	{IPA_RC_L2_MAC_NOT_AUTH_BY_HYP,	"L2 mac not authorized by hypervisor"},
 | |
| 	{IPA_RC_L2_MAC_NOT_AUTH_BY_ADP,	"L2 mac not authorized by adapter"},
 | |
| 	{IPA_RC_L2_MAC_NOT_FOUND,	"L2 mac address not found"},
 | |
| 	{IPA_RC_L2_INVALID_VLAN_ID,	"L2 invalid vlan id"},
 | |
| 	{IPA_RC_L2_DUP_VLAN_ID,		"L2 duplicate vlan id"},
 | |
| 	{IPA_RC_L2_VLAN_ID_NOT_FOUND,	"L2 vlan id not found"},
 | |
| 	{IPA_RC_VNICC_VNICBP,		"VNIC is BridgePort"},
 | |
| 	{IPA_RC_SBP_OSA_NOT_CONFIGURED,	"Not configured for bridgeport"},
 | |
| 	{IPA_RC_SBP_OSA_OS_MISMATCH,	"OS mismatch"},
 | |
| 	{IPA_RC_SBP_OSA_ANO_DEV_PRIMARY, "Primary bridgeport exists already"},
 | |
| 	{IPA_RC_SBP_OSA_CURRENT_SECOND,	"Bridgeport is currently secondary"},
 | |
| 	{IPA_RC_SBP_OSA_LIMIT_SECOND, "Limit of secondary bridgeports reached"},
 | |
| 	{IPA_RC_SBP_OSA_NOT_AUTHD_BY_ZMAN, "Not authorized by zManager"},
 | |
| 	{IPA_RC_SBP_OSA_CURRENT_PRIMARY, "Bridgeport is currently primary"},
 | |
| 	{IPA_RC_SBP_OSA_NO_QDIO_QUEUES,	"QDIO queues not established"},
 | |
| 	{IPA_RC_DATA_MISMATCH,		"Data field mismatch (v4/v6 mixed)"},
 | |
| 	{IPA_RC_INVALID_MTU_SIZE,	"Invalid MTU size"},
 | |
| 	{IPA_RC_INVALID_LANTYPE,	"Invalid LAN type"},
 | |
| 	{IPA_RC_INVALID_LANNUM,		"Invalid LAN num"},
 | |
| 	{IPA_RC_DUPLICATE_IP_ADDRESS,	"Address already registered"},
 | |
| 	{IPA_RC_IP_ADDR_TABLE_FULL,	"IP address table full"},
 | |
| 	{IPA_RC_LAN_PORT_STATE_ERROR,	"LAN port state error"},
 | |
| 	{IPA_RC_SETIP_NO_STARTLAN,	"Setip no startlan received"},
 | |
| 	{IPA_RC_SETIP_ALREADY_RECEIVED,	"Setip already received"},
 | |
| 	{IPA_RC_IP_ADDR_ALREADY_USED,	"IP address already in use on LAN"},
 | |
| 	{IPA_RC_MC_ADDR_NOT_FOUND,	"Multicast address not found"},
 | |
| 	{IPA_RC_SETIP_INVALID_VERSION,	"SETIP invalid IP version"},
 | |
| 	{IPA_RC_UNSUPPORTED_SUBCMD,	"Unsupported assist subcommand"},
 | |
| 	{IPA_RC_ARP_ASSIST_NO_ENABLE,	"Only partial success, no enable"},
 | |
| 	{IPA_RC_PRIMARY_ALREADY_DEFINED, "Primary already defined"},
 | |
| 	{IPA_RC_SECOND_ALREADY_DEFINED,	"Secondary already defined"},
 | |
| 	{IPA_RC_INVALID_SETRTG_INDICATOR, "Invalid SETRTG indicator"},
 | |
| 	{IPA_RC_MC_ADDR_ALREADY_DEFINED, "Multicast address already defined"},
 | |
| 	{IPA_RC_LAN_OFFLINE,		"STRTLAN_LAN_DISABLED - LAN offline"},
 | |
| 	{IPA_RC_VEPA_TO_VEB_TRANSITION,	"Adj. switch disabled port mode RR"},
 | |
| 	{IPA_RC_INVALID_IP_VERSION2,	"Invalid IP version"},
 | |
| 	/* default for qeth_get_ipa_msg(): */
 | |
| 	{IPA_RC_FFFF,			"Unknown Error"}
 | |
| };
 | |
| 
 | |
| const char *qeth_get_ipa_msg(enum qeth_ipa_return_codes rc)
 | |
| {
 | |
| 	int x;
 | |
| 
 | |
| 	for (x = 0; x < ARRAY_SIZE(qeth_ipa_rc_msg) - 1; x++)
 | |
| 		if (qeth_ipa_rc_msg[x].rc == rc)
 | |
| 			return qeth_ipa_rc_msg[x].msg;
 | |
| 	return qeth_ipa_rc_msg[x].msg;
 | |
| }
 | |
| 
 | |
| 
 | |
| struct ipa_cmd_names {
 | |
| 	enum qeth_ipa_cmds cmd;
 | |
| 	const char *name;
 | |
| };
 | |
| 
 | |
| static const struct ipa_cmd_names qeth_ipa_cmd_names[] = {
 | |
| 	{IPA_CMD_STARTLAN,	"startlan"},
 | |
| 	{IPA_CMD_STOPLAN,	"stoplan"},
 | |
| 	{IPA_CMD_SETVMAC,	"setvmac"},
 | |
| 	{IPA_CMD_DELVMAC,	"delvmac"},
 | |
| 	{IPA_CMD_SETGMAC,	"setgmac"},
 | |
| 	{IPA_CMD_DELGMAC,	"delgmac"},
 | |
| 	{IPA_CMD_SETVLAN,	"setvlan"},
 | |
| 	{IPA_CMD_DELVLAN,	"delvlan"},
 | |
| 	{IPA_CMD_VNICC,		"vnic_characteristics"},
 | |
| 	{IPA_CMD_SETBRIDGEPORT_OSA,	"set_bridge_port(osa)"},
 | |
| 	{IPA_CMD_SETCCID,	"setccid"},
 | |
| 	{IPA_CMD_DELCCID,	"delccid"},
 | |
| 	{IPA_CMD_MODCCID,	"modccid"},
 | |
| 	{IPA_CMD_SETIP,		"setip"},
 | |
| 	{IPA_CMD_QIPASSIST,	"qipassist"},
 | |
| 	{IPA_CMD_SETASSPARMS,	"setassparms"},
 | |
| 	{IPA_CMD_SETIPM,	"setipm"},
 | |
| 	{IPA_CMD_DELIPM,	"delipm"},
 | |
| 	{IPA_CMD_SETRTG,	"setrtg"},
 | |
| 	{IPA_CMD_DELIP,		"delip"},
 | |
| 	{IPA_CMD_SETADAPTERPARMS, "setadapterparms"},
 | |
| 	{IPA_CMD_SET_DIAG_ASS,	"set_diag_ass"},
 | |
| 	{IPA_CMD_SETBRIDGEPORT_IQD,	"set_bridge_port(hs)"},
 | |
| 	{IPA_CMD_CREATE_ADDR,	"create_addr"},
 | |
| 	{IPA_CMD_DESTROY_ADDR,	"destroy_addr"},
 | |
| 	{IPA_CMD_REGISTER_LOCAL_ADDR,	"register_local_addr"},
 | |
| 	{IPA_CMD_UNREGISTER_LOCAL_ADDR,	"unregister_local_addr"},
 | |
| 	{IPA_CMD_ADDRESS_CHANGE_NOTIF, "address_change_notification"},
 | |
| 	{IPA_CMD_UNKNOWN,	"unknown"},
 | |
| };
 | |
| 
 | |
| const char *qeth_get_ipa_cmd_name(enum qeth_ipa_cmds cmd)
 | |
| {
 | |
| 	int x;
 | |
| 
 | |
| 	for (x = 0; x < ARRAY_SIZE(qeth_ipa_cmd_names) - 1; x++)
 | |
| 		if (qeth_ipa_cmd_names[x].cmd == cmd)
 | |
| 			return qeth_ipa_cmd_names[x].name;
 | |
| 	return qeth_ipa_cmd_names[x].name;
 | |
| }
 |