diff options
author | Frank Blaschka <frank.blaschka@de.ibm.com> | 2012-02-07 19:19:49 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-02-08 18:50:20 -0500 |
commit | c3ab96f36aa308fa5bf432d5a4dafc80b7373805 (patch) | |
tree | 8ab0bb57340bf267fd6921b8f8db008b1b352cbd | |
parent | 51363b8751a673a00ad48eea895266396d53fa52 (diff) |
qeth: add query OSA address table support
Add qeth device private ioctl to query the OSA address table.
This helps debugging hw related problems.
Signed-off-by: Frank Blaschka <frank.blaschka@de.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | arch/s390/include/asm/qeth.h | 7 | ||||
-rw-r--r-- | drivers/s390/net/qeth_core.h | 1 | ||||
-rw-r--r-- | drivers/s390/net/qeth_core_main.c | 99 | ||||
-rw-r--r-- | drivers/s390/net/qeth_core_mpc.h | 13 | ||||
-rw-r--r-- | drivers/s390/net/qeth_l2_main.c | 3 | ||||
-rw-r--r-- | drivers/s390/net/qeth_l3_main.c | 3 |
6 files changed, 126 insertions, 0 deletions
diff --git a/arch/s390/include/asm/qeth.h b/arch/s390/include/asm/qeth.h index 90efda0b137d..2c7c898c03e4 100644 --- a/arch/s390/include/asm/qeth.h +++ b/arch/s390/include/asm/qeth.h | |||
@@ -20,6 +20,7 @@ | |||
20 | #define SIOC_QETH_ARP_FLUSH_CACHE (SIOCDEVPRIVATE + 4) | 20 | #define SIOC_QETH_ARP_FLUSH_CACHE (SIOCDEVPRIVATE + 4) |
21 | #define SIOC_QETH_ADP_SET_SNMP_CONTROL (SIOCDEVPRIVATE + 5) | 21 | #define SIOC_QETH_ADP_SET_SNMP_CONTROL (SIOCDEVPRIVATE + 5) |
22 | #define SIOC_QETH_GET_CARD_TYPE (SIOCDEVPRIVATE + 6) | 22 | #define SIOC_QETH_GET_CARD_TYPE (SIOCDEVPRIVATE + 6) |
23 | #define SIOC_QETH_QUERY_OAT (SIOCDEVPRIVATE + 7) | ||
23 | 24 | ||
24 | struct qeth_arp_cache_entry { | 25 | struct qeth_arp_cache_entry { |
25 | __u8 macaddr[6]; | 26 | __u8 macaddr[6]; |
@@ -107,4 +108,10 @@ struct qeth_arp_query_user_data { | |||
107 | char *entries; | 108 | char *entries; |
108 | } __attribute__((packed)); | 109 | } __attribute__((packed)); |
109 | 110 | ||
111 | struct qeth_query_oat_data { | ||
112 | __u32 command; | ||
113 | __u32 buffer_len; | ||
114 | __u32 response_len; | ||
115 | __u64 ptr; | ||
116 | }; | ||
110 | #endif /* __ASM_S390_QETH_IOCTL_H__ */ | 117 | #endif /* __ASM_S390_QETH_IOCTL_H__ */ |
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 4abc79d3963f..ec7921b5138e 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h | |||
@@ -906,6 +906,7 @@ void qeth_prepare_ipa_cmd(struct qeth_card *, struct qeth_cmd_buffer *, char); | |||
906 | struct qeth_cmd_buffer *qeth_wait_for_buffer(struct qeth_channel *); | 906 | struct qeth_cmd_buffer *qeth_wait_for_buffer(struct qeth_channel *); |
907 | int qeth_mdio_read(struct net_device *, int, int); | 907 | int qeth_mdio_read(struct net_device *, int, int); |
908 | int qeth_snmp_command(struct qeth_card *, char __user *); | 908 | int qeth_snmp_command(struct qeth_card *, char __user *); |
909 | int qeth_query_oat_command(struct qeth_card *, char __user *); | ||
909 | struct qeth_cmd_buffer *qeth_get_adapter_cmd(struct qeth_card *, __u32, __u32); | 910 | struct qeth_cmd_buffer *qeth_get_adapter_cmd(struct qeth_card *, __u32, __u32); |
910 | int qeth_default_setadapterparms_cb(struct qeth_card *, struct qeth_reply *, | 911 | int qeth_default_setadapterparms_cb(struct qeth_card *, struct qeth_reply *, |
911 | unsigned long); | 912 | unsigned long); |
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 9c3f38da4c01..0565584b52c3 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <asm/ebcdic.h> | 26 | #include <asm/ebcdic.h> |
27 | #include <asm/io.h> | 27 | #include <asm/io.h> |
28 | #include <asm/sysinfo.h> | 28 | #include <asm/sysinfo.h> |
29 | #include <asm/compat.h> | ||
29 | 30 | ||
30 | #include "qeth_core.h" | 31 | #include "qeth_core.h" |
31 | 32 | ||
@@ -4402,6 +4403,104 @@ int qeth_snmp_command(struct qeth_card *card, char __user *udata) | |||
4402 | } | 4403 | } |
4403 | EXPORT_SYMBOL_GPL(qeth_snmp_command); | 4404 | EXPORT_SYMBOL_GPL(qeth_snmp_command); |
4404 | 4405 | ||
4406 | static int qeth_setadpparms_query_oat_cb(struct qeth_card *card, | ||
4407 | struct qeth_reply *reply, unsigned long data) | ||
4408 | { | ||
4409 | struct qeth_ipa_cmd *cmd; | ||
4410 | struct qeth_qoat_priv *priv; | ||
4411 | char *resdata; | ||
4412 | int resdatalen; | ||
4413 | |||
4414 | QETH_CARD_TEXT(card, 3, "qoatcb"); | ||
4415 | |||
4416 | cmd = (struct qeth_ipa_cmd *)data; | ||
4417 | priv = (struct qeth_qoat_priv *)reply->param; | ||
4418 | resdatalen = cmd->data.setadapterparms.hdr.cmdlength; | ||
4419 | resdata = (char *)data + 28; | ||
4420 | |||
4421 | if (resdatalen > (priv->buffer_len - priv->response_len)) { | ||
4422 | cmd->hdr.return_code = IPA_RC_FFFF; | ||
4423 | return 0; | ||
4424 | } | ||
4425 | |||
4426 | memcpy((priv->buffer + priv->response_len), resdata, | ||
4427 | resdatalen); | ||
4428 | priv->response_len += resdatalen; | ||
4429 | |||
4430 | if (cmd->data.setadapterparms.hdr.seq_no < | ||
4431 | cmd->data.setadapterparms.hdr.used_total) | ||
4432 | return 1; | ||
4433 | return 0; | ||
4434 | } | ||
4435 | |||
4436 | int qeth_query_oat_command(struct qeth_card *card, char __user *udata) | ||
4437 | { | ||
4438 | int rc = 0; | ||
4439 | struct qeth_cmd_buffer *iob; | ||
4440 | struct qeth_ipa_cmd *cmd; | ||
4441 | struct qeth_query_oat *oat_req; | ||
4442 | struct qeth_query_oat_data oat_data; | ||
4443 | struct qeth_qoat_priv priv; | ||
4444 | void __user *tmp; | ||
4445 | |||
4446 | QETH_CARD_TEXT(card, 3, "qoatcmd"); | ||
4447 | |||
4448 | if (!qeth_adp_supported(card, IPA_SETADP_QUERY_OAT)) { | ||
4449 | rc = -EOPNOTSUPP; | ||
4450 | goto out; | ||
4451 | } | ||
4452 | |||
4453 | if (copy_from_user(&oat_data, udata, | ||
4454 | sizeof(struct qeth_query_oat_data))) { | ||
4455 | rc = -EFAULT; | ||
4456 | goto out; | ||
4457 | } | ||
4458 | |||
4459 | priv.buffer_len = oat_data.buffer_len; | ||
4460 | priv.response_len = 0; | ||
4461 | priv.buffer = kzalloc(oat_data.buffer_len, GFP_KERNEL); | ||
4462 | if (!priv.buffer) { | ||
4463 | rc = -ENOMEM; | ||
4464 | goto out; | ||
4465 | } | ||
4466 | |||
4467 | iob = qeth_get_adapter_cmd(card, IPA_SETADP_QUERY_OAT, | ||
4468 | sizeof(struct qeth_ipacmd_setadpparms_hdr) + | ||
4469 | sizeof(struct qeth_query_oat)); | ||
4470 | cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); | ||
4471 | oat_req = &cmd->data.setadapterparms.data.query_oat; | ||
4472 | oat_req->subcmd_code = oat_data.command; | ||
4473 | |||
4474 | rc = qeth_send_ipa_cmd(card, iob, qeth_setadpparms_query_oat_cb, | ||
4475 | &priv); | ||
4476 | if (!rc) { | ||
4477 | if (is_compat_task()) | ||
4478 | tmp = compat_ptr(oat_data.ptr); | ||
4479 | else | ||
4480 | tmp = (void __user *)(unsigned long)oat_data.ptr; | ||
4481 | |||
4482 | if (copy_to_user(tmp, priv.buffer, | ||
4483 | priv.response_len)) { | ||
4484 | rc = -EFAULT; | ||
4485 | goto out_free; | ||
4486 | } | ||
4487 | |||
4488 | oat_data.response_len = priv.response_len; | ||
4489 | |||
4490 | if (copy_to_user(udata, &oat_data, | ||
4491 | sizeof(struct qeth_query_oat_data))) | ||
4492 | rc = -EFAULT; | ||
4493 | } else | ||
4494 | if (rc == IPA_RC_FFFF) | ||
4495 | rc = -EFAULT; | ||
4496 | |||
4497 | out_free: | ||
4498 | kfree(priv.buffer); | ||
4499 | out: | ||
4500 | return rc; | ||
4501 | } | ||
4502 | EXPORT_SYMBOL_GPL(qeth_query_oat_command); | ||
4503 | |||
4405 | static inline int qeth_get_qdio_q_format(struct qeth_card *card) | 4504 | static inline int qeth_get_qdio_q_format(struct qeth_card *card) |
4406 | { | 4505 | { |
4407 | switch (card->info.type) { | 4506 | switch (card->info.type) { |
diff --git a/drivers/s390/net/qeth_core_mpc.h b/drivers/s390/net/qeth_core_mpc.h index e5a9d1c03839..578e19a2de6b 100644 --- a/drivers/s390/net/qeth_core_mpc.h +++ b/drivers/s390/net/qeth_core_mpc.h | |||
@@ -249,6 +249,7 @@ enum qeth_ipa_setadp_cmd { | |||
249 | IPA_SETADP_SET_PROMISC_MODE = 0x00000800L, | 249 | IPA_SETADP_SET_PROMISC_MODE = 0x00000800L, |
250 | IPA_SETADP_SET_DIAG_ASSIST = 0x00002000L, | 250 | IPA_SETADP_SET_DIAG_ASSIST = 0x00002000L, |
251 | IPA_SETADP_SET_ACCESS_CONTROL = 0x00010000L, | 251 | IPA_SETADP_SET_ACCESS_CONTROL = 0x00010000L, |
252 | IPA_SETADP_QUERY_OAT = 0x00080000L, | ||
252 | }; | 253 | }; |
253 | enum qeth_ipa_mac_ops { | 254 | enum qeth_ipa_mac_ops { |
254 | CHANGE_ADDR_READ_MAC = 0, | 255 | CHANGE_ADDR_READ_MAC = 0, |
@@ -398,6 +399,17 @@ struct qeth_set_access_ctrl { | |||
398 | __u32 subcmd_code; | 399 | __u32 subcmd_code; |
399 | } __attribute__((packed)); | 400 | } __attribute__((packed)); |
400 | 401 | ||
402 | struct qeth_query_oat { | ||
403 | __u32 subcmd_code; | ||
404 | __u8 reserved[12]; | ||
405 | } __packed; | ||
406 | |||
407 | struct qeth_qoat_priv { | ||
408 | __u32 buffer_len; | ||
409 | __u32 response_len; | ||
410 | char *buffer; | ||
411 | }; | ||
412 | |||
401 | struct qeth_ipacmd_setadpparms_hdr { | 413 | struct qeth_ipacmd_setadpparms_hdr { |
402 | __u32 supp_hw_cmds; | 414 | __u32 supp_hw_cmds; |
403 | __u32 reserved1; | 415 | __u32 reserved1; |
@@ -417,6 +429,7 @@ struct qeth_ipacmd_setadpparms { | |||
417 | struct qeth_change_addr change_addr; | 429 | struct qeth_change_addr change_addr; |
418 | struct qeth_snmp_cmd snmp; | 430 | struct qeth_snmp_cmd snmp; |
419 | struct qeth_set_access_ctrl set_access_ctrl; | 431 | struct qeth_set_access_ctrl set_access_ctrl; |
432 | struct qeth_query_oat query_oat; | ||
420 | __u32 mode; | 433 | __u32 mode; |
421 | } data; | 434 | } data; |
422 | } __attribute__ ((packed)); | 435 | } __attribute__ ((packed)); |
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index c12967133114..e5c9cf15e5c6 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c | |||
@@ -75,6 +75,9 @@ static int qeth_l2_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | |||
75 | mii_data->val_out = qeth_mdio_read(dev, | 75 | mii_data->val_out = qeth_mdio_read(dev, |
76 | mii_data->phy_id, mii_data->reg_num); | 76 | mii_data->phy_id, mii_data->reg_num); |
77 | break; | 77 | break; |
78 | case SIOC_QETH_QUERY_OAT: | ||
79 | rc = qeth_query_oat_command(card, rq->ifr_ifru.ifru_data); | ||
80 | break; | ||
78 | default: | 81 | default: |
79 | rc = -EOPNOTSUPP; | 82 | rc = -EOPNOTSUPP; |
80 | } | 83 | } |
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 25cd3799a76c..73bf8889984b 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c | |||
@@ -2745,6 +2745,9 @@ static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | |||
2745 | mii_data->phy_id, | 2745 | mii_data->phy_id, |
2746 | mii_data->reg_num); | 2746 | mii_data->reg_num); |
2747 | break; | 2747 | break; |
2748 | case SIOC_QETH_QUERY_OAT: | ||
2749 | rc = qeth_query_oat_command(card, rq->ifr_ifru.ifru_data); | ||
2750 | break; | ||
2748 | default: | 2751 | default: |
2749 | rc = -EOPNOTSUPP; | 2752 | rc = -EOPNOTSUPP; |
2750 | } | 2753 | } |