Commit 096cc49c authored by David S. Miller's avatar David S. Miller

Merge branch 's390-qeth-next'

Julian Wiedmann says:

====================
s390/qeth: updates 2019-06-27

please apply another round of qeth updates for net-next.
This completes the conversion of the control path to use dynamically
allocated cmd buffers, along with some fine-tuning for the route
validation fix that recently went into -net.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 39f41f36 eca1d5c2
......@@ -25,6 +25,8 @@
#include <linux/wait.h>
#include <linux/workqueue.h>
#include <net/dst.h>
#include <net/ip6_fib.h>
#include <net/ipv6.h>
#include <net/if_inet6.h>
#include <net/addrconf.h>
......@@ -60,7 +62,7 @@ struct qeth_dbf_info {
debug_info_t *id;
};
#define QETH_DBF_CTRL_LEN 256
#define QETH_DBF_CTRL_LEN 256U
#define QETH_DBF_TEXT(name, level, text) \
debug_text_event(qeth_dbf[QETH_DBF_##name].id, level, text)
......@@ -524,11 +526,6 @@ struct qeth_qdio_info {
int default_out_queue;
};
/**
* buffer stuff for read channel
*/
#define QETH_CMD_BUFFER_NO 8
/**
* channel state machine
*/
......@@ -551,16 +548,11 @@ enum qeth_card_states {
* Protocol versions
*/
enum qeth_prot_versions {
QETH_PROT_NONE = 0x0000,
QETH_PROT_IPV4 = 0x0004,
QETH_PROT_IPV6 = 0x0006,
};
enum qeth_cmd_buffer_state {
BUF_STATE_FREE,
BUF_STATE_LOCKED,
BUF_STATE_MALLOC,
};
enum qeth_cq {
QETH_CQ_DISABLED = 0,
QETH_CQ_ENABLED = 1,
......@@ -574,18 +566,20 @@ struct qeth_ipato {
struct list_head entries;
};
struct qeth_channel;
struct qeth_channel {
struct ccw_device *ccwdev;
enum qeth_channel_states state;
atomic_t irq_pending;
};
struct qeth_cmd_buffer {
enum qeth_cmd_buffer_state state;
unsigned int length;
refcount_t ref_count;
struct qeth_channel *channel;
struct qeth_reply *reply;
long timeout;
unsigned char *data;
void (*finalize)(struct qeth_card *card, struct qeth_cmd_buffer *iob,
unsigned int length);
void (*finalize)(struct qeth_card *card, struct qeth_cmd_buffer *iob);
void (*callback)(struct qeth_card *card, struct qeth_cmd_buffer *iob);
};
......@@ -599,25 +593,8 @@ static inline struct qeth_ipa_cmd *__ipa_cmd(struct qeth_cmd_buffer *iob)
return (struct qeth_ipa_cmd *)(iob->data + IPA_PDU_HEADER_SIZE);
}
/**
* definition of a qeth channel, used for read and write
*/
struct qeth_channel {
enum qeth_channel_states state;
struct ccw1 *ccw;
spinlock_t iob_lock;
wait_queue_head_t wait_q;
struct ccw_device *ccwdev;
/*command buffer for control data*/
struct qeth_cmd_buffer iob[QETH_CMD_BUFFER_NO];
atomic_t irq_pending;
int io_buf_no;
};
static inline struct ccw1 *__ccw_from_cmd(struct qeth_cmd_buffer *iob)
{
if (iob->state != BUF_STATE_MALLOC)
return iob->channel->ccw;
return (struct ccw1 *)(iob->data + ALIGN(iob->length, 8));
}
......@@ -738,9 +715,6 @@ struct qeth_discipline {
void (*remove) (struct ccwgroup_device *);
int (*set_online) (struct ccwgroup_device *);
int (*set_offline) (struct ccwgroup_device *);
int (*freeze)(struct ccwgroup_device *);
int (*thaw) (struct ccwgroup_device *);
int (*restore)(struct ccwgroup_device *);
int (*do_ioctl)(struct net_device *dev, struct ifreq *rq, int cmd);
int (*control_event_handler)(struct qeth_card *card,
struct qeth_ipa_cmd *cmd);
......@@ -905,6 +879,17 @@ static inline int qeth_get_ether_cast_type(struct sk_buff *skb)
return RTN_UNICAST;
}
static inline struct dst_entry *qeth_dst_check_rcu(struct sk_buff *skb, int ipv)
{
struct dst_entry *dst = skb_dst(skb);
struct rt6_info *rt;
rt = (struct rt6_info *) dst;
if (dst)
dst = dst_check(dst, (ipv == 6) ? rt6_get_cookie(rt) : 0);
return dst;
}
static inline void qeth_rx_csum(struct qeth_card *card, struct sk_buff *skb,
u8 flags)
{
......@@ -939,12 +924,12 @@ static inline int qeth_is_diagass_supported(struct qeth_card *card,
int qeth_send_simple_setassparms_prot(struct qeth_card *card,
enum qeth_ipa_funcs ipa_func,
u16 cmd_code, long data,
u16 cmd_code, u32 *data,
enum qeth_prot_versions prot);
/* IPv4 variant */
static inline int qeth_send_simple_setassparms(struct qeth_card *card,
enum qeth_ipa_funcs ipa_func,
u16 cmd_code, long data)
u16 cmd_code, u32 *data)
{
return qeth_send_simple_setassparms_prot(card, ipa_func, cmd_code,
data, QETH_PROT_IPV4);
......@@ -952,7 +937,7 @@ static inline int qeth_send_simple_setassparms(struct qeth_card *card,
static inline int qeth_send_simple_setassparms_v6(struct qeth_card *card,
enum qeth_ipa_funcs ipa_func,
u16 cmd_code, long data)
u16 cmd_code, u32 *data)
{
return qeth_send_simple_setassparms_prot(card, ipa_func, cmd_code,
data, QETH_PROT_IPV6);
......@@ -993,8 +978,23 @@ int qeth_send_ipa_cmd(struct qeth_card *, struct qeth_cmd_buffer *,
int (*reply_cb)
(struct qeth_card *, struct qeth_reply *, unsigned long),
void *);
struct qeth_cmd_buffer *qeth_get_ipacmd_buffer(struct qeth_card *,
enum qeth_ipa_cmds, enum qeth_prot_versions);
struct qeth_cmd_buffer *qeth_ipa_alloc_cmd(struct qeth_card *card,
enum qeth_ipa_cmds cmd_code,
enum qeth_prot_versions prot,
unsigned int data_length);
struct qeth_cmd_buffer *qeth_alloc_cmd(struct qeth_channel *channel,
unsigned int length, unsigned int ccws,
long timeout);
struct qeth_cmd_buffer *qeth_get_setassparms_cmd(struct qeth_card *card,
enum qeth_ipa_funcs ipa_func,
u16 cmd_code,
unsigned int data_length,
enum qeth_prot_versions prot);
struct qeth_cmd_buffer *qeth_get_diag_cmd(struct qeth_card *card,
enum qeth_diags_cmds sub_cmd,
unsigned int data_length);
void qeth_put_cmd(struct qeth_cmd_buffer *iob);
struct sk_buff *qeth_core_get_next_skb(struct qeth_card *,
struct qeth_qdio_buffer *, struct qdio_buffer_element **, int *,
struct qeth_hdr **);
......@@ -1003,16 +1003,13 @@ int qeth_poll(struct napi_struct *napi, int budget);
void qeth_clear_ipacmd_list(struct qeth_card *);
int qeth_qdio_clear_card(struct qeth_card *, int);
void qeth_clear_working_pool_list(struct qeth_card *);
void qeth_clear_cmd_buffers(struct qeth_channel *);
void qeth_drain_output_queues(struct qeth_card *card);
void qeth_setadp_promisc_mode(struct qeth_card *);
int qeth_setadpparms_change_macaddr(struct qeth_card *);
void qeth_tx_timeout(struct net_device *);
void qeth_release_buffer(struct qeth_cmd_buffer *iob);
void qeth_notify_reply(struct qeth_reply *reply, int reason);
void qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
u16 cmd_length);
struct qeth_cmd_buffer *qeth_get_buffer(struct qeth_channel *channel);
int qeth_query_switch_attributes(struct qeth_card *card,
struct qeth_switch_info *sw_info);
int qeth_query_card_info(struct qeth_card *card,
......@@ -1029,10 +1026,6 @@ int qeth_configure_cq(struct qeth_card *, enum qeth_cq);
int qeth_hw_trap(struct qeth_card *, enum qeth_diags_trap_action);
void qeth_trace_features(struct qeth_card *);
int qeth_setassparms_cb(struct qeth_card *, struct qeth_reply *, unsigned long);
struct qeth_cmd_buffer *qeth_get_setassparms_cmd(struct qeth_card *,
enum qeth_ipa_funcs,
__u16, __u16,
enum qeth_prot_versions);
int qeth_set_features(struct net_device *, netdev_features_t);
void qeth_enable_hw_features(struct net_device *dev);
netdev_features_t qeth_fix_features(struct net_device *, netdev_features_t);
......@@ -1047,11 +1040,10 @@ int qeth_stop(struct net_device *dev);
int qeth_vm_request_mac(struct qeth_card *card);
int qeth_xmit(struct qeth_card *card, struct sk_buff *skb,
struct qeth_qdio_out_q *queue, int ipv, int cast_type,
struct qeth_qdio_out_q *queue, int ipv,
void (*fill_header)(struct qeth_qdio_out_q *queue,
struct qeth_hdr *hdr, struct sk_buff *skb,
int ipv, int cast_type,
unsigned int data_len));
int ipv, unsigned int data_len));
/* exports for OSN */
int qeth_osn_assist(struct net_device *, void *, int);
......
......@@ -517,7 +517,7 @@ static int __qeth_issue_next_read(struct qeth_card *card)
QETH_DBF_MESSAGE(2, "error %i on device %x when starting next read ccw!\n",
rc, CARD_DEVID(card));
atomic_set(&channel->irq_pending, 0);
qeth_release_buffer(iob);
qeth_put_cmd(iob);
card->read_or_write_problem = 1;
qeth_schedule_recovery(card);
wake_up(&card->wait_q);
......@@ -689,7 +689,7 @@ static int qeth_check_idx_response(struct qeth_card *card,
return 0;
}
static void qeth_put_cmd(struct qeth_cmd_buffer *iob)
void qeth_put_cmd(struct qeth_cmd_buffer *iob)
{
if (refcount_dec_and_test(&iob->ref_count)) {
if (iob->reply)
......@@ -698,53 +698,12 @@ static void qeth_put_cmd(struct qeth_cmd_buffer *iob)
kfree(iob);
}
}
static struct qeth_cmd_buffer *__qeth_get_buffer(struct qeth_channel *channel)
{
__u8 index;
index = channel->io_buf_no;
do {
if (channel->iob[index].state == BUF_STATE_FREE) {
channel->iob[index].state = BUF_STATE_LOCKED;
channel->iob[index].timeout = QETH_TIMEOUT;
channel->io_buf_no = (channel->io_buf_no + 1) %
QETH_CMD_BUFFER_NO;
memset(channel->iob[index].data, 0, QETH_BUFSIZE);
return channel->iob + index;
}
index = (index + 1) % QETH_CMD_BUFFER_NO;
} while (index != channel->io_buf_no);
return NULL;
}
void qeth_release_buffer(struct qeth_cmd_buffer *iob)
{
struct qeth_channel *channel = iob->channel;
unsigned long flags;
if (iob->state == BUF_STATE_MALLOC) {
qeth_put_cmd(iob);
return;
}
spin_lock_irqsave(&channel->iob_lock, flags);
iob->state = BUF_STATE_FREE;
iob->callback = NULL;
if (iob->reply) {
qeth_put_reply(iob->reply);
iob->reply = NULL;
}
spin_unlock_irqrestore(&channel->iob_lock, flags);
wake_up(&channel->wait_q);
}
EXPORT_SYMBOL_GPL(qeth_release_buffer);
EXPORT_SYMBOL_GPL(qeth_put_cmd);
static void qeth_release_buffer_cb(struct qeth_card *card,
struct qeth_cmd_buffer *iob)
{
qeth_release_buffer(iob);
qeth_put_cmd(iob);
}
static void qeth_cancel_cmd(struct qeth_cmd_buffer *iob, int rc)
......@@ -753,24 +712,12 @@ static void qeth_cancel_cmd(struct qeth_cmd_buffer *iob, int rc)
if (reply)
qeth_notify_reply(reply, rc);
qeth_release_buffer(iob);
}
struct qeth_cmd_buffer *qeth_get_buffer(struct qeth_channel *channel)
{
struct qeth_cmd_buffer *buffer = NULL;
unsigned long flags;
spin_lock_irqsave(&channel->iob_lock, flags);
buffer = __qeth_get_buffer(channel);
spin_unlock_irqrestore(&channel->iob_lock, flags);
return buffer;
qeth_put_cmd(iob);
}
EXPORT_SYMBOL_GPL(qeth_get_buffer);
static struct qeth_cmd_buffer *qeth_alloc_cmd(struct qeth_channel *channel,
unsigned int length,
unsigned int ccws, long timeout)
struct qeth_cmd_buffer *qeth_alloc_cmd(struct qeth_channel *channel,
unsigned int length, unsigned int ccws,
long timeout)
{
struct qeth_cmd_buffer *iob;
......@@ -788,23 +735,13 @@ static struct qeth_cmd_buffer *qeth_alloc_cmd(struct qeth_channel *channel,
return NULL;
}
iob->state = BUF_STATE_MALLOC;
refcount_set(&iob->ref_count, 1);
iob->channel = channel;
iob->timeout = timeout;
iob->length = length;
return iob;
}
void qeth_clear_cmd_buffers(struct qeth_channel *channel)
{
int cnt;
for (cnt = 0; cnt < QETH_CMD_BUFFER_NO; cnt++)
qeth_release_buffer(&channel->iob[cnt]);
channel->io_buf_no = 0;
}
EXPORT_SYMBOL_GPL(qeth_clear_cmd_buffers);
EXPORT_SYMBOL_GPL(qeth_alloc_cmd);
static void qeth_issue_next_read_cb(struct qeth_card *card,
struct qeth_cmd_buffer *iob)
......@@ -879,7 +816,7 @@ static void qeth_issue_next_read_cb(struct qeth_card *card,
memcpy(&card->seqno.pdu_hdr_ack,
QETH_PDU_HEADER_SEQ_NO(iob->data),
QETH_SEQ_NO_LENGTH);
qeth_release_buffer(iob);
qeth_put_cmd(iob);
__qeth_issue_next_read(card);
}
......@@ -1229,56 +1166,26 @@ static void qeth_free_buffer_pool(struct qeth_card *card)
static void qeth_clean_channel(struct qeth_channel *channel)
{
struct ccw_device *cdev = channel->ccwdev;
int cnt;
QETH_DBF_TEXT(SETUP, 2, "freech");
spin_lock_irq(get_ccwdev_lock(cdev));
cdev->handler = NULL;
spin_unlock_irq(get_ccwdev_lock(cdev));
for (cnt = 0; cnt < QETH_CMD_BUFFER_NO; cnt++)
kfree(channel->iob[cnt].data);
kfree(channel->ccw);
}
static int qeth_setup_channel(struct qeth_channel *channel, bool alloc_buffers)
static void qeth_setup_channel(struct qeth_channel *channel)
{
struct ccw_device *cdev = channel->ccwdev;
int cnt;
QETH_DBF_TEXT(SETUP, 2, "setupch");
channel->ccw = kmalloc(sizeof(struct ccw1), GFP_KERNEL | GFP_DMA);
if (!channel->ccw)
return -ENOMEM;
channel->state = CH_STATE_DOWN;
atomic_set(&channel->irq_pending, 0);
init_waitqueue_head(&channel->wait_q);
spin_lock_irq(get_ccwdev_lock(cdev));
cdev->handler = qeth_irq;
spin_unlock_irq(get_ccwdev_lock(cdev));
if (!alloc_buffers)
return 0;
for (cnt = 0; cnt < QETH_CMD_BUFFER_NO; cnt++) {
channel->iob[cnt].data = kmalloc(QETH_BUFSIZE,
GFP_KERNEL | GFP_DMA);
if (channel->iob[cnt].data == NULL)
break;
channel->iob[cnt].state = BUF_STATE_FREE;
channel->iob[cnt].channel = channel;
}
if (cnt < QETH_CMD_BUFFER_NO) {
qeth_clean_channel(channel);
return -ENOMEM;
}
channel->io_buf_no = 0;
spin_lock_init(&channel->iob_lock);
return 0;
}
static int qeth_osa_set_output_queues(struct qeth_card *card, bool single)
......@@ -1452,22 +1359,14 @@ static struct qeth_card *qeth_alloc_card(struct ccwgroup_device *gdev)
card->read_cmd = qeth_alloc_cmd(&card->read, QETH_BUFSIZE, 1, 0);
if (!card->read_cmd)
goto out_read_cmd;
if (qeth_setup_channel(&card->read, false))
goto out_read;
if (qeth_setup_channel(&card->write, true))
goto out_write;
if (qeth_setup_channel(&card->data, false))
goto out_data;
qeth_setup_channel(&card->read);
qeth_setup_channel(&card->write);
qeth_setup_channel(&card->data);
card->qeth_service_level.seq_print = qeth_core_sl_print;
register_service_level(&card->qeth_service_level);
return card;
out_data:
qeth_clean_channel(&card->write);
out_write:
qeth_clean_channel(&card->read);
out_read:
qeth_release_buffer(card->read_cmd);
out_read_cmd:
destroy_workqueue(card->event_wq);
out_wq:
......@@ -1715,8 +1614,7 @@ static void qeth_init_func_level(struct qeth_card *card)
}
static void qeth_idx_finalize_cmd(struct qeth_card *card,
struct qeth_cmd_buffer *iob,
unsigned int length)
struct qeth_cmd_buffer *iob)
{
memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data), &card->seqno.trans_hdr,
QETH_SEQ_NO_LENGTH);
......@@ -1734,12 +1632,9 @@ static int qeth_peer_func_level(int level)
}
static void qeth_mpc_finalize_cmd(struct qeth_card *card,
struct qeth_cmd_buffer *iob,
unsigned int length)
struct qeth_cmd_buffer *iob)
{
qeth_setup_ccw(__ccw_from_cmd(iob), CCW_CMD_WRITE, 0, length,
iob->data);
qeth_idx_finalize_cmd(card, iob, length);
qeth_idx_finalize_cmd(card, iob);
memcpy(QETH_PDU_HEADER_SEQ_NO(iob->data),
&card->seqno.pdu_hdr, QETH_SEQ_NO_LENGTH);
......@@ -1751,20 +1646,26 @@ static void qeth_mpc_finalize_cmd(struct qeth_card *card,
iob->callback = qeth_release_buffer_cb;
}
static struct qeth_cmd_buffer *qeth_mpc_get_cmd_buffer(struct qeth_card *card)
static struct qeth_cmd_buffer *qeth_mpc_alloc_cmd(struct qeth_card *card,
void *data,
unsigned int data_length)
{
struct qeth_cmd_buffer *iob;
iob = qeth_get_buffer(&card->write);
if (iob)
iob->finalize = qeth_mpc_finalize_cmd;
iob = qeth_alloc_cmd(&card->write, data_length, 1, QETH_TIMEOUT);
if (!iob)
return NULL;
memcpy(iob->data, data, data_length);
qeth_setup_ccw(__ccw_from_cmd(iob), CCW_CMD_WRITE, 0, data_length,
iob->data);
iob->finalize = qeth_mpc_finalize_cmd;
return iob;
}
/**
* qeth_send_control_data() - send control command to the card
* @card: qeth_card structure pointer
* @len: size of the command buffer
* @iob: qeth_cmd_buffer pointer
* @reply_cb: callback function pointer
* @cb_card: pointer to the qeth_card structure
......@@ -1784,7 +1685,7 @@ static struct qeth_cmd_buffer *qeth_mpc_get_cmd_buffer(struct qeth_card *card)
* field 'param' of the structure qeth_reply.
*/
static int qeth_send_control_data(struct qeth_card *card, int len,
static int qeth_send_control_data(struct qeth_card *card,
struct qeth_cmd_buffer *iob,
int (*reply_cb)(struct qeth_card *cb_card,
struct qeth_reply *cb_reply,
......@@ -1800,13 +1701,13 @@ static int qeth_send_control_data(struct qeth_card *card, int len,
reply = qeth_alloc_reply(card);
if (!reply) {
qeth_release_buffer(iob);
qeth_put_cmd(iob);
return -ENOMEM;
}
reply->callback = reply_cb;
reply->param = reply_param;
/* pairs with qeth_release_buffer(): */
/* pairs with qeth_put_cmd(): */
qeth_get_reply(reply);
iob->reply = reply;
......@@ -1815,13 +1716,13 @@ static int qeth_send_control_data(struct qeth_card *card, int len,
timeout);
if (timeout <= 0) {
qeth_put_reply(reply);
qeth_release_buffer(iob);
qeth_put_cmd(iob);
return (timeout == -ERESTARTSYS) ? -EINTR : -ETIME;
}
if (iob->finalize)
iob->finalize(card, iob, len);
QETH_DBF_HEX(CTRL, 2, iob->data, min(len, QETH_DBF_CTRL_LEN));
iob->finalize(card, iob);
QETH_DBF_HEX(CTRL, 2, iob->data, min(iob->length, QETH_DBF_CTRL_LEN));
qeth_enqueue_reply(card, reply);
......@@ -1836,7 +1737,7 @@ static int qeth_send_control_data(struct qeth_card *card, int len,
QETH_CARD_TEXT_(card, 2, " err%d", rc);
qeth_dequeue_reply(card, reply);
qeth_put_reply(reply);
qeth_release_buffer(iob);
qeth_put_cmd(iob);
atomic_set(&channel->irq_pending, 0);
wake_up(&card->wait_q);
return rc;
......@@ -1869,7 +1770,7 @@ static void qeth_read_conf_data_cb(struct qeth_card *card,
prcd[76] >= 0xF1 && prcd[76] <= 0xF4;
qeth_notify_reply(iob->reply, 0);
qeth_release_buffer(iob);
qeth_put_cmd(iob);
}
static int qeth_read_conf_data(struct qeth_card *card)
......@@ -1891,7 +1792,7 @@ static int qeth_read_conf_data(struct qeth_card *card)
qeth_setup_ccw(__ccw_from_cmd(iob), ciw->cmd, 0, iob->length,
iob->data);
return qeth_send_control_data(card, iob->length, iob, NULL, NULL);
return qeth_send_control_data(card, iob, NULL, NULL);
}
static int qeth_idx_check_activate_response(struct qeth_card *card,
......@@ -1958,7 +1859,7 @@ static void qeth_idx_activate_read_channel_cb(struct qeth_card *card,
out:
qeth_notify_reply(iob->reply, rc);
qeth_release_buffer(iob);
qeth_put_cmd(iob);
}
static void qeth_idx_activate_write_channel_cb(struct qeth_card *card,
......@@ -1985,7 +1886,7 @@ static void qeth_idx_activate_write_channel_cb(struct qeth_card *card,
out:
qeth_notify_reply(iob->reply, rc);
qeth_release_buffer(iob);
qeth_put_cmd(iob);
}
static void qeth_idx_setup_activate_cmd(struct qeth_card *card,
......@@ -2027,7 +1928,7 @@ static int qeth_idx_activate_read_channel(struct qeth_card *card)
qeth_idx_setup_activate_cmd(card, iob);
iob->callback = qeth_idx_activate_read_channel_cb;
rc = qeth_send_control_data(card, IDX_ACTIVATE_SIZE, iob, NULL, NULL);
rc = qeth_send_control_data(card, iob, NULL, NULL);
if (rc)
return rc;
......@@ -2051,7 +1952,7 @@ static int qeth_idx_activate_write_channel(struct qeth_card *card)
qeth_idx_setup_activate_cmd(card, iob);
iob->callback = qeth_idx_activate_write_channel_cb;
rc = qeth_send_control_data(card, IDX_ACTIVATE_SIZE, iob, NULL, NULL);
rc = qeth_send_control_data(card, iob, NULL, NULL);
if (rc)
return rc;
......@@ -2075,24 +1976,20 @@ static int qeth_cm_enable_cb(struct qeth_card *card, struct qeth_reply *reply,
static int qeth_cm_enable(struct qeth_card *card)
{
int rc;
struct qeth_cmd_buffer *iob;
QETH_CARD_TEXT(card, 2, "cmenable");
iob = qeth_mpc_get_cmd_buffer(card);
iob = qeth_mpc_alloc_cmd(card, CM_ENABLE, CM_ENABLE_SIZE);
if (!iob)
return -ENOMEM;
memcpy(iob->data, CM_ENABLE, CM_ENABLE_SIZE);
memcpy(QETH_CM_ENABLE_ISSUER_RM_TOKEN(iob->data),
&card->token.issuer_rm_r, QETH_MPC_TOKEN_LENGTH);
memcpy(QETH_CM_ENABLE_FILTER_TOKEN(iob->data),
&card->token.cm_filter_w, QETH_MPC_TOKEN_LENGTH);
rc = qeth_send_control_data(card, CM_ENABLE_SIZE, iob,
qeth_cm_enable_cb, NULL);
return rc;
return qeth_send_control_data(card, iob, qeth_cm_enable_cb, NULL);
}
static int qeth_cm_setup_cb(struct qeth_card *card, struct qeth_reply *reply,
......@@ -2111,25 +2008,21 @@ static int qeth_cm_setup_cb(struct qeth_card *card, struct qeth_reply *reply,
static int qeth_cm_setup(struct qeth_card *card)
{
int rc;
struct qeth_cmd_buffer *iob;
QETH_CARD_TEXT(card, 2, "cmsetup");
iob = qeth_mpc_get_cmd_buffer(card);
iob = qeth_mpc_alloc_cmd(card, CM_SETUP, CM_SETUP_SIZE);
if (!iob)
return -ENOMEM;
memcpy(iob->data, CM_SETUP, CM_SETUP_SIZE);
memcpy(QETH_CM_SETUP_DEST_ADDR(iob->data),
&card->token.issuer_rm_r, QETH_MPC_TOKEN_LENGTH);
memcpy(QETH_CM_SETUP_CONNECTION_TOKEN(iob->data),
&card->token.cm_connection_w, QETH_MPC_TOKEN_LENGTH);
memcpy(QETH_CM_SETUP_FILTER_TOKEN(iob->data),
&card->token.cm_filter_r, QETH_MPC_TOKEN_LENGTH);
rc = qeth_send_control_data(card, CM_SETUP_SIZE, iob,
qeth_cm_setup_cb, NULL);
return rc;
return qeth_send_control_data(card, iob, qeth_cm_setup_cb, NULL);
}
static int qeth_update_max_mtu(struct qeth_card *card, unsigned int max_mtu)
......@@ -2235,19 +2128,17 @@ static int qeth_ulp_enable(struct qeth_card *card)
QETH_CARD_TEXT(card, 2, "ulpenabl");
iob = qeth_mpc_get_cmd_buffer(card);
iob = qeth_mpc_alloc_cmd(card, ULP_ENABLE, ULP_ENABLE_SIZE);
if (!iob)
return -ENOMEM;
memcpy(iob->data, ULP_ENABLE, ULP_ENABLE_SIZE);
*(QETH_ULP_ENABLE_LINKNUM(iob->data)) = (u8) card->dev->dev_port;
memcpy(QETH_ULP_ENABLE_PROT_TYPE(iob->data), &prot_type, 1);
memcpy(QETH_ULP_ENABLE_DEST_ADDR(iob->data),
&card->token.cm_connection_r, QETH_MPC_TOKEN_LENGTH);
memcpy(QETH_ULP_ENABLE_FILTER_TOKEN(iob->data),
&card->token.ulp_filter_w, QETH_MPC_TOKEN_LENGTH);
rc = qeth_send_control_data(card, ULP_ENABLE_SIZE, iob,
qeth_ulp_enable_cb, &max_mtu);
rc = qeth_send_control_data(card, iob, qeth_ulp_enable_cb, &max_mtu);
if (rc)
return rc;
return qeth_update_max_mtu(card, max_mtu);
......@@ -2276,18 +2167,16 @@ static int qeth_ulp_setup_cb(struct qeth_card *card, struct qeth_reply *reply,
static int qeth_ulp_setup(struct qeth_card *card)
{
int rc;
__u16 temp;
struct qeth_cmd_buffer *iob;
struct ccw_dev_id dev_id;
QETH_CARD_TEXT(card, 2, "ulpsetup");
iob = qeth_mpc_get_cmd_buffer(card);
iob = qeth_mpc_alloc_cmd(card, ULP_SETUP, ULP_SETUP_SIZE);
if (!iob)
return -ENOMEM;
memcpy(iob->data, ULP_SETUP, ULP_SETUP_SIZE);
memcpy(QETH_ULP_SETUP_DEST_ADDR(iob->data),
&card->token.cm_connection_r, QETH_MPC_TOKEN_LENGTH);
memcpy(QETH_ULP_SETUP_CONNECTION_TOKEN(iob->data),
......@@ -2299,9 +2188,7 @@ static int qeth_ulp_setup(struct qeth_card *card)
memcpy(QETH_ULP_SETUP_CUA(iob->data), &dev_id.devno, 2);
temp = (card->info.cula << 8) + card->info.unit_addr2;
memcpy(QETH_ULP_SETUP_REAL_DEVADDR(iob->data), &temp, 2);
rc = qeth_send_control_data(card, ULP_SETUP_SIZE, iob,
qeth_ulp_setup_cb, NULL);
return rc;
return qeth_send_control_data(card, iob, qeth_ulp_setup_cb, NULL);
}
static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *q, int bidx)
......@@ -2468,22 +2355,19 @@ static int qeth_qdio_activate(struct qeth_card *card)
static int qeth_dm_act(struct qeth_card *card)
{
int rc;
struct qeth_cmd_buffer *iob;
QETH_CARD_TEXT(card, 2, "dmact");
iob = qeth_mpc_get_cmd_buffer(card);
iob = qeth_mpc_alloc_cmd(card, DM_ACT, DM_ACT_SIZE);
if (!iob)
return -ENOMEM;
memcpy(iob->data, DM_ACT, DM_ACT_SIZE);
memcpy(QETH_DM_ACT_DEST_ADDR(iob->data),
&card->token.cm_connection_r, QETH_MPC_TOKEN_LENGTH);
memcpy(QETH_DM_ACT_CONNECTION_TOKEN(iob->data),
&card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
rc = qeth_send_control_data(card, DM_ACT_SIZE, iob, NULL, NULL);
return rc;
return qeth_send_control_data(card, iob, NULL, NULL);
}
static int qeth_mpc_initialize(struct qeth_card *card)
......@@ -2728,36 +2612,10 @@ int qeth_init_qdio_queues(struct qeth_card *card)
}
EXPORT_SYMBOL_GPL(qeth_init_qdio_queues);
static __u8 qeth_get_ipa_adp_type(enum qeth_link_types link_type)
{
switch (link_type) {
case QETH_LINK_TYPE_HSTR:
return 2;
default:
return 1;
}
}
static void qeth_fill_ipacmd_header(struct qeth_card *card,
struct qeth_ipa_cmd *cmd,
enum qeth_ipa_cmds command,
enum qeth_prot_versions prot)
{
cmd->hdr.command = command;
cmd->hdr.initiator = IPA_CMD_INITIATOR_HOST;
/* cmd->hdr.seqno is set by qeth_send_control_data() */
cmd->hdr.adapter_type = qeth_get_ipa_adp_type(card->info.link_type);
cmd->hdr.rel_adapter_no = (u8) card->dev->dev_port;
cmd->hdr.prim_version_no = IS_LAYER2(card) ? 2 : 1;
cmd->hdr.param_count = 1;
cmd->hdr.prot_version = prot;
}
static void qeth_ipa_finalize_cmd(struct qeth_card *card,
struct qeth_cmd_buffer *iob,
unsigned int length)
struct qeth_cmd_buffer *iob)
{
qeth_mpc_finalize_cmd(card, iob, length);
qeth_mpc_finalize_cmd(card, iob);
/* override with IPA-specific values: */
__ipa_cmd(iob)->hdr.seqno = card->seqno.ipa;
......@@ -2767,11 +2625,12 @@ static void qeth_ipa_finalize_cmd(struct qeth_card *card,
void qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
u16 cmd_length)
{
u16 total_length = IPA_PDU_HEADER_SIZE + cmd_length;
u8 prot_type = qeth_mpc_select_prot_type(card);
u16 total_length = iob->length;
qeth_setup_ccw(__ccw_from_cmd(iob), CCW_CMD_WRITE, 0, total_length,
iob->data);
iob->finalize = qeth_ipa_finalize_cmd;
iob->timeout = QETH_IPA_TIMEOUT;
memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
memcpy(QETH_IPA_PDU_LEN_TOTAL(iob->data), &total_length, 2);
......@@ -2784,25 +2643,35 @@ void qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
}
EXPORT_SYMBOL_GPL(qeth_prepare_ipa_cmd);
struct qeth_cmd_buffer *qeth_get_ipacmd_buffer(struct qeth_card *card,
enum qeth_ipa_cmds ipacmd, enum qeth_prot_versions prot)
struct qeth_cmd_buffer *qeth_ipa_alloc_cmd(struct qeth_card *card,
enum qeth_ipa_cmds cmd_code,
enum qeth_prot_versions prot,
unsigned int data_length)
{
enum qeth_link_types link_type = card->info.link_type;
struct qeth_cmd_buffer *iob;
struct qeth_ipacmd_hdr *hdr;
iob = qeth_get_buffer(&card->write);
if (iob) {
qeth_prepare_ipa_cmd(card, iob, sizeof(struct qeth_ipa_cmd));
qeth_fill_ipacmd_header(card, __ipa_cmd(iob), ipacmd, prot);
} else {
dev_warn(&card->gdev->dev,
"The qeth driver ran out of channel command buffers\n");
QETH_DBF_MESSAGE(1, "device %x ran out of channel command buffers",
CARD_DEVID(card));
}
data_length += offsetof(struct qeth_ipa_cmd, data);
iob = qeth_alloc_cmd(&card->write, IPA_PDU_HEADER_SIZE + data_length, 1,
QETH_IPA_TIMEOUT);
if (!iob)
return NULL;
qeth_prepare_ipa_cmd(card, iob, data_length);
hdr = &__ipa_cmd(iob)->hdr;
hdr->command = cmd_code;
hdr->initiator = IPA_CMD_INITIATOR_HOST;
/* hdr->seqno is set by qeth_send_control_data() */
hdr->adapter_type = (link_type == QETH_LINK_TYPE_HSTR) ? 2 : 1;
hdr->rel_adapter_no = (u8) card->dev->dev_port;
hdr->prim_version_no = IS_LAYER2(card) ? 2 : 1;
hdr->param_count = 1;
hdr->prot_version = prot;
return iob;
}
EXPORT_SYMBOL_GPL(qeth_get_ipacmd_buffer);
EXPORT_SYMBOL_GPL(qeth_ipa_alloc_cmd);
static int qeth_send_ipa_cmd_cb(struct qeth_card *card,
struct qeth_reply *reply, unsigned long data)
......@@ -2823,20 +2692,18 @@ int qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
unsigned long),
void *reply_param)
{
u16 length;
int rc;
QETH_CARD_TEXT(card, 4, "sendipa");
if (card->read_or_write_problem) {
qeth_release_buffer(iob);
qeth_put_cmd(iob);
return -EIO;
}
if (reply_cb == NULL)
reply_cb = qeth_send_ipa_cmd_cb;
memcpy(&length, QETH_IPA_PDU_LEN_TOTAL(iob->data), 2);
rc = qeth_send_control_data(card, length, iob, reply_cb, reply_param);
rc = qeth_send_control_data(card, iob, reply_cb, reply_param);
if (rc == -ETIME) {
qeth_clear_ipacmd_list(card);
qeth_schedule_recovery(card);
......@@ -2862,7 +2729,7 @@ static int qeth_send_startlan(struct qeth_card *card)
QETH_CARD_TEXT(card, 2, "strtlan");
iob = qeth_get_ipacmd_buffer(card, IPA_CMD_STARTLAN, 0);
iob = qeth_ipa_alloc_cmd(card, IPA_CMD_STARTLAN, QETH_PROT_NONE, 0);
if (!iob)
return -ENOMEM;
return qeth_send_ipa_cmd(card, iob, qeth_send_startlan_cb, NULL);
......@@ -2896,21 +2763,24 @@ static int qeth_query_setadapterparms_cb(struct qeth_card *card,
}
static struct qeth_cmd_buffer *qeth_get_adapter_cmd(struct qeth_card *card,
__u32 command, __u32 cmdlen)
enum qeth_ipa_setadp_cmd adp_cmd,
unsigned int data_length)
{
struct qeth_ipacmd_setadpparms_hdr *hdr;
struct qeth_cmd_buffer *iob;
struct qeth_ipa_cmd *cmd;
iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETADAPTERPARMS,
QETH_PROT_IPV4);
if (iob) {
cmd = __ipa_cmd(iob);
cmd->data.setadapterparms.hdr.cmdlength = cmdlen;
cmd->data.setadapterparms.hdr.command_code = command;
cmd->data.setadapterparms.hdr.used_total = 1;
cmd->data.setadapterparms.hdr.seq_no = 1;
}
iob = qeth_ipa_alloc_cmd(card, IPA_CMD_SETADAPTERPARMS, QETH_PROT_IPV4,
data_length +
offsetof(struct qeth_ipacmd_setadpparms,
data));
if (!iob)
return NULL;
hdr = &__ipa_cmd(iob)->data.setadapterparms.hdr;
hdr->cmdlength = sizeof(*hdr) + data_length;
hdr->command_code = adp_cmd;
hdr->used_total = 1;
hdr->seq_no = 1;
return iob;
}
......@@ -2921,7 +2791,7 @@ static int qeth_query_setadapterparms(struct qeth_card *card)
QETH_CARD_TEXT(card, 3, "queryadp");
iob = qeth_get_adapter_cmd(card, IPA_SETADP_QUERY_COMMANDS_SUPPORTED,
sizeof(struct qeth_ipacmd_setadpparms));
SETADP_DATA_SIZEOF(query_cmds_supp));
if (!iob)
return -ENOMEM;
rc = qeth_send_ipa_cmd(card, iob, qeth_query_setadapterparms_cb, NULL);
......@@ -2971,7 +2841,7 @@ static int qeth_query_ipassists(struct qeth_card *card,
struct qeth_cmd_buffer *iob;
QETH_CARD_TEXT_(card, 2, "qipassi%i", prot);
iob = qeth_get_ipacmd_buffer(card, IPA_CMD_QIPASSIST, prot);
iob = qeth_ipa_alloc_cmd(card, IPA_CMD_QIPASSIST, prot, 0);
if (!iob)
return -ENOMEM;
rc = qeth_send_ipa_cmd(card, iob, qeth_query_ipassists_cb, NULL);
......@@ -3008,14 +2878,32 @@ int qeth_query_switch_attributes(struct qeth_card *card,
return -EOPNOTSUPP;
if (!netif_carrier_ok(card->dev))
return -ENOMEDIUM;
iob = qeth_get_adapter_cmd(card, IPA_SETADP_QUERY_SWITCH_ATTRIBUTES,
sizeof(struct qeth_ipacmd_setadpparms_hdr));
iob = qeth_get_adapter_cmd(card, IPA_SETADP_QUERY_SWITCH_ATTRIBUTES, 0);
if (!iob)
return -ENOMEM;
return qeth_send_ipa_cmd(card, iob,
qeth_query_switch_attributes_cb, sw_info);
}
struct qeth_cmd_buffer *qeth_get_diag_cmd(struct qeth_card *card,
enum qeth_diags_cmds sub_cmd,
unsigned int data_length)
{
struct qeth_ipacmd_diagass *cmd;
struct qeth_cmd_buffer *iob;
iob = qeth_ipa_alloc_cmd(card, IPA_CMD_SET_DIAG_ASS, QETH_PROT_NONE,
DIAG_HDR_LEN + data_length);
if (!iob)
return NULL;
cmd = &__ipa_cmd(iob)->data.diagass;
cmd->subcmd_len = DIAG_SUB_HDR_LEN + data_length;
cmd->subcmd = sub_cmd;
return iob;
}
EXPORT_SYMBOL_GPL(qeth_get_diag_cmd);
static int qeth_query_setdiagass_cb(struct qeth_card *card,
struct qeth_reply *reply, unsigned long data)
{
......@@ -3034,15 +2922,11 @@ static int qeth_query_setdiagass_cb(struct qeth_card *card,
static int qeth_query_setdiagass(struct qeth_card *card)
{
struct qeth_cmd_buffer *iob;
struct qeth_ipa_cmd *cmd;
QETH_CARD_TEXT(card, 2, "qdiagass");
iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SET_DIAG_ASS, 0);
iob = qeth_get_diag_cmd(card, QETH_DIAGS_CMD_QUERY, 0);
if (!iob)
return -ENOMEM;
cmd = __ipa_cmd(iob);
cmd->data.diagass.subcmd_len = 16;
cmd->data.diagass.subcmd = QETH_DIAGS_CMD_QUERY;
return qeth_send_ipa_cmd(card, iob, qeth_query_setdiagass_cb, NULL);
}
......@@ -3090,12 +2974,10 @@ int qeth_hw_trap(struct qeth_card *card, enum qeth_diags_trap_action action)
struct qeth_ipa_cmd *cmd;
QETH_CARD_TEXT(card, 2, "diagtrap");
iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SET_DIAG_ASS, 0);
iob = qeth_get_diag_cmd(card, QETH_DIAGS_CMD_TRAP, 64);
if (!iob)
return -ENOMEM;
cmd = __ipa_cmd(iob);
cmd->data.diagass.subcmd_len = 80;
cmd->data.diagass.subcmd = QETH_DIAGS_CMD_TRAP;
cmd->data.diagass.type = 1;
cmd->data.diagass.action = action;
switch (action) {
......@@ -4026,11 +3908,10 @@ static void qeth_fill_tso_ext(struct qeth_hdr_tso *hdr,
}
int qeth_xmit(struct qeth_card *card, struct sk_buff *skb,
struct qeth_qdio_out_q *queue, int ipv, int cast_type,
struct qeth_qdio_out_q *queue, int ipv,
void (*fill_header)(struct qeth_qdio_out_q *queue,
struct qeth_hdr *hdr, struct sk_buff *skb,
int ipv, int cast_type,
unsigned int data_len))
int ipv, unsigned int data_len))
{
unsigned int proto_len, hw_hdr_len;
unsigned int frame_len = skb->len;
......@@ -4064,7 +3945,7 @@ int qeth_xmit(struct qeth_card *card, struct sk_buff *skb,
data_offset = push_len + proto_len;
}
memset(hdr, 0, hw_hdr_len);
fill_header(queue, hdr, skb, ipv, cast_type, frame_len);
fill_header(queue, hdr, skb, ipv, frame_len);
if (is_tso)
qeth_fill_tso_ext((struct qeth_hdr_tso *) hdr,
frame_len - proto_len, skb, proto_len);
......@@ -4133,7 +4014,7 @@ void qeth_setadp_promisc_mode(struct qeth_card *card)
QETH_CARD_TEXT_(card, 4, "mode:%x", mode);
iob = qeth_get_adapter_cmd(card, IPA_SETADP_SET_PROMISC_MODE,
sizeof(struct qeth_ipacmd_setadpparms_hdr) + 8);
SETADP_DATA_SIZEOF(mode));
if (!iob)
return;
cmd = __ipa_cmd(iob);
......@@ -4173,8 +4054,7 @@ int qeth_setadpparms_change_macaddr(struct qeth_card *card)
QETH_CARD_TEXT(card, 4, "chgmac");
iob = qeth_get_adapter_cmd(card, IPA_SETADP_ALTER_MAC_ADDRESS,
sizeof(struct qeth_ipacmd_setadpparms_hdr) +
sizeof(struct qeth_change_addr));
SETADP_DATA_SIZEOF(change_addr));
if (!iob)
return -ENOMEM;
cmd = __ipa_cmd(iob);
......@@ -4283,8 +4163,7 @@ static int qeth_setadpparms_set_access_ctrl(struct qeth_card *card,
QETH_CARD_TEXT(card, 4, "setacctl");
iob = qeth_get_adapter_cmd(card, IPA_SETADP_SET_ACCESS_CONTROL,
sizeof(struct qeth_ipacmd_setadpparms_hdr) +
sizeof(struct qeth_set_access_ctrl));
SETADP_DATA_SIZEOF(set_access_ctrl));
if (!iob)
return -ENOMEM;
cmd = __ipa_cmd(iob);
......@@ -4440,18 +4319,13 @@ static int qeth_snmp_command_cb(struct qeth_card *card,
return -ENOSPC;
}
QETH_CARD_TEXT_(card, 4, "snore%i",
cmd->data.setadapterparms.hdr.used_total);
cmd->data.setadapterparms.hdr.used_total);
QETH_CARD_TEXT_(card, 4, "sseqn%i",
cmd->data.setadapterparms.hdr.seq_no);
cmd->data.setadapterparms.hdr.seq_no);
/*copy entries to user buffer*/
memcpy(qinfo->udata + qinfo->udata_offset, snmp_data, data_len);
qinfo->udata_offset += data_len;
/* check if all replies received ... */
QETH_CARD_TEXT_(card, 4, "srtot%i",
cmd->data.setadapterparms.hdr.used_total);
QETH_CARD_TEXT_(card, 4, "srseq%i",
cmd->data.setadapterparms.hdr.seq_no);
if (cmd->data.setadapterparms.hdr.seq_no <
cmd->data.setadapterparms.hdr.used_total)
return 1;
......@@ -4460,9 +4334,8 @@ static int qeth_snmp_command_cb(struct qeth_card *card,
static int qeth_snmp_command(struct qeth_card *card, char __user *udata)
{
struct qeth_snmp_ureq __user *ureq;
struct qeth_cmd_buffer *iob;
struct qeth_ipa_cmd *cmd;
struct qeth_snmp_ureq *ureq;
unsigned int req_len;
struct qeth_arp_query_info qinfo = {0, };
int rc = 0;
......@@ -4476,38 +4349,28 @@ static int qeth_snmp_command(struct qeth_card *card, char __user *udata)
IS_LAYER3(card))
return -EOPNOTSUPP;
/* skip 4 bytes (data_len struct member) to get req_len */
if (copy_from_user(&req_len, udata + sizeof(int), sizeof(int)))
ureq = (struct qeth_snmp_ureq __user *) udata;
if (get_user(qinfo.udata_len, &ureq->hdr.data_len) ||
get_user(req_len, &ureq->hdr.req_len))
return -EFAULT;
iob = qeth_get_adapter_cmd(card, IPA_SETADP_SET_SNMP_CONTROL, req_len);
if (!iob)
return -ENOMEM;
if (copy_from_user(&__ipa_cmd(iob)->data.setadapterparms.data.snmp,
&ureq->cmd, req_len)) {
qeth_put_cmd(iob);
return -EFAULT;
if (req_len > (QETH_BUFSIZE - IPA_PDU_HEADER_SIZE -
sizeof(struct qeth_ipacmd_hdr) -
sizeof(struct qeth_ipacmd_setadpparms_hdr)))
return -EINVAL;
ureq = memdup_user(udata, req_len + sizeof(struct qeth_snmp_ureq_hdr));
if (IS_ERR(ureq)) {
QETH_CARD_TEXT(card, 2, "snmpnome");
return PTR_ERR(ureq);
}
qinfo.udata_len = ureq->hdr.data_len;
qinfo.udata = kzalloc(qinfo.udata_len, GFP_KERNEL);
if (!qinfo.udata) {
kfree(ureq);
qeth_put_cmd(iob);
return -ENOMEM;
}
qinfo.udata_offset = sizeof(struct qeth_snmp_ureq_hdr);
iob = qeth_get_adapter_cmd(card, IPA_SETADP_SET_SNMP_CONTROL,
QETH_SNMP_SETADP_CMDLENGTH + req_len);
if (!iob) {
rc = -ENOMEM;
goto out;
}
/* for large requests, fix-up the length fields: */
qeth_prepare_ipa_cmd(card, iob, QETH_SETADP_BASE_LEN + req_len);
cmd = __ipa_cmd(iob);
memcpy(&cmd->data.setadapterparms.data.snmp, &ureq->cmd, req_len);
rc = qeth_send_ipa_cmd(card, iob, qeth_snmp_command_cb, &qinfo);
if (rc)
QETH_DBF_MESSAGE(2, "SNMP command failed on device %x: (%#x)\n",
......@@ -4516,8 +4379,7 @@ static int qeth_snmp_command(struct qeth_card *card, char __user *udata)
if (copy_to_user(udata, qinfo.udata, qinfo.udata_len))
rc = -EFAULT;
}
out:
kfree(ureq);
kfree(qinfo.udata);
return rc;
}
......@@ -4583,8 +4445,7 @@ static int qeth_query_oat_command(struct qeth_card *card, char __user *udata)
}
iob = qeth_get_adapter_cmd(card, IPA_SETADP_QUERY_OAT,
sizeof(struct qeth_ipacmd_setadpparms_hdr) +
sizeof(struct qeth_query_oat));
SETADP_DATA_SIZEOF(query_oat));
if (!iob) {
rc = -ENOMEM;
goto out_free;
......@@ -4646,8 +4507,7 @@ int qeth_query_card_info(struct qeth_card *card,
QETH_CARD_TEXT(card, 2, "qcrdinfo");
if (!qeth_adp_supported(card, IPA_SETADP_QUERY_CARD_INFO))
return -EOPNOTSUPP;
iob = qeth_get_adapter_cmd(card, IPA_SETADP_QUERY_CARD_INFO,
sizeof(struct qeth_ipacmd_setadpparms_hdr));
iob = qeth_get_adapter_cmd(card, IPA_SETADP_QUERY_CARD_INFO, 0);
if (!iob)
return -ENOMEM;
return qeth_send_ipa_cmd(card, iob, qeth_query_card_info_cb,
......@@ -4901,7 +4761,7 @@ static void qeth_core_free_card(struct qeth_card *card)
qeth_clean_channel(&card->read);
qeth_clean_channel(&card->write);
qeth_clean_channel(&card->data);
qeth_release_buffer(card->read_cmd);
qeth_put_cmd(card->read_cmd);
destroy_workqueue(card->event_wq);
qeth_free_qdio_queues(card);
unregister_service_level(&card->qeth_service_level);
......@@ -5314,42 +5174,47 @@ EXPORT_SYMBOL_GPL(qeth_setassparms_cb);
struct qeth_cmd_buffer *qeth_get_setassparms_cmd(struct qeth_card *card,
enum qeth_ipa_funcs ipa_func,
__u16 cmd_code, __u16 len,
u16 cmd_code,
unsigned int data_length,
enum qeth_prot_versions prot)
{
struct qeth_ipacmd_setassparms *setassparms;
struct qeth_ipacmd_setassparms_hdr *hdr;
struct qeth_cmd_buffer *iob;
struct qeth_ipa_cmd *cmd;
QETH_CARD_TEXT(card, 4, "getasscm");
iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETASSPARMS, prot);
iob = qeth_ipa_alloc_cmd(card, IPA_CMD_SETASSPARMS, prot,
data_length +
offsetof(struct qeth_ipacmd_setassparms,
data));
if (!iob)
return NULL;
if (iob) {
cmd = __ipa_cmd(iob);
cmd->data.setassparms.hdr.assist_no = ipa_func;
cmd->data.setassparms.hdr.length = 8 + len;
cmd->data.setassparms.hdr.command_code = cmd_code;
}
setassparms = &__ipa_cmd(iob)->data.setassparms;
setassparms->assist_no = ipa_func;
hdr = &setassparms->hdr;
hdr->length = sizeof(*hdr) + data_length;
hdr->command_code = cmd_code;
return iob;
}
EXPORT_SYMBOL_GPL(qeth_get_setassparms_cmd);
int qeth_send_simple_setassparms_prot(struct qeth_card *card,
enum qeth_ipa_funcs ipa_func,
u16 cmd_code, long data,
u16 cmd_code, u32 *data,
enum qeth_prot_versions prot)
{
int length = 0;
unsigned int length = data ? SETASS_DATA_SIZEOF(flags_32bit) : 0;
struct qeth_cmd_buffer *iob;
QETH_CARD_TEXT_(card, 4, "simassp%i", prot);
if (data)
length = sizeof(__u32);
iob = qeth_get_setassparms_cmd(card, ipa_func, cmd_code, length, prot);
if (!iob)
return -ENOMEM;
__ipa_cmd(iob)->data.setassparms.data.flags_32bit = (__u32) data;
if (data)
__ipa_cmd(iob)->data.setassparms.data.flags_32bit = *data;
return qeth_send_ipa_cmd(card, iob, qeth_setassparms_cb, NULL);
}
EXPORT_SYMBOL_GPL(qeth_send_simple_setassparms_prot);
......@@ -5723,28 +5588,30 @@ static void qeth_core_shutdown(struct ccwgroup_device *gdev)
qdio_free(CARD_DDEV(card));
}
static int qeth_core_freeze(struct ccwgroup_device *gdev)
static int qeth_suspend(struct ccwgroup_device *gdev)
{
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
if (card->discipline && card->discipline->freeze)
return card->discipline->freeze(gdev);
return 0;
}
static int qeth_core_thaw(struct ccwgroup_device *gdev)
{
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
if (card->discipline && card->discipline->thaw)
return card->discipline->thaw(gdev);
qeth_set_allowed_threads(card, 0, 1);
wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
if (gdev->state == CCWGROUP_OFFLINE)
return 0;
card->discipline->set_offline(gdev);
return 0;
}
static int qeth_core_restore(struct ccwgroup_device *gdev)
static int qeth_resume(struct ccwgroup_device *gdev)
{
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
if (card->discipline && card->discipline->restore)
return card->discipline->restore(gdev);
return 0;
int rc;
rc = card->discipline->set_online(gdev);
qeth_set_allowed_threads(card, 0xffffffff, 0);
if (rc)
dev_warn(&card->gdev->dev, "The qeth device driver failed to recover an error on the device\n");
return rc;
}
static ssize_t group_store(struct device_driver *ddrv, const char *buf,
......@@ -5785,9 +5652,9 @@ static struct ccwgroup_driver qeth_core_ccwgroup_driver = {
.shutdown = qeth_core_shutdown,
.prepare = NULL,
.complete = NULL,
.freeze = qeth_core_freeze,
.thaw = qeth_core_thaw,
.restore = qeth_core_restore,
.freeze = qeth_suspend,
.thaw = qeth_resume,
.restore = qeth_resume,
};
struct qeth_card *qeth_get_card_by_busid(char *bus_id)
......@@ -5866,8 +5733,8 @@ static int qeth_start_csum_cb(struct qeth_card *card, struct qeth_reply *reply,
static int qeth_set_csum_off(struct qeth_card *card, enum qeth_ipa_funcs cstype,
enum qeth_prot_versions prot)
{
return qeth_send_simple_setassparms_prot(card, cstype,
IPA_CMD_ASS_STOP, 0, prot);
return qeth_send_simple_setassparms_prot(card, cstype, IPA_CMD_ASS_STOP,
NULL, prot);
}
static int qeth_set_csum_on(struct qeth_card *card, enum qeth_ipa_funcs cstype,
......@@ -5898,7 +5765,8 @@ static int qeth_set_csum_on(struct qeth_card *card, enum qeth_ipa_funcs cstype,
return -EOPNOTSUPP;
}
iob = qeth_get_setassparms_cmd(card, cstype, IPA_CMD_ASS_ENABLE, 4,
iob = qeth_get_setassparms_cmd(card, cstype, IPA_CMD_ASS_ENABLE,
SETASS_DATA_SIZEOF(flags_32bit),
prot);
if (!iob) {
qeth_set_csum_off(card, cstype, prot);
......@@ -5955,7 +5823,7 @@ static int qeth_set_tso_off(struct qeth_card *card,
enum qeth_prot_versions prot)
{
return qeth_send_simple_setassparms_prot(card, IPA_OUTBOUND_TSO,
IPA_CMD_ASS_STOP, 0, prot);
IPA_CMD_ASS_STOP, NULL, prot);
}
static int qeth_set_tso_on(struct qeth_card *card,
......@@ -5981,7 +5849,8 @@ static int qeth_set_tso_on(struct qeth_card *card,
}
iob = qeth_get_setassparms_cmd(card, IPA_OUTBOUND_TSO,
IPA_CMD_ASS_ENABLE, sizeof(caps), prot);
IPA_CMD_ASS_ENABLE,
SETASS_DATA_SIZEOF(caps), prot);
if (!iob) {
qeth_set_tso_off(card, prot);
return -ENOMEM;
......
......@@ -379,9 +379,7 @@ struct qeth_ipacmd_layer2setdelvlan {
__u16 vlan_id;
} __attribute__ ((packed));
struct qeth_ipacmd_setassparms_hdr {
__u32 assist_no;
__u16 length;
__u16 command_code;
__u16 return_code;
......@@ -426,6 +424,7 @@ struct qeth_tso_start_data {
/* SETASSPARMS IPA Command: */
struct qeth_ipacmd_setassparms {
u32 assist_no;
struct qeth_ipacmd_setassparms_hdr hdr;
union {
__u32 flags_32bit;
......@@ -437,6 +436,8 @@ struct qeth_ipacmd_setassparms {
} data;
} __attribute__ ((packed));
#define SETASS_DATA_SIZEOF(field) FIELD_SIZEOF(struct qeth_ipacmd_setassparms,\
data.field)
/* SETRTG IPA Command: ****************************************************/
struct qeth_set_routing {
......@@ -524,8 +525,6 @@ struct qeth_query_switch_attributes {
#define QETH_SETADP_FLAGS_VIRTUAL_MAC 0x80 /* for CHANGE_ADDR_READ_MAC */
struct qeth_ipacmd_setadpparms_hdr {
u32 supp_hw_cmds;
u32 reserved1;
u16 cmdlength;
u16 reserved2;
u32 command_code;
......@@ -537,6 +536,7 @@ struct qeth_ipacmd_setadpparms_hdr {
};
struct qeth_ipacmd_setadpparms {
struct qeth_ipa_caps hw_cmds;
struct qeth_ipacmd_setadpparms_hdr hdr;
union {
struct qeth_query_cmds_supp query_cmds_supp;
......@@ -550,6 +550,9 @@ struct qeth_ipacmd_setadpparms {
} data;
} __attribute__ ((packed));
#define SETADP_DATA_SIZEOF(field) FIELD_SIZEOF(struct qeth_ipacmd_setadpparms,\
data.field)
/* CREATE_ADDR IPA Command: ***********************************************/
struct qeth_create_destroy_address {
__u8 unique_id[8];
......@@ -596,6 +599,11 @@ struct qeth_ipacmd_diagass {
__u8 cdata[64];
} __attribute__ ((packed));
#define DIAG_HDR_LEN offsetofend(struct qeth_ipacmd_diagass, ext)
#define DIAG_SUB_HDR_LEN (offsetofend(struct qeth_ipacmd_diagass, ext) -\
offsetof(struct qeth_ipacmd_diagass, \
subcmd_len))
/* VNIC Characteristics IPA Command: *****************************************/
/* IPA commands/sub commands for VNICC */
#define IPA_VNICC_QUERY_CHARS 0x00000000L
......@@ -622,12 +630,6 @@ struct qeth_ipacmd_diagass {
/* VNICC header */
struct qeth_ipacmd_vnicc_hdr {
u32 sup;
u32 cur;
};
/* VNICC sub command header */
struct qeth_vnicc_sub_hdr {
u16 data_length;
u16 reserved;
u32 sub_command;
......@@ -652,15 +654,18 @@ struct qeth_vnicc_getset_timeout {
/* complete VNICC IPA command message */
struct qeth_ipacmd_vnicc {
struct qeth_ipa_caps vnicc_cmds;
struct qeth_ipacmd_vnicc_hdr hdr;
struct qeth_vnicc_sub_hdr sub_hdr;
union {
struct qeth_vnicc_query_cmds query_cmds;
struct qeth_vnicc_set_char set_char;
struct qeth_vnicc_getset_timeout getset_timeout;
};
} data;
};
#define VNICC_DATA_SIZEOF(field) FIELD_SIZEOF(struct qeth_ipacmd_vnicc,\
data.field)
/* SETBRIDGEPORT IPA Command: *********************************************/
enum qeth_ipa_sbp_cmd {
IPA_SBP_QUERY_COMMANDS_SUPPORTED = 0x00000000L,
......@@ -686,8 +691,6 @@ struct mac_addr_lnid {
} __packed;
struct qeth_ipacmd_sbp_hdr {
__u32 supported_sbp_cmds;
__u32 enabled_sbp_cmds;
__u16 cmdlength;
__u16 reserved1;
__u32 command_code;
......@@ -702,16 +705,10 @@ struct qeth_sbp_query_cmds_supp {
__u32 reserved;
} __packed;
struct qeth_sbp_reset_role {
} __packed;
struct qeth_sbp_set_primary {
struct net_if_token token;
} __packed;
struct qeth_sbp_set_secondary {
} __packed;
struct qeth_sbp_port_entry {
__u8 role;
__u8 state;
......@@ -737,17 +734,19 @@ struct qeth_sbp_state_change {
} __packed;
struct qeth_ipacmd_setbridgeport {
struct qeth_ipa_caps sbp_cmds;
struct qeth_ipacmd_sbp_hdr hdr;
union {
struct qeth_sbp_query_cmds_supp query_cmds_supp;
struct qeth_sbp_reset_role reset_role;
struct qeth_sbp_set_primary set_primary;
struct qeth_sbp_set_secondary set_secondary;
struct qeth_sbp_query_ports query_ports;
struct qeth_sbp_state_change state_change;
} data;
} __packed;
#define SBP_DATA_SIZEOF(field) FIELD_SIZEOF(struct qeth_ipacmd_setbridgeport,\
data.field)
/* ADDRESS_CHANGE_NOTIFICATION adapter-initiated "command" *******************/
/* Bitmask for entry->change_code. Both bits may be raised. */
enum qeth_ipa_addr_change_code {
......@@ -806,6 +805,8 @@ struct qeth_ipa_cmd {
} data;
} __attribute__ ((packed));
#define IPA_DATA_SIZEOF(field) FIELD_SIZEOF(struct qeth_ipa_cmd, data.field)
/*
* special command for ARP processing.
* this is not included in setassparms command before, because we get
......@@ -823,10 +824,6 @@ enum qeth_ipa_arp_return_codes {
extern const char *qeth_get_ipa_msg(enum qeth_ipa_return_codes rc);
extern const char *qeth_get_ipa_cmd_name(enum qeth_ipa_cmds cmd);
#define QETH_SETADP_BASE_LEN (sizeof(struct qeth_ipacmd_hdr) + \
sizeof(struct qeth_ipacmd_setadpparms_hdr))
#define QETH_SNMP_SETADP_CMDLENGTH 16
/* Helper functions */
#define IS_IPA_REPLY(cmd) ((cmd->hdr.initiator == IPA_CMD_INITIATOR_HOST) || \
(cmd->hdr.initiator == IPA_CMD_INITIATOR_OSA_REPLY))
......
......@@ -85,7 +85,8 @@ static int qeth_l2_send_setdelmac(struct qeth_card *card, __u8 *mac,
struct qeth_cmd_buffer *iob;
QETH_CARD_TEXT(card, 2, "L2sdmac");
iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4);
iob = qeth_ipa_alloc_cmd(card, ipacmd, QETH_PROT_IPV4,
IPA_DATA_SIZEOF(setdelmac));
if (!iob)
return -ENOMEM;
cmd = __ipa_cmd(iob);
......@@ -163,8 +164,9 @@ static void qeth_l2_drain_rx_mode_cache(struct qeth_card *card)
static void qeth_l2_fill_header(struct qeth_qdio_out_q *queue,
struct qeth_hdr *hdr, struct sk_buff *skb,
int ipv, int cast_type, unsigned int data_len)
int ipv, unsigned int data_len)
{
int cast_type = qeth_get_ether_cast_type(skb);
struct vlan_ethhdr *veth = vlan_eth_hdr(skb);
hdr->hdr.l2.pkt_length = data_len;
......@@ -240,7 +242,8 @@ static int qeth_l2_send_setdelvlan(struct qeth_card *card, __u16 i,
struct qeth_cmd_buffer *iob;
QETH_CARD_TEXT_(card, 4, "L2sdv%x", ipacmd);
iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4);
iob = qeth_ipa_alloc_cmd(card, ipacmd, QETH_PROT_IPV4,
IPA_DATA_SIZEOF(setdelvlan));
if (!iob)
return -ENOMEM;
cmd = __ipa_cmd(iob);
......@@ -292,7 +295,6 @@ static void qeth_l2_stop_card(struct qeth_card *card)
card->state = CARD_STATE_DOWN;
}
qeth_clear_cmd_buffers(&card->write);
flush_workqueue(card->event_wq);
card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
}
......@@ -597,7 +599,6 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb,
rc = qeth_l2_xmit_osn(card, skb, queue);
else
rc = qeth_xmit(card, skb, queue, qeth_get_ip_version(skb),
qeth_get_ether_cast_type(skb),
qeth_l2_fill_header);
if (!rc) {
......@@ -964,33 +965,6 @@ static void __exit qeth_l2_exit(void)
pr_info("unregister layer 2 discipline\n");
}
static int qeth_l2_pm_suspend(struct ccwgroup_device *gdev)
{
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
qeth_set_allowed_threads(card, 0, 1);
wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
if (gdev->state == CCWGROUP_OFFLINE)
return 0;
qeth_l2_set_offline(gdev);
return 0;
}
static int qeth_l2_pm_resume(struct ccwgroup_device *gdev)
{
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
int rc;
rc = qeth_l2_set_online(gdev);
qeth_set_allowed_threads(card, 0xffffffff, 0);
if (rc)
dev_warn(&card->gdev->dev, "The qeth device driver "
"failed to recover an error on the device\n");
return rc;
}
/* Returns zero if the command is successfully "consumed" */
static int qeth_l2_control_event(struct qeth_card *card,
struct qeth_ipa_cmd *cmd)
......@@ -1020,9 +994,6 @@ struct qeth_discipline qeth_l2_discipline = {
.remove = qeth_l2_remove_device,
.set_online = qeth_l2_set_online,
.set_offline = qeth_l2_set_offline,
.freeze = qeth_l2_pm_suspend,
.thaw = qeth_l2_pm_resume,
.restore = qeth_l2_pm_resume,
.do_ioctl = NULL,
.control_event_handler = qeth_l2_control_event,
};
......@@ -1032,7 +1003,7 @@ static void qeth_osn_assist_cb(struct qeth_card *card,
struct qeth_cmd_buffer *iob)
{
qeth_notify_reply(iob->reply, 0);
qeth_release_buffer(iob);
qeth_put_cmd(iob);
}
int qeth_osn_assist(struct net_device *dev, void *data, int data_len)
......@@ -1040,6 +1011,8 @@ int qeth_osn_assist(struct net_device *dev, void *data, int data_len)
struct qeth_cmd_buffer *iob;
struct qeth_card *card;
if (data_len < 0)
return -EINVAL;
if (!dev)
return -ENODEV;
card = dev->ml_priv;
......@@ -1048,7 +1021,9 @@ int qeth_osn_assist(struct net_device *dev, void *data, int data_len)
QETH_CARD_TEXT(card, 2, "osnsdmc");
if (!qeth_card_hw_is_reachable(card))
return -ENODEV;
iob = qeth_get_buffer(&card->write);
iob = qeth_alloc_cmd(&card->write, IPA_PDU_HEADER_SIZE + data_len, 1,
QETH_IPA_TIMEOUT);
if (!iob)
return -ENOMEM;
......@@ -1421,22 +1396,25 @@ static int qeth_bridgeport_makerc(struct qeth_card *card,
static struct qeth_cmd_buffer *qeth_sbp_build_cmd(struct qeth_card *card,
enum qeth_ipa_sbp_cmd sbp_cmd,
unsigned int cmd_length)
unsigned int data_length)
{
enum qeth_ipa_cmds ipa_cmd = IS_IQD(card) ? IPA_CMD_SETBRIDGEPORT_IQD :
IPA_CMD_SETBRIDGEPORT_OSA;
struct qeth_ipacmd_sbp_hdr *hdr;
struct qeth_cmd_buffer *iob;
struct qeth_ipa_cmd *cmd;
iob = qeth_get_ipacmd_buffer(card, ipa_cmd, 0);
iob = qeth_ipa_alloc_cmd(card, ipa_cmd, QETH_PROT_NONE,
data_length +
offsetof(struct qeth_ipacmd_setbridgeport,
data));
if (!iob)
return iob;
cmd = __ipa_cmd(iob);
cmd->data.sbp.hdr.cmdlength = sizeof(struct qeth_ipacmd_sbp_hdr) +
cmd_length;
cmd->data.sbp.hdr.command_code = sbp_cmd;
cmd->data.sbp.hdr.used_total = 1;
cmd->data.sbp.hdr.seq_no = 1;
hdr = &__ipa_cmd(iob)->data.sbp.hdr;
hdr->cmdlength = sizeof(*hdr) + data_length;
hdr->command_code = sbp_cmd;
hdr->used_total = 1;
hdr->seq_no = 1;
return iob;
}
......@@ -1471,7 +1449,7 @@ static void qeth_bridgeport_query_support(struct qeth_card *card)
QETH_CARD_TEXT(card, 2, "brqsuppo");
iob = qeth_sbp_build_cmd(card, IPA_SBP_QUERY_COMMANDS_SUPPORTED,
sizeof(struct qeth_sbp_query_cmds_supp));
SBP_DATA_SIZEOF(query_cmds_supp));
if (!iob)
return;
......@@ -1563,23 +1541,21 @@ static int qeth_bridgeport_set_cb(struct qeth_card *card,
*/
int qeth_bridgeport_setrole(struct qeth_card *card, enum qeth_sbp_roles role)
{
int cmdlength;
struct qeth_cmd_buffer *iob;
enum qeth_ipa_sbp_cmd setcmd;
unsigned int cmdlength = 0;
QETH_CARD_TEXT(card, 2, "brsetrol");
switch (role) {
case QETH_SBP_ROLE_NONE:
setcmd = IPA_SBP_RESET_BRIDGE_PORT_ROLE;
cmdlength = sizeof(struct qeth_sbp_reset_role);
break;
case QETH_SBP_ROLE_PRIMARY:
setcmd = IPA_SBP_SET_PRIMARY_BRIDGE_PORT;
cmdlength = sizeof(struct qeth_sbp_set_primary);
cmdlength = SBP_DATA_SIZEOF(set_primary);
break;
case QETH_SBP_ROLE_SECONDARY:
setcmd = IPA_SBP_SET_SECONDARY_BRIDGE_PORT;
cmdlength = sizeof(struct qeth_sbp_set_secondary);
break;
default:
return -EINVAL;
......@@ -1728,10 +1704,6 @@ static int qeth_l2_vnicc_makerc(struct qeth_card *card, u16 ipa_rc)
/* generic VNICC request call back control */
struct _qeth_l2_vnicc_request_cbctl {
u32 sub_cmd;
struct {
u32 vnic_char;
u32 timeout;
} param;
struct {
union{
u32 *sup_cmds;
......@@ -1754,80 +1726,52 @@ static int qeth_l2_vnicc_request_cb(struct qeth_card *card,
if (cmd->hdr.return_code)
return qeth_l2_vnicc_makerc(card, cmd->hdr.return_code);
/* return results to caller */
card->options.vnicc.sup_chars = rep->hdr.sup;
card->options.vnicc.cur_chars = rep->hdr.cur;
card->options.vnicc.sup_chars = rep->vnicc_cmds.supported;
card->options.vnicc.cur_chars = rep->vnicc_cmds.enabled;
if (cbctl->sub_cmd == IPA_VNICC_QUERY_CMDS)
*cbctl->result.sup_cmds = rep->query_cmds.sup_cmds;
*cbctl->result.sup_cmds = rep->data.query_cmds.sup_cmds;
if (cbctl->sub_cmd == IPA_VNICC_GET_TIMEOUT)
*cbctl->result.timeout = rep->getset_timeout.timeout;
*cbctl->result.timeout = rep->data.getset_timeout.timeout;
return 0;
}
/* generic VNICC request */
static int qeth_l2_vnicc_request(struct qeth_card *card,
struct _qeth_l2_vnicc_request_cbctl *cbctl)
static struct qeth_cmd_buffer *qeth_l2_vnicc_build_cmd(struct qeth_card *card,
u32 vnicc_cmd,
unsigned int data_length)
{
struct qeth_ipacmd_vnicc *req;
struct qeth_ipacmd_vnicc_hdr *hdr;
struct qeth_cmd_buffer *iob;
struct qeth_ipa_cmd *cmd;
QETH_CARD_TEXT(card, 2, "vniccreq");
/* get new buffer for request */
iob = qeth_get_ipacmd_buffer(card, IPA_CMD_VNICC, 0);
iob = qeth_ipa_alloc_cmd(card, IPA_CMD_VNICC, QETH_PROT_NONE,
data_length +
offsetof(struct qeth_ipacmd_vnicc, data));
if (!iob)
return -ENOMEM;
/* create header for request */
cmd = __ipa_cmd(iob);
req = &cmd->data.vnicc;
/* create sub command header for request */
req->sub_hdr.data_length = sizeof(req->sub_hdr);
req->sub_hdr.sub_command = cbctl->sub_cmd;
/* create sub command specific request fields */
switch (cbctl->sub_cmd) {
case IPA_VNICC_QUERY_CHARS:
break;
case IPA_VNICC_QUERY_CMDS:
req->sub_hdr.data_length += sizeof(req->query_cmds);
req->query_cmds.vnic_char = cbctl->param.vnic_char;
break;
case IPA_VNICC_ENABLE:
case IPA_VNICC_DISABLE:
req->sub_hdr.data_length += sizeof(req->set_char);
req->set_char.vnic_char = cbctl->param.vnic_char;
break;
case IPA_VNICC_SET_TIMEOUT:
req->getset_timeout.timeout = cbctl->param.timeout;
/* fallthrough */
case IPA_VNICC_GET_TIMEOUT:
req->sub_hdr.data_length += sizeof(req->getset_timeout);
req->getset_timeout.vnic_char = cbctl->param.vnic_char;
break;
default:
qeth_release_buffer(iob);
return -EOPNOTSUPP;
}
return NULL;
/* send request */
return qeth_send_ipa_cmd(card, iob, qeth_l2_vnicc_request_cb, cbctl);
hdr = &__ipa_cmd(iob)->data.vnicc.hdr;
hdr->data_length = sizeof(*hdr) + data_length;
hdr->sub_command = vnicc_cmd;
return iob;
}
/* VNICC query VNIC characteristics request */
static int qeth_l2_vnicc_query_chars(struct qeth_card *card)
{
struct _qeth_l2_vnicc_request_cbctl cbctl;
struct qeth_cmd_buffer *iob;
QETH_CARD_TEXT(card, 2, "vniccqch");
iob = qeth_l2_vnicc_build_cmd(card, IPA_VNICC_QUERY_CHARS, 0);
if (!iob)
return -ENOMEM;
/* prepare callback control */
cbctl.sub_cmd = IPA_VNICC_QUERY_CHARS;
QETH_CARD_TEXT(card, 2, "vniccqch");
return qeth_l2_vnicc_request(card, &cbctl);
return qeth_send_ipa_cmd(card, iob, qeth_l2_vnicc_request_cb, &cbctl);
}
/* VNICC query sub commands request */
......@@ -1835,14 +1779,21 @@ static int qeth_l2_vnicc_query_cmds(struct qeth_card *card, u32 vnic_char,
u32 *sup_cmds)
{
struct _qeth_l2_vnicc_request_cbctl cbctl;
struct qeth_cmd_buffer *iob;
QETH_CARD_TEXT(card, 2, "vniccqcm");
iob = qeth_l2_vnicc_build_cmd(card, IPA_VNICC_QUERY_CMDS,
VNICC_DATA_SIZEOF(query_cmds));
if (!iob)
return -ENOMEM;
__ipa_cmd(iob)->data.vnicc.data.query_cmds.vnic_char = vnic_char;
/* prepare callback control */
cbctl.sub_cmd = IPA_VNICC_QUERY_CMDS;
cbctl.param.vnic_char = vnic_char;
cbctl.result.sup_cmds = sup_cmds;
QETH_CARD_TEXT(card, 2, "vniccqcm");
return qeth_l2_vnicc_request(card, &cbctl);
return qeth_send_ipa_cmd(card, iob, qeth_l2_vnicc_request_cb, &cbctl);
}
/* VNICC enable/disable characteristic request */
......@@ -1850,31 +1801,47 @@ static int qeth_l2_vnicc_set_char(struct qeth_card *card, u32 vnic_char,
u32 cmd)
{
struct _qeth_l2_vnicc_request_cbctl cbctl;
struct qeth_cmd_buffer *iob;
QETH_CARD_TEXT(card, 2, "vniccedc");
iob = qeth_l2_vnicc_build_cmd(card, cmd, VNICC_DATA_SIZEOF(set_char));
if (!iob)
return -ENOMEM;
__ipa_cmd(iob)->data.vnicc.data.set_char.vnic_char = vnic_char;
/* prepare callback control */
cbctl.sub_cmd = cmd;
cbctl.param.vnic_char = vnic_char;
QETH_CARD_TEXT(card, 2, "vniccedc");
return qeth_l2_vnicc_request(card, &cbctl);
return qeth_send_ipa_cmd(card, iob, qeth_l2_vnicc_request_cb, &cbctl);
}
/* VNICC get/set timeout for characteristic request */
static int qeth_l2_vnicc_getset_timeout(struct qeth_card *card, u32 vnicc,
u32 cmd, u32 *timeout)
{
struct qeth_vnicc_getset_timeout *getset_timeout;
struct _qeth_l2_vnicc_request_cbctl cbctl;
struct qeth_cmd_buffer *iob;
QETH_CARD_TEXT(card, 2, "vniccgst");
iob = qeth_l2_vnicc_build_cmd(card, cmd,
VNICC_DATA_SIZEOF(getset_timeout));
if (!iob)
return -ENOMEM;
getset_timeout = &__ipa_cmd(iob)->data.vnicc.data.getset_timeout;
getset_timeout->vnic_char = vnicc;
if (cmd == IPA_VNICC_SET_TIMEOUT)
getset_timeout->timeout = *timeout;
/* prepare callback control */
cbctl.sub_cmd = cmd;
cbctl.param.vnic_char = vnicc;
if (cmd == IPA_VNICC_SET_TIMEOUT)
cbctl.param.timeout = *timeout;
if (cmd == IPA_VNICC_GET_TIMEOUT)
cbctl.result.timeout = timeout;
QETH_CARD_TEXT(card, 2, "vniccgst");
return qeth_l2_vnicc_request(card, &cbctl);
return qeth_send_ipa_cmd(card, iob, qeth_l2_vnicc_request_cb, &cbctl);
}
/* set current VNICC flag state; called from sysfs store function */
......
......@@ -32,7 +32,6 @@
#include <net/route.h>
#include <net/ipv6.h>
#include <net/ip6_route.h>
#include <net/ip6_fib.h>
#include <net/iucv/af_iucv.h>
#include <linux/hashtable.h>
......@@ -377,7 +376,8 @@ static int qeth_l3_send_setdelmc(struct qeth_card *card,
QETH_CARD_TEXT(card, 4, "setdelmc");
iob = qeth_get_ipacmd_buffer(card, ipacmd, addr->proto);
iob = qeth_ipa_alloc_cmd(card, ipacmd, addr->proto,
IPA_DATA_SIZEOF(setdelipm));
if (!iob)
return -ENOMEM;
cmd = __ipa_cmd(iob);
......@@ -429,7 +429,8 @@ static int qeth_l3_send_setdelip(struct qeth_card *card,
QETH_CARD_TEXT(card, 4, "setdelip");
iob = qeth_get_ipacmd_buffer(card, ipacmd, addr->proto);
iob = qeth_ipa_alloc_cmd(card, ipacmd, addr->proto,
IPA_DATA_SIZEOF(setdelip6));
if (!iob)
return -ENOMEM;
cmd = __ipa_cmd(iob);
......@@ -461,7 +462,8 @@ static int qeth_l3_send_setrouting(struct qeth_card *card,
struct qeth_cmd_buffer *iob;
QETH_CARD_TEXT(card, 4, "setroutg");
iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETRTG, prot);
iob = qeth_ipa_alloc_cmd(card, IPA_CMD_SETRTG, prot,
IPA_DATA_SIZEOF(setrtg));
if (!iob)
return -ENOMEM;
cmd = __ipa_cmd(iob);
......@@ -767,7 +769,7 @@ static int qeth_l3_start_ipa_arp_processing(struct qeth_card *card)
return 0;
}
rc = qeth_send_simple_setassparms(card, IPA_ARP_PROCESSING,
IPA_CMD_ASS_START, 0);
IPA_CMD_ASS_START, NULL);
if (rc) {
dev_warn(&card->gdev->dev,
"Starting ARP processing support for %s failed\n",
......@@ -790,7 +792,7 @@ static int qeth_l3_start_ipa_source_mac(struct qeth_card *card)
}
rc = qeth_send_simple_setassparms(card, IPA_SOURCE_MAC,
IPA_CMD_ASS_START, 0);
IPA_CMD_ASS_START, NULL);
if (rc)
dev_warn(&card->gdev->dev,
"Starting source MAC-address support for %s failed\n",
......@@ -811,7 +813,7 @@ static int qeth_l3_start_ipa_vlan(struct qeth_card *card)
}
rc = qeth_send_simple_setassparms(card, IPA_VLAN_PRIO,
IPA_CMD_ASS_START, 0);
IPA_CMD_ASS_START, NULL);
if (rc) {
dev_warn(&card->gdev->dev,
"Starting VLAN support for %s failed\n",
......@@ -836,7 +838,7 @@ static int qeth_l3_start_ipa_multicast(struct qeth_card *card)
}
rc = qeth_send_simple_setassparms(card, IPA_MULTICASTING,
IPA_CMD_ASS_START, 0);
IPA_CMD_ASS_START, NULL);
if (rc) {
dev_warn(&card->gdev->dev,
"Starting multicast support for %s failed\n",
......@@ -850,6 +852,7 @@ static int qeth_l3_start_ipa_multicast(struct qeth_card *card)
static int qeth_l3_softsetup_ipv6(struct qeth_card *card)
{
u32 ipv6_data = 3;
int rc;
QETH_CARD_TEXT(card, 3, "softipv6");
......@@ -857,16 +860,16 @@ static int qeth_l3_softsetup_ipv6(struct qeth_card *card)
if (IS_IQD(card))
goto out;
rc = qeth_send_simple_setassparms(card, IPA_IPV6,
IPA_CMD_ASS_START, 3);
rc = qeth_send_simple_setassparms(card, IPA_IPV6, IPA_CMD_ASS_START,
&ipv6_data);
if (rc) {
dev_err(&card->gdev->dev,
"Activating IPv6 support for %s failed\n",
QETH_CARD_IFNAME(card));
return rc;
}
rc = qeth_send_simple_setassparms_v6(card, IPA_IPV6,
IPA_CMD_ASS_START, 0);
rc = qeth_send_simple_setassparms_v6(card, IPA_IPV6, IPA_CMD_ASS_START,
NULL);
if (rc) {
dev_err(&card->gdev->dev,
"Activating IPv6 support for %s failed\n",
......@@ -874,7 +877,7 @@ static int qeth_l3_softsetup_ipv6(struct qeth_card *card)
return rc;
}
rc = qeth_send_simple_setassparms_v6(card, IPA_PASSTHRU,
IPA_CMD_ASS_START, 0);
IPA_CMD_ASS_START, NULL);
if (rc) {
dev_warn(&card->gdev->dev,
"Enabling the passthrough mode for %s failed\n",
......@@ -900,6 +903,7 @@ static int qeth_l3_start_ipa_ipv6(struct qeth_card *card)
static int qeth_l3_start_ipa_broadcast(struct qeth_card *card)
{
u32 filter_data = 1;
int rc;
QETH_CARD_TEXT(card, 3, "stbrdcst");
......@@ -912,7 +916,7 @@ static int qeth_l3_start_ipa_broadcast(struct qeth_card *card)
goto out;
}
rc = qeth_send_simple_setassparms(card, IPA_FILTERING,
IPA_CMD_ASS_START, 0);
IPA_CMD_ASS_START, NULL);
if (rc) {
dev_warn(&card->gdev->dev, "Enabling broadcast filtering for "
"%s failed\n", QETH_CARD_IFNAME(card));
......@@ -920,7 +924,7 @@ static int qeth_l3_start_ipa_broadcast(struct qeth_card *card)
}
rc = qeth_send_simple_setassparms(card, IPA_FILTERING,
IPA_CMD_ASS_CONFIGURE, 1);
IPA_CMD_ASS_CONFIGURE, &filter_data);
if (rc) {
dev_warn(&card->gdev->dev,
"Setting up broadcast filtering for %s failed\n",
......@@ -930,7 +934,7 @@ static int qeth_l3_start_ipa_broadcast(struct qeth_card *card)
card->info.broadcast_capable = QETH_BROADCAST_WITH_ECHO;
dev_info(&card->gdev->dev, "Broadcast enabled\n");
rc = qeth_send_simple_setassparms(card, IPA_FILTERING,
IPA_CMD_ASS_ENABLE, 1);
IPA_CMD_ASS_ENABLE, &filter_data);
if (rc) {
dev_warn(&card->gdev->dev, "Setting up broadcast echo "
"filtering for %s failed\n", QETH_CARD_IFNAME(card));
......@@ -981,8 +985,8 @@ static int qeth_l3_iqd_read_initial_mac(struct qeth_card *card)
QETH_CARD_TEXT(card, 2, "hsrmac");
iob = qeth_get_ipacmd_buffer(card, IPA_CMD_CREATE_ADDR,
QETH_PROT_IPV6);
iob = qeth_ipa_alloc_cmd(card, IPA_CMD_CREATE_ADDR, QETH_PROT_IPV6,
IPA_DATA_SIZEOF(create_destroy_addr));
if (!iob)
return -ENOMEM;
cmd = __ipa_cmd(iob);
......@@ -1025,8 +1029,8 @@ static int qeth_l3_get_unique_id(struct qeth_card *card)
return 0;
}
iob = qeth_get_ipacmd_buffer(card, IPA_CMD_CREATE_ADDR,
QETH_PROT_IPV6);
iob = qeth_ipa_alloc_cmd(card, IPA_CMD_CREATE_ADDR, QETH_PROT_IPV6,
IPA_DATA_SIZEOF(create_destroy_addr));
if (!iob)
return -ENOMEM;
cmd = __ipa_cmd(iob);
......@@ -1102,12 +1106,10 @@ qeth_diags_trace(struct qeth_card *card, enum qeth_diags_trace_cmds diags_cmd)
QETH_CARD_TEXT(card, 2, "diagtrac");
iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SET_DIAG_ASS, 0);
iob = qeth_get_diag_cmd(card, QETH_DIAGS_CMD_TRACE, 0);
if (!iob)
return -ENOMEM;
cmd = __ipa_cmd(iob);
cmd->data.diagass.subcmd_len = 16;
cmd->data.diagass.subcmd = QETH_DIAGS_CMD_TRACE;
cmd->data.diagass.type = QETH_DIAGS_TYPE_HIPERSOCKET;
cmd->data.diagass.action = diags_cmd;
return qeth_send_ipa_cmd(card, iob, qeth_diags_trace_cb, NULL);
......@@ -1309,6 +1311,15 @@ static int qeth_l3_vlan_rx_kill_vid(struct net_device *dev,
static void qeth_l3_rebuild_skb(struct qeth_card *card, struct sk_buff *skb,
struct qeth_hdr *hdr)
{
struct af_iucv_trans_hdr *iucv = (struct af_iucv_trans_hdr *) skb->data;
struct net_device *dev = skb->dev;
if (IS_IQD(card) && iucv->magic == ETH_P_AF_IUCV) {
dev_hard_header(skb, dev, ETH_P_AF_IUCV, dev->dev_addr,
"FAKELL", skb->len);
return;
}
if (!(hdr->hdr.l3.flags & QETH_HDR_PASSTHRU)) {
u16 prot = (hdr->hdr.l3.flags & QETH_HDR_IPV6) ? ETH_P_IPV6 :
ETH_P_IP;
......@@ -1342,8 +1353,6 @@ static void qeth_l3_rebuild_skb(struct qeth_card *card, struct sk_buff *skb,
tg_addr, "FAKELL", skb->len);
}
skb->protocol = eth_type_trans(skb, card->dev);
/* copy VLAN tag from hdr into skb */
if (!card->options.sniffer &&
(hdr->hdr.l3.ext_flags & (QETH_HDR_EXT_VLAN_FRAME |
......@@ -1360,12 +1369,10 @@ static void qeth_l3_rebuild_skb(struct qeth_card *card, struct sk_buff *skb,
static int qeth_l3_process_inbound_buffer(struct qeth_card *card,
int budget, int *done)
{
struct net_device *dev = card->dev;
int work_done = 0;
struct sk_buff *skb;
struct qeth_hdr *hdr;
unsigned int len;
__u16 magic;
*done = 0;
WARN_ON_ONCE(!budget);
......@@ -1379,23 +1386,12 @@ static int qeth_l3_process_inbound_buffer(struct qeth_card *card,
}
switch (hdr->hdr.l3.id) {
case QETH_HEADER_TYPE_LAYER3:
magic = *(__u16 *)skb->data;
if (IS_IQD(card) && magic == ETH_P_AF_IUCV) {
len = skb->len;
dev_hard_header(skb, dev, ETH_P_AF_IUCV,
dev->dev_addr, "FAKELL", len);
skb->protocol = eth_type_trans(skb, dev);
netif_receive_skb(skb);
} else {
qeth_l3_rebuild_skb(card, skb, hdr);
len = skb->len;
napi_gro_receive(&card->napi, skb);
}
break;
qeth_l3_rebuild_skb(card, skb, hdr);
/* fall through */
case QETH_HEADER_TYPE_LAYER2: /* for HiperSockets sniffer */
skb->protocol = eth_type_trans(skb, skb->dev);
len = skb->len;
netif_receive_skb(skb);
napi_gro_receive(&card->napi, skb);
break;
default:
dev_kfree_skb_any(skb);
......@@ -1436,7 +1432,6 @@ static void qeth_l3_stop_card(struct qeth_card *card)
card->state = CARD_STATE_DOWN;
}
qeth_clear_cmd_buffers(&card->write);
flush_workqueue(card->event_wq);
}
......@@ -1559,7 +1554,8 @@ static int qeth_l3_arp_set_no_entries(struct qeth_card *card, int no_entries)
}
iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
IPA_CMD_ASS_ARP_SET_NO_ENTRIES, 4,
IPA_CMD_ASS_ARP_SET_NO_ENTRIES,
SETASS_DATA_SIZEOF(flags_32bit),
QETH_PROT_IPV4);
if (!iob)
return -ENOMEM;
......@@ -1705,9 +1701,7 @@ static int qeth_l3_query_arp_cache_info(struct qeth_card *card,
iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
IPA_CMD_ASS_ARP_QUERY_INFO,
sizeof(struct qeth_arp_query_data)
- sizeof(char),
prot);
SETASS_DATA_SIZEOF(query_arp), prot);
if (!iob)
return -ENOMEM;
cmd = __ipa_cmd(iob);
......@@ -1791,7 +1785,8 @@ static int qeth_l3_arp_modify_entry(struct qeth_card *card,
}
iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING, arp_cmd,
sizeof(*cmd_entry), QETH_PROT_IPV4);
SETASS_DATA_SIZEOF(arp_entry),
QETH_PROT_IPV4);
if (!iob)
return -ENOMEM;
......@@ -1882,26 +1877,17 @@ static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
return rc;
}
static int qeth_l3_get_cast_type(struct sk_buff *skb)
static int qeth_l3_get_cast_type_rcu(struct sk_buff *skb, struct dst_entry *dst,
int ipv)
{
int ipv = qeth_get_ip_version(skb);
struct neighbour *n = NULL;
struct dst_entry *dst;
rcu_read_lock();
dst = skb_dst(skb);
if (dst) {
struct rt6_info *rt = (struct rt6_info *) dst;
dst = dst_check(dst, (ipv == 6) ? rt6_get_cookie(rt) : 0);
if (dst)
n = dst_neigh_lookup_skb(dst, skb);
}
if (dst)
n = dst_neigh_lookup_skb(dst, skb);
if (n) {
int cast_type = n->type;
rcu_read_unlock();
neigh_release(n);
if ((cast_type == RTN_BROADCAST) ||
(cast_type == RTN_MULTICAST) ||
......@@ -1909,7 +1895,6 @@ static int qeth_l3_get_cast_type(struct sk_buff *skb)
return cast_type;
return RTN_UNICAST;
}
rcu_read_unlock();
/* no neighbour (eg AF_PACKET), fall back to target's IP address ... */
switch (ipv) {
......@@ -1927,6 +1912,20 @@ static int qeth_l3_get_cast_type(struct sk_buff *skb)
}
}
static int qeth_l3_get_cast_type(struct sk_buff *skb)
{
int ipv = qeth_get_ip_version(skb);
struct dst_entry *dst;
int cast_type;
rcu_read_lock();
dst = qeth_dst_check_rcu(skb, ipv);
cast_type = qeth_l3_get_cast_type_rcu(skb, dst, ipv);
rcu_read_unlock();
return cast_type;
}
static u8 qeth_l3_cast_type_to_flag(int cast_type)
{
if (cast_type == RTN_MULTICAST)
......@@ -1940,12 +1939,13 @@ static u8 qeth_l3_cast_type_to_flag(int cast_type)
static void qeth_l3_fill_header(struct qeth_qdio_out_q *queue,
struct qeth_hdr *hdr, struct sk_buff *skb,
int ipv, int cast_type, unsigned int data_len)
int ipv, unsigned int data_len)
{
struct qeth_hdr_layer3 *l3_hdr = &hdr->hdr.l3;
struct vlan_ethhdr *veth = vlan_eth_hdr(skb);
struct qeth_card *card = queue->card;
struct dst_entry *dst;
int cast_type;
hdr->hdr.l3.length = data_len;
......@@ -1982,36 +1982,23 @@ static void qeth_l3_fill_header(struct qeth_qdio_out_q *queue,
hdr->hdr.l3.vlan_id = ntohs(veth->h_vlan_TCI);
}
l3_hdr->flags = qeth_l3_cast_type_to_flag(cast_type);
/* OSA only: */
if (!ipv) {
l3_hdr->flags |= QETH_HDR_PASSTHRU;
return;
}
rcu_read_lock();
dst = skb_dst(skb);
dst = qeth_dst_check_rcu(skb, ipv);
if (ipv == 4) {
struct rtable *rt;
if (IS_IQD(card) && skb_get_queue_mapping(skb) != QETH_IQD_MCAST_TXQ)
cast_type = RTN_UNICAST;
else
cast_type = qeth_l3_get_cast_type_rcu(skb, dst, ipv);
l3_hdr->flags |= qeth_l3_cast_type_to_flag(cast_type);
if (dst)
dst = dst_check(dst, 0);
rt = (struct rtable *) dst;
if (ipv == 4) {
struct rtable *rt = (struct rtable *) dst;
*((__be32 *) &hdr->hdr.l3.next_hop.ipv4.addr) = (rt) ?
rt_nexthop(rt, ip_hdr(skb)->daddr) :
ip_hdr(skb)->daddr;
} else {
/* IPv6 */
struct rt6_info *rt;
if (dst) {
rt = (struct rt6_info *) dst;
dst = dst_check(dst, rt6_get_cookie(rt));
}
rt = (struct rt6_info *) dst;
} else if (ipv == 6) {
struct rt6_info *rt = (struct rt6_info *) dst;
if (rt && !ipv6_addr_any(&rt->rt6i_gateway))
l3_hdr->next_hop.ipv6_addr = rt->rt6i_gateway;
......@@ -2021,6 +2008,9 @@ static void qeth_l3_fill_header(struct qeth_qdio_out_q *queue,
hdr->hdr.l3.flags |= QETH_HDR_IPV6;
if (!IS_IQD(card))
hdr->hdr.l3.flags |= QETH_HDR_PASSTHRU;
} else {
/* OSA only: */
l3_hdr->flags |= QETH_HDR_PASSTHRU;
}
rcu_read_unlock();
}
......@@ -2040,7 +2030,7 @@ static void qeth_l3_fixup_headers(struct sk_buff *skb)
}
static int qeth_l3_xmit(struct qeth_card *card, struct sk_buff *skb,
struct qeth_qdio_out_q *queue, int ipv, int cast_type)
struct qeth_qdio_out_q *queue, int ipv)
{
unsigned int hw_hdr_len;
int rc;
......@@ -2054,7 +2044,7 @@ static int qeth_l3_xmit(struct qeth_card *card, struct sk_buff *skb,
skb_pull(skb, ETH_HLEN);
qeth_l3_fixup_headers(skb);
return qeth_xmit(card, skb, queue, ipv, cast_type, qeth_l3_fill_header);
return qeth_xmit(card, skb, queue, ipv, qeth_l3_fill_header);
}
static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb,
......@@ -2065,7 +2055,7 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb,
int ipv = qeth_get_ip_version(skb);
struct qeth_qdio_out_q *queue;
int tx_bytes = skb->len;
int cast_type, rc;
int rc;
if (IS_IQD(card)) {
queue = card->qdio.out_qs[qeth_iqd_translate_txq(dev, txq)];
......@@ -2076,24 +2066,18 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb,
(card->options.cq == QETH_CQ_ENABLED &&
skb->protocol != htons(ETH_P_AF_IUCV)))
goto tx_drop;
if (txq == QETH_IQD_MCAST_TXQ)
cast_type = qeth_l3_get_cast_type(skb);
else
cast_type = RTN_UNICAST;
} else {
queue = card->qdio.out_qs[txq];
cast_type = qeth_l3_get_cast_type(skb);
}
if (cast_type == RTN_BROADCAST && !card->info.broadcast_capable)
if (!(dev->flags & IFF_BROADCAST) &&
qeth_l3_get_cast_type(skb) == RTN_BROADCAST)
goto tx_drop;
if (ipv == 4 || IS_IQD(card))
rc = qeth_l3_xmit(card, skb, queue, ipv, cast_type);
rc = qeth_l3_xmit(card, skb, queue, ipv);
else
rc = qeth_xmit(card, skb, queue, ipv, cast_type,
qeth_l3_fill_header);
rc = qeth_xmit(card, skb, queue, ipv, qeth_l3_fill_header);
if (!rc) {
QETH_TXQ_STAT_INC(queue, tx_packets);
......@@ -2498,33 +2482,6 @@ static int qeth_l3_recover(void *ptr)
return 0;
}
static int qeth_l3_pm_suspend(struct ccwgroup_device *gdev)
{
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
qeth_set_allowed_threads(card, 0, 1);
wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
if (gdev->state == CCWGROUP_OFFLINE)
return 0;
qeth_l3_set_offline(gdev);
return 0;
}
static int qeth_l3_pm_resume(struct ccwgroup_device *gdev)
{
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
int rc;
rc = qeth_l3_set_online(gdev);
qeth_set_allowed_threads(card, 0xffffffff, 0);
if (rc)
dev_warn(&card->gdev->dev, "The qeth device driver "
"failed to recover an error on the device\n");
return rc;
}
/* Returns zero if the command is successfully "consumed" */
static int qeth_l3_control_event(struct qeth_card *card,
struct qeth_ipa_cmd *cmd)
......@@ -2540,9 +2497,6 @@ struct qeth_discipline qeth_l3_discipline = {
.remove = qeth_l3_remove_device,
.set_online = qeth_l3_set_online,
.set_offline = qeth_l3_set_offline,
.freeze = qeth_l3_pm_suspend,
.thaw = qeth_l3_pm_resume,
.restore = qeth_l3_pm_resume,
.do_ioctl = qeth_l3_do_ioctl,
.control_event_handler = qeth_l3_control_event,
};
......
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