Commit c3ab96f3 authored by Frank Blaschka's avatar Frank Blaschka Committed by David S. Miller

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: default avatarFrank Blaschka <frank.blaschka@de.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 51363b87
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#define SIOC_QETH_ARP_FLUSH_CACHE (SIOCDEVPRIVATE + 4) #define SIOC_QETH_ARP_FLUSH_CACHE (SIOCDEVPRIVATE + 4)
#define SIOC_QETH_ADP_SET_SNMP_CONTROL (SIOCDEVPRIVATE + 5) #define SIOC_QETH_ADP_SET_SNMP_CONTROL (SIOCDEVPRIVATE + 5)
#define SIOC_QETH_GET_CARD_TYPE (SIOCDEVPRIVATE + 6) #define SIOC_QETH_GET_CARD_TYPE (SIOCDEVPRIVATE + 6)
#define SIOC_QETH_QUERY_OAT (SIOCDEVPRIVATE + 7)
struct qeth_arp_cache_entry { struct qeth_arp_cache_entry {
__u8 macaddr[6]; __u8 macaddr[6];
...@@ -107,4 +108,10 @@ struct qeth_arp_query_user_data { ...@@ -107,4 +108,10 @@ struct qeth_arp_query_user_data {
char *entries; char *entries;
} __attribute__((packed)); } __attribute__((packed));
struct qeth_query_oat_data {
__u32 command;
__u32 buffer_len;
__u32 response_len;
__u64 ptr;
};
#endif /* __ASM_S390_QETH_IOCTL_H__ */ #endif /* __ASM_S390_QETH_IOCTL_H__ */
...@@ -906,6 +906,7 @@ void qeth_prepare_ipa_cmd(struct qeth_card *, struct qeth_cmd_buffer *, char); ...@@ -906,6 +906,7 @@ void qeth_prepare_ipa_cmd(struct qeth_card *, struct qeth_cmd_buffer *, char);
struct qeth_cmd_buffer *qeth_wait_for_buffer(struct qeth_channel *); struct qeth_cmd_buffer *qeth_wait_for_buffer(struct qeth_channel *);
int qeth_mdio_read(struct net_device *, int, int); int qeth_mdio_read(struct net_device *, int, int);
int qeth_snmp_command(struct qeth_card *, char __user *); int qeth_snmp_command(struct qeth_card *, char __user *);
int qeth_query_oat_command(struct qeth_card *, char __user *);
struct qeth_cmd_buffer *qeth_get_adapter_cmd(struct qeth_card *, __u32, __u32); struct qeth_cmd_buffer *qeth_get_adapter_cmd(struct qeth_card *, __u32, __u32);
int qeth_default_setadapterparms_cb(struct qeth_card *, struct qeth_reply *, int qeth_default_setadapterparms_cb(struct qeth_card *, struct qeth_reply *,
unsigned long); unsigned long);
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <asm/ebcdic.h> #include <asm/ebcdic.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/sysinfo.h> #include <asm/sysinfo.h>
#include <asm/compat.h>
#include "qeth_core.h" #include "qeth_core.h"
...@@ -4402,6 +4403,104 @@ int qeth_snmp_command(struct qeth_card *card, char __user *udata) ...@@ -4402,6 +4403,104 @@ int qeth_snmp_command(struct qeth_card *card, char __user *udata)
} }
EXPORT_SYMBOL_GPL(qeth_snmp_command); EXPORT_SYMBOL_GPL(qeth_snmp_command);
static int qeth_setadpparms_query_oat_cb(struct qeth_card *card,
struct qeth_reply *reply, unsigned long data)
{
struct qeth_ipa_cmd *cmd;
struct qeth_qoat_priv *priv;
char *resdata;
int resdatalen;
QETH_CARD_TEXT(card, 3, "qoatcb");
cmd = (struct qeth_ipa_cmd *)data;
priv = (struct qeth_qoat_priv *)reply->param;
resdatalen = cmd->data.setadapterparms.hdr.cmdlength;
resdata = (char *)data + 28;
if (resdatalen > (priv->buffer_len - priv->response_len)) {
cmd->hdr.return_code = IPA_RC_FFFF;
return 0;
}
memcpy((priv->buffer + priv->response_len), resdata,
resdatalen);
priv->response_len += resdatalen;
if (cmd->data.setadapterparms.hdr.seq_no <
cmd->data.setadapterparms.hdr.used_total)
return 1;
return 0;
}
int qeth_query_oat_command(struct qeth_card *card, char __user *udata)
{
int rc = 0;
struct qeth_cmd_buffer *iob;
struct qeth_ipa_cmd *cmd;
struct qeth_query_oat *oat_req;
struct qeth_query_oat_data oat_data;
struct qeth_qoat_priv priv;
void __user *tmp;
QETH_CARD_TEXT(card, 3, "qoatcmd");
if (!qeth_adp_supported(card, IPA_SETADP_QUERY_OAT)) {
rc = -EOPNOTSUPP;
goto out;
}
if (copy_from_user(&oat_data, udata,
sizeof(struct qeth_query_oat_data))) {
rc = -EFAULT;
goto out;
}
priv.buffer_len = oat_data.buffer_len;
priv.response_len = 0;
priv.buffer = kzalloc(oat_data.buffer_len, GFP_KERNEL);
if (!priv.buffer) {
rc = -ENOMEM;
goto out;
}
iob = qeth_get_adapter_cmd(card, IPA_SETADP_QUERY_OAT,
sizeof(struct qeth_ipacmd_setadpparms_hdr) +
sizeof(struct qeth_query_oat));
cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
oat_req = &cmd->data.setadapterparms.data.query_oat;
oat_req->subcmd_code = oat_data.command;
rc = qeth_send_ipa_cmd(card, iob, qeth_setadpparms_query_oat_cb,
&priv);
if (!rc) {
if (is_compat_task())
tmp = compat_ptr(oat_data.ptr);
else
tmp = (void __user *)(unsigned long)oat_data.ptr;
if (copy_to_user(tmp, priv.buffer,
priv.response_len)) {
rc = -EFAULT;
goto out_free;
}
oat_data.response_len = priv.response_len;
if (copy_to_user(udata, &oat_data,
sizeof(struct qeth_query_oat_data)))
rc = -EFAULT;
} else
if (rc == IPA_RC_FFFF)
rc = -EFAULT;
out_free:
kfree(priv.buffer);
out:
return rc;
}
EXPORT_SYMBOL_GPL(qeth_query_oat_command);
static inline int qeth_get_qdio_q_format(struct qeth_card *card) static inline int qeth_get_qdio_q_format(struct qeth_card *card)
{ {
switch (card->info.type) { switch (card->info.type) {
......
...@@ -249,6 +249,7 @@ enum qeth_ipa_setadp_cmd { ...@@ -249,6 +249,7 @@ enum qeth_ipa_setadp_cmd {
IPA_SETADP_SET_PROMISC_MODE = 0x00000800L, IPA_SETADP_SET_PROMISC_MODE = 0x00000800L,
IPA_SETADP_SET_DIAG_ASSIST = 0x00002000L, IPA_SETADP_SET_DIAG_ASSIST = 0x00002000L,
IPA_SETADP_SET_ACCESS_CONTROL = 0x00010000L, IPA_SETADP_SET_ACCESS_CONTROL = 0x00010000L,
IPA_SETADP_QUERY_OAT = 0x00080000L,
}; };
enum qeth_ipa_mac_ops { enum qeth_ipa_mac_ops {
CHANGE_ADDR_READ_MAC = 0, CHANGE_ADDR_READ_MAC = 0,
...@@ -398,6 +399,17 @@ struct qeth_set_access_ctrl { ...@@ -398,6 +399,17 @@ struct qeth_set_access_ctrl {
__u32 subcmd_code; __u32 subcmd_code;
} __attribute__((packed)); } __attribute__((packed));
struct qeth_query_oat {
__u32 subcmd_code;
__u8 reserved[12];
} __packed;
struct qeth_qoat_priv {
__u32 buffer_len;
__u32 response_len;
char *buffer;
};
struct qeth_ipacmd_setadpparms_hdr { struct qeth_ipacmd_setadpparms_hdr {
__u32 supp_hw_cmds; __u32 supp_hw_cmds;
__u32 reserved1; __u32 reserved1;
...@@ -417,6 +429,7 @@ struct qeth_ipacmd_setadpparms { ...@@ -417,6 +429,7 @@ struct qeth_ipacmd_setadpparms {
struct qeth_change_addr change_addr; struct qeth_change_addr change_addr;
struct qeth_snmp_cmd snmp; struct qeth_snmp_cmd snmp;
struct qeth_set_access_ctrl set_access_ctrl; struct qeth_set_access_ctrl set_access_ctrl;
struct qeth_query_oat query_oat;
__u32 mode; __u32 mode;
} data; } data;
} __attribute__ ((packed)); } __attribute__ ((packed));
......
...@@ -75,6 +75,9 @@ static int qeth_l2_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -75,6 +75,9 @@ static int qeth_l2_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
mii_data->val_out = qeth_mdio_read(dev, mii_data->val_out = qeth_mdio_read(dev,
mii_data->phy_id, mii_data->reg_num); mii_data->phy_id, mii_data->reg_num);
break; break;
case SIOC_QETH_QUERY_OAT:
rc = qeth_query_oat_command(card, rq->ifr_ifru.ifru_data);
break;
default: default:
rc = -EOPNOTSUPP; rc = -EOPNOTSUPP;
} }
......
...@@ -2745,6 +2745,9 @@ static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -2745,6 +2745,9 @@ static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
mii_data->phy_id, mii_data->phy_id,
mii_data->reg_num); mii_data->reg_num);
break; break;
case SIOC_QETH_QUERY_OAT:
rc = qeth_query_oat_command(card, rq->ifr_ifru.ifru_data);
break;
default: default:
rc = -EOPNOTSUPP; rc = -EOPNOTSUPP;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment