Merge branch 's390-qeth-next'
Julian Wiedmann says: ==================== s390/qeth: updates 2019-02-12 please apply one more round of qeth patches to net-next. This series targets the driver's control paths. It primarily brings improvements to the error handling for sent cmds and received responses, along with the usual cleanup and consolidation efforts. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Коммит
8a1343c5f8
|
@ -595,8 +595,8 @@ struct qeth_channel;
|
|||
struct qeth_cmd_buffer {
|
||||
enum qeth_cmd_buffer_state state;
|
||||
struct qeth_channel *channel;
|
||||
struct qeth_reply *reply;
|
||||
unsigned char *data;
|
||||
int rc;
|
||||
void (*callback)(struct qeth_card *card, struct qeth_channel *channel,
|
||||
struct qeth_cmd_buffer *iob);
|
||||
};
|
||||
|
@ -1000,13 +1000,11 @@ void qeth_tx_timeout(struct net_device *);
|
|||
void qeth_prepare_control_data(struct qeth_card *, int,
|
||||
struct qeth_cmd_buffer *);
|
||||
void qeth_release_buffer(struct qeth_channel *, struct qeth_cmd_buffer *);
|
||||
void qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob);
|
||||
void qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
|
||||
u16 cmd_length);
|
||||
struct qeth_cmd_buffer *qeth_wait_for_buffer(struct qeth_channel *);
|
||||
int qeth_query_switch_attributes(struct qeth_card *card,
|
||||
struct qeth_switch_info *sw_info);
|
||||
int qeth_send_control_data(struct qeth_card *, int, struct qeth_cmd_buffer *,
|
||||
int (*reply_cb)(struct qeth_card *, struct qeth_reply*, unsigned long),
|
||||
void *reply_param);
|
||||
unsigned int qeth_count_elements(struct sk_buff *skb, unsigned int data_offset);
|
||||
int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
|
||||
struct sk_buff *skb, struct qeth_hdr *hdr,
|
||||
|
|
|
@ -566,6 +566,7 @@ static struct qeth_reply *qeth_alloc_reply(struct qeth_card *card)
|
|||
if (reply) {
|
||||
refcount_set(&reply->refcnt, 1);
|
||||
atomic_set(&reply->received, 0);
|
||||
init_waitqueue_head(&reply->wait_q);
|
||||
}
|
||||
return reply;
|
||||
}
|
||||
|
@ -581,6 +582,26 @@ static void qeth_put_reply(struct qeth_reply *reply)
|
|||
kfree(reply);
|
||||
}
|
||||
|
||||
static void qeth_enqueue_reply(struct qeth_card *card, struct qeth_reply *reply)
|
||||
{
|
||||
spin_lock_irq(&card->lock);
|
||||
list_add_tail(&reply->list, &card->cmd_waiter_list);
|
||||
spin_unlock_irq(&card->lock);
|
||||
}
|
||||
|
||||
static void qeth_dequeue_reply(struct qeth_card *card, struct qeth_reply *reply)
|
||||
{
|
||||
spin_lock_irq(&card->lock);
|
||||
list_del(&reply->list);
|
||||
spin_unlock_irq(&card->lock);
|
||||
}
|
||||
|
||||
static void qeth_notify_reply(struct qeth_reply *reply)
|
||||
{
|
||||
atomic_inc(&reply->received);
|
||||
wake_up(&reply->wait_q);
|
||||
}
|
||||
|
||||
static void qeth_issue_ipa_msg(struct qeth_ipa_cmd *cmd, int rc,
|
||||
struct qeth_card *card)
|
||||
{
|
||||
|
@ -657,19 +678,15 @@ static struct qeth_ipa_cmd *qeth_check_ipa_data(struct qeth_card *card,
|
|||
|
||||
void qeth_clear_ipacmd_list(struct qeth_card *card)
|
||||
{
|
||||
struct qeth_reply *reply, *r;
|
||||
struct qeth_reply *reply;
|
||||
unsigned long flags;
|
||||
|
||||
QETH_CARD_TEXT(card, 4, "clipalst");
|
||||
|
||||
spin_lock_irqsave(&card->lock, flags);
|
||||
list_for_each_entry_safe(reply, r, &card->cmd_waiter_list, list) {
|
||||
qeth_get_reply(reply);
|
||||
list_for_each_entry(reply, &card->cmd_waiter_list, list) {
|
||||
reply->rc = -EIO;
|
||||
atomic_inc(&reply->received);
|
||||
list_del_init(&reply->list);
|
||||
wake_up(&reply->wait_q);
|
||||
qeth_put_reply(reply);
|
||||
qeth_notify_reply(reply);
|
||||
}
|
||||
spin_unlock_irqrestore(&card->lock, flags);
|
||||
}
|
||||
|
@ -726,7 +743,10 @@ void qeth_release_buffer(struct qeth_channel *channel,
|
|||
spin_lock_irqsave(&channel->iob_lock, flags);
|
||||
iob->state = BUF_STATE_FREE;
|
||||
iob->callback = qeth_send_control_data_cb;
|
||||
iob->rc = 0;
|
||||
if (iob->reply) {
|
||||
qeth_put_reply(iob->reply);
|
||||
iob->reply = NULL;
|
||||
}
|
||||
spin_unlock_irqrestore(&channel->iob_lock, flags);
|
||||
wake_up(&channel->wait_q);
|
||||
}
|
||||
|
@ -739,6 +759,17 @@ static void qeth_release_buffer_cb(struct qeth_card *card,
|
|||
qeth_release_buffer(channel, iob);
|
||||
}
|
||||
|
||||
static void qeth_cancel_cmd(struct qeth_cmd_buffer *iob, int rc)
|
||||
{
|
||||
struct qeth_reply *reply = iob->reply;
|
||||
|
||||
if (reply) {
|
||||
reply->rc = rc;
|
||||
qeth_notify_reply(reply);
|
||||
}
|
||||
qeth_release_buffer(iob->channel, iob);
|
||||
}
|
||||
|
||||
static struct qeth_cmd_buffer *qeth_get_buffer(struct qeth_channel *channel)
|
||||
{
|
||||
struct qeth_cmd_buffer *buffer = NULL;
|
||||
|
@ -774,9 +805,9 @@ static void qeth_send_control_data_cb(struct qeth_card *card,
|
|||
struct qeth_cmd_buffer *iob)
|
||||
{
|
||||
struct qeth_ipa_cmd *cmd = NULL;
|
||||
struct qeth_reply *reply, *r;
|
||||
struct qeth_reply *reply = NULL;
|
||||
struct qeth_reply *r;
|
||||
unsigned long flags;
|
||||
int keep_reply;
|
||||
int rc = 0;
|
||||
|
||||
QETH_CARD_TEXT(card, 4, "sndctlcb");
|
||||
|
@ -808,44 +839,40 @@ static void qeth_send_control_data_cb(struct qeth_card *card,
|
|||
goto out;
|
||||
}
|
||||
|
||||
/* match against pending cmd requests */
|
||||
spin_lock_irqsave(&card->lock, flags);
|
||||
list_for_each_entry_safe(reply, r, &card->cmd_waiter_list, list) {
|
||||
if ((reply->seqno == QETH_IDX_COMMAND_SEQNO) ||
|
||||
((cmd) && (reply->seqno == cmd->hdr.seqno))) {
|
||||
list_for_each_entry(r, &card->cmd_waiter_list, list) {
|
||||
if ((r->seqno == QETH_IDX_COMMAND_SEQNO) ||
|
||||
(cmd && (r->seqno == cmd->hdr.seqno))) {
|
||||
reply = r;
|
||||
/* take the object outside the lock */
|
||||
qeth_get_reply(reply);
|
||||
list_del_init(&reply->list);
|
||||
spin_unlock_irqrestore(&card->lock, flags);
|
||||
keep_reply = 0;
|
||||
if (reply->callback != NULL) {
|
||||
if (cmd) {
|
||||
reply->offset = (__u16)((char *)cmd -
|
||||
(char *)iob->data);
|
||||
keep_reply = reply->callback(card,
|
||||
reply,
|
||||
(unsigned long)cmd);
|
||||
} else
|
||||
keep_reply = reply->callback(card,
|
||||
reply,
|
||||
(unsigned long)iob);
|
||||
}
|
||||
if (cmd)
|
||||
reply->rc = (u16) cmd->hdr.return_code;
|
||||
else if (iob->rc)
|
||||
reply->rc = iob->rc;
|
||||
if (keep_reply) {
|
||||
spin_lock_irqsave(&card->lock, flags);
|
||||
list_add_tail(&reply->list,
|
||||
&card->cmd_waiter_list);
|
||||
spin_unlock_irqrestore(&card->lock, flags);
|
||||
} else {
|
||||
atomic_inc(&reply->received);
|
||||
wake_up(&reply->wait_q);
|
||||
}
|
||||
qeth_put_reply(reply);
|
||||
goto out;
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&card->lock, flags);
|
||||
|
||||
if (!reply)
|
||||
goto out;
|
||||
|
||||
if (!reply->callback) {
|
||||
rc = 0;
|
||||
} else {
|
||||
if (cmd) {
|
||||
reply->offset = (u16)((char *)cmd - (char *)iob->data);
|
||||
rc = reply->callback(card, reply, (unsigned long)cmd);
|
||||
} else {
|
||||
rc = reply->callback(card, reply, (unsigned long)iob);
|
||||
}
|
||||
}
|
||||
|
||||
if (rc <= 0) {
|
||||
reply->rc = rc;
|
||||
qeth_notify_reply(reply);
|
||||
}
|
||||
|
||||
qeth_put_reply(reply);
|
||||
|
||||
out:
|
||||
memcpy(&card->seqno.pdu_hdr_ack,
|
||||
QETH_PDU_HEADER_SEQ_NO(iob->data),
|
||||
|
@ -976,9 +1003,8 @@ static int qeth_get_problem(struct qeth_card *card, struct ccw_device *cdev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static long qeth_check_irb_error(struct qeth_card *card,
|
||||
struct ccw_device *cdev, unsigned long intparm,
|
||||
struct irb *irb)
|
||||
static int qeth_check_irb_error(struct qeth_card *card, struct ccw_device *cdev,
|
||||
unsigned long intparm, struct irb *irb)
|
||||
{
|
||||
if (!IS_ERR(irb))
|
||||
return 0;
|
||||
|
@ -989,7 +1015,7 @@ static long qeth_check_irb_error(struct qeth_card *card,
|
|||
CCW_DEVID(cdev));
|
||||
QETH_CARD_TEXT(card, 2, "ckirberr");
|
||||
QETH_CARD_TEXT_(card, 2, " rc%d", -EIO);
|
||||
break;
|
||||
return -EIO;
|
||||
case -ETIMEDOUT:
|
||||
dev_warn(&cdev->dev, "A hardware operation timed out"
|
||||
" on the device\n");
|
||||
|
@ -1001,14 +1027,14 @@ static long qeth_check_irb_error(struct qeth_card *card,
|
|||
wake_up(&card->wait_q);
|
||||
}
|
||||
}
|
||||
break;
|
||||
return -ETIMEDOUT;
|
||||
default:
|
||||
QETH_DBF_MESSAGE(2, "unknown error %ld on channel %x\n",
|
||||
PTR_ERR(irb), CCW_DEVID(cdev));
|
||||
QETH_CARD_TEXT(card, 2, "ckirberr");
|
||||
QETH_CARD_TEXT(card, 2, " rc???");
|
||||
return PTR_ERR(irb);
|
||||
}
|
||||
return PTR_ERR(irb);
|
||||
}
|
||||
|
||||
static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
|
||||
|
@ -1043,10 +1069,11 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
|
|||
if (qeth_intparm_is_iob(intparm))
|
||||
iob = (struct qeth_cmd_buffer *) __va((addr_t)intparm);
|
||||
|
||||
if (qeth_check_irb_error(card, cdev, intparm, irb)) {
|
||||
rc = qeth_check_irb_error(card, cdev, intparm, irb);
|
||||
if (rc) {
|
||||
/* IO was terminated, free its resources. */
|
||||
if (iob)
|
||||
qeth_release_buffer(iob->channel, iob);
|
||||
qeth_cancel_cmd(iob, rc);
|
||||
atomic_set(&channel->irq_pending, 0);
|
||||
wake_up(&card->wait_q);
|
||||
return;
|
||||
|
@ -1102,7 +1129,7 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
|
|||
if (rc) {
|
||||
card->read_or_write_problem = 1;
|
||||
if (iob)
|
||||
qeth_release_buffer(iob->channel, iob);
|
||||
qeth_cancel_cmd(iob, rc);
|
||||
qeth_clear_ipacmd_list(card);
|
||||
qeth_schedule_recovery(card);
|
||||
goto out;
|
||||
|
@ -1264,7 +1291,6 @@ static int qeth_setup_channel(struct qeth_channel *channel, bool alloc_buffers)
|
|||
channel->iob[cnt].state = BUF_STATE_FREE;
|
||||
channel->iob[cnt].channel = channel;
|
||||
channel->iob[cnt].callback = qeth_send_control_data_cb;
|
||||
channel->iob[cnt].rc = 0;
|
||||
}
|
||||
if (cnt < QETH_CMD_BUFFER_NO) {
|
||||
qeth_clean_channel(channel);
|
||||
|
@ -1991,7 +2017,7 @@ void qeth_prepare_control_data(struct qeth_card *card, int len,
|
|||
card->seqno.pdu_hdr++;
|
||||
memcpy(QETH_PDU_HEADER_ACK_SEQ_NO(iob->data),
|
||||
&card->seqno.pdu_hdr_ack, QETH_SEQ_NO_LENGTH);
|
||||
QETH_DBF_HEX(CTRL, 2, iob->data, QETH_DBF_CTRL_LEN);
|
||||
QETH_DBF_HEX(CTRL, 2, iob->data, min(len, QETH_DBF_CTRL_LEN));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qeth_prepare_control_data);
|
||||
|
||||
|
@ -2008,24 +2034,22 @@ EXPORT_SYMBOL_GPL(qeth_prepare_control_data);
|
|||
* for the IPA commands.
|
||||
* @reply_param: private pointer passed to the callback
|
||||
*
|
||||
* Returns the value of the `return_code' field of the response
|
||||
* block returned from the hardware, or other error indication.
|
||||
* Value of zero indicates successful execution of the command.
|
||||
*
|
||||
* Callback function gets called one or more times, with cb_cmd
|
||||
* pointing to the response returned by the hardware. Callback
|
||||
* function must return non-zero if more reply blocks are expected,
|
||||
* and zero if the last or only reply block is received. Callback
|
||||
* function can get the value of the reply_param pointer from the
|
||||
* function must return
|
||||
* > 0 if more reply blocks are expected,
|
||||
* 0 if the last or only reply block is received, and
|
||||
* < 0 on error.
|
||||
* Callback function can get the value of the reply_param pointer from the
|
||||
* field 'param' of the structure qeth_reply.
|
||||
*/
|
||||
|
||||
int qeth_send_control_data(struct qeth_card *card, int len,
|
||||
struct qeth_cmd_buffer *iob,
|
||||
int (*reply_cb)(struct qeth_card *cb_card,
|
||||
struct qeth_reply *cb_reply,
|
||||
unsigned long cb_cmd),
|
||||
void *reply_param)
|
||||
static int qeth_send_control_data(struct qeth_card *card, int len,
|
||||
struct qeth_cmd_buffer *iob,
|
||||
int (*reply_cb)(struct qeth_card *cb_card,
|
||||
struct qeth_reply *cb_reply,
|
||||
unsigned long cb_cmd),
|
||||
void *reply_param)
|
||||
{
|
||||
struct qeth_channel *channel = iob->channel;
|
||||
int rc;
|
||||
|
@ -2047,7 +2071,9 @@ int qeth_send_control_data(struct qeth_card *card, int len,
|
|||
reply->callback = reply_cb;
|
||||
reply->param = reply_param;
|
||||
|
||||
init_waitqueue_head(&reply->wait_q);
|
||||
/* pairs with qeth_release_buffer(): */
|
||||
qeth_get_reply(reply);
|
||||
iob->reply = reply;
|
||||
|
||||
while (atomic_cmpxchg(&channel->irq_pending, 0, 1)) ;
|
||||
|
||||
|
@ -2062,9 +2088,7 @@ int qeth_send_control_data(struct qeth_card *card, int len,
|
|||
}
|
||||
qeth_prepare_control_data(card, len, iob);
|
||||
|
||||
spin_lock_irq(&card->lock);
|
||||
list_add_tail(&reply->list, &card->cmd_waiter_list);
|
||||
spin_unlock_irq(&card->lock);
|
||||
qeth_enqueue_reply(card, reply);
|
||||
|
||||
timeout = jiffies + event_timeout;
|
||||
|
||||
|
@ -2077,10 +2101,8 @@ int qeth_send_control_data(struct qeth_card *card, int len,
|
|||
QETH_DBF_MESSAGE(2, "qeth_send_control_data on device %x: ccw_device_start rc = %i\n",
|
||||
CARD_DEVID(card), rc);
|
||||
QETH_CARD_TEXT_(card, 2, " err%d", rc);
|
||||
spin_lock_irq(&card->lock);
|
||||
list_del_init(&reply->list);
|
||||
qeth_dequeue_reply(card, reply);
|
||||
qeth_put_reply(reply);
|
||||
spin_unlock_irq(&card->lock);
|
||||
qeth_release_buffer(channel, iob);
|
||||
atomic_set(&channel->irq_pending, 0);
|
||||
wake_up(&card->wait_q);
|
||||
|
@ -2102,21 +2124,16 @@ int qeth_send_control_data(struct qeth_card *card, int len,
|
|||
}
|
||||
}
|
||||
|
||||
qeth_dequeue_reply(card, reply);
|
||||
rc = reply->rc;
|
||||
qeth_put_reply(reply);
|
||||
return rc;
|
||||
|
||||
time_err:
|
||||
reply->rc = -ETIME;
|
||||
spin_lock_irq(&card->lock);
|
||||
list_del_init(&reply->list);
|
||||
spin_unlock_irq(&card->lock);
|
||||
atomic_inc(&reply->received);
|
||||
rc = reply->rc;
|
||||
qeth_dequeue_reply(card, reply);
|
||||
qeth_put_reply(reply);
|
||||
return rc;
|
||||
return -ETIME;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qeth_send_control_data);
|
||||
|
||||
static int qeth_cm_enable_cb(struct qeth_card *card, struct qeth_reply *reply,
|
||||
unsigned long data)
|
||||
|
@ -2321,9 +2338,8 @@ static int qeth_ulp_setup_cb(struct qeth_card *card, struct qeth_reply *reply,
|
|||
QETH_DBF_TEXT(SETUP, 2, "olmlimit");
|
||||
dev_err(&card->gdev->dev, "A connection could not be "
|
||||
"established because of an OLM limit\n");
|
||||
iob->rc = -EMLINK;
|
||||
return -EMLINK;
|
||||
}
|
||||
QETH_DBF_TEXT_(SETUP, 2, " rc%d", iob->rc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2816,14 +2832,20 @@ static void qeth_fill_ipacmd_header(struct qeth_card *card,
|
|||
cmd->hdr.prot_version = prot;
|
||||
}
|
||||
|
||||
void qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob)
|
||||
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);
|
||||
|
||||
memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
|
||||
memcpy(QETH_IPA_PDU_LEN_TOTAL(iob->data), &total_length, 2);
|
||||
memcpy(QETH_IPA_CMD_PROT_TYPE(iob->data), &prot_type, 1);
|
||||
memcpy(QETH_IPA_PDU_LEN_PDU1(iob->data), &cmd_length, 2);
|
||||
memcpy(QETH_IPA_PDU_LEN_PDU2(iob->data), &cmd_length, 2);
|
||||
memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
|
||||
&card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
|
||||
memcpy(QETH_IPA_PDU_LEN_PDU3(iob->data), &cmd_length, 2);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qeth_prepare_ipa_cmd);
|
||||
|
||||
|
@ -2834,7 +2856,7 @@ struct qeth_cmd_buffer *qeth_get_ipacmd_buffer(struct qeth_card *card,
|
|||
|
||||
iob = qeth_get_buffer(&card->write);
|
||||
if (iob) {
|
||||
qeth_prepare_ipa_cmd(card, 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,
|
||||
|
@ -2847,6 +2869,14 @@ struct qeth_cmd_buffer *qeth_get_ipacmd_buffer(struct qeth_card *card,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(qeth_get_ipacmd_buffer);
|
||||
|
||||
static int qeth_send_ipa_cmd_cb(struct qeth_card *card,
|
||||
struct qeth_reply *reply, unsigned long data)
|
||||
{
|
||||
struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
|
||||
|
||||
return (cmd->hdr.return_code) ? -EIO : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* qeth_send_ipa_cmd() - send an IPA command
|
||||
*
|
||||
|
@ -2858,11 +2888,15 @@ 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");
|
||||
rc = qeth_send_control_data(card, IPA_CMD_LENGTH,
|
||||
iob, reply_cb, reply_param);
|
||||
|
||||
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);
|
||||
if (rc == -ETIME) {
|
||||
qeth_clear_ipacmd_list(card);
|
||||
qeth_schedule_recovery(card);
|
||||
|
@ -2871,9 +2905,19 @@ int qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(qeth_send_ipa_cmd);
|
||||
|
||||
static int qeth_send_startlan_cb(struct qeth_card *card,
|
||||
struct qeth_reply *reply, unsigned long data)
|
||||
{
|
||||
struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
|
||||
|
||||
if (cmd->hdr.return_code == IPA_RC_LAN_OFFLINE)
|
||||
return -ENETDOWN;
|
||||
|
||||
return (cmd->hdr.return_code) ? -EIO : 0;
|
||||
}
|
||||
|
||||
static int qeth_send_startlan(struct qeth_card *card)
|
||||
{
|
||||
int rc;
|
||||
struct qeth_cmd_buffer *iob;
|
||||
|
||||
QETH_DBF_TEXT(SETUP, 2, "strtlan");
|
||||
|
@ -2881,8 +2925,7 @@ static int qeth_send_startlan(struct qeth_card *card)
|
|||
iob = qeth_get_ipacmd_buffer(card, IPA_CMD_STARTLAN, 0);
|
||||
if (!iob)
|
||||
return -ENOMEM;
|
||||
rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
|
||||
return rc;
|
||||
return qeth_send_ipa_cmd(card, iob, qeth_send_startlan_cb, NULL);
|
||||
}
|
||||
|
||||
static int qeth_setadpparms_inspect_rc(struct qeth_ipa_cmd *cmd)
|
||||
|
@ -2900,7 +2943,7 @@ static int qeth_query_setadapterparms_cb(struct qeth_card *card,
|
|||
|
||||
QETH_CARD_TEXT(card, 3, "quyadpcb");
|
||||
if (qeth_setadpparms_inspect_rc(cmd))
|
||||
return 0;
|
||||
return -EIO;
|
||||
|
||||
if (cmd->data.setadapterparms.data.query_cmds_supp.lan_type & 0x7f) {
|
||||
card->info.link_type =
|
||||
|
@ -2955,19 +2998,18 @@ static int qeth_query_ipassists_cb(struct qeth_card *card,
|
|||
cmd = (struct qeth_ipa_cmd *) data;
|
||||
|
||||
switch (cmd->hdr.return_code) {
|
||||
case IPA_RC_SUCCESS:
|
||||
break;
|
||||
case IPA_RC_NOTSUPP:
|
||||
case IPA_RC_L2_UNSUPPORTED_CMD:
|
||||
QETH_DBF_TEXT(SETUP, 2, "ipaunsup");
|
||||
card->options.ipa4.supported_funcs |= IPA_SETADAPTERPARMS;
|
||||
card->options.ipa6.supported_funcs |= IPA_SETADAPTERPARMS;
|
||||
return 0;
|
||||
return -EOPNOTSUPP;
|
||||
default:
|
||||
if (cmd->hdr.return_code) {
|
||||
QETH_DBF_MESSAGE(1, "IPA_CMD_QIPASSIST on device %x: Unhandled rc=%#x\n",
|
||||
CARD_DEVID(card),
|
||||
cmd->hdr.return_code);
|
||||
return 0;
|
||||
}
|
||||
QETH_DBF_MESSAGE(1, "IPA_CMD_QIPASSIST on device %x: Unhandled rc=%#x\n",
|
||||
CARD_DEVID(card), cmd->hdr.return_code);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (cmd->hdr.prot_version == QETH_PROT_IPV4) {
|
||||
|
@ -3005,7 +3047,7 @@ static int qeth_query_switch_attributes_cb(struct qeth_card *card,
|
|||
|
||||
QETH_CARD_TEXT(card, 2, "qswiatcb");
|
||||
if (qeth_setadpparms_inspect_rc(cmd))
|
||||
return 0;
|
||||
return -EIO;
|
||||
|
||||
sw_info = (struct qeth_switch_info *)reply->param;
|
||||
attrs = &cmd->data.setadapterparms.data.query_switch_attributes;
|
||||
|
@ -3037,15 +3079,15 @@ int qeth_query_switch_attributes(struct qeth_card *card,
|
|||
static int qeth_query_setdiagass_cb(struct qeth_card *card,
|
||||
struct qeth_reply *reply, unsigned long data)
|
||||
{
|
||||
struct qeth_ipa_cmd *cmd;
|
||||
__u16 rc;
|
||||
struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
|
||||
u16 rc = cmd->hdr.return_code;
|
||||
|
||||
cmd = (struct qeth_ipa_cmd *)data;
|
||||
rc = cmd->hdr.return_code;
|
||||
if (rc)
|
||||
if (rc) {
|
||||
QETH_CARD_TEXT_(card, 2, "diagq:%x", rc);
|
||||
else
|
||||
card->info.diagass_support = cmd->data.diagass.ext;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
card->info.diagass_support = cmd->data.diagass.ext;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3092,13 +3134,13 @@ static void qeth_get_trap_id(struct qeth_card *card, struct qeth_trap_id *tid)
|
|||
static int qeth_hw_trap_cb(struct qeth_card *card,
|
||||
struct qeth_reply *reply, unsigned long data)
|
||||
{
|
||||
struct qeth_ipa_cmd *cmd;
|
||||
__u16 rc;
|
||||
struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
|
||||
u16 rc = cmd->hdr.return_code;
|
||||
|
||||
cmd = (struct qeth_ipa_cmd *)data;
|
||||
rc = cmd->hdr.return_code;
|
||||
if (rc)
|
||||
if (rc) {
|
||||
QETH_CARD_TEXT_(card, 2, "trapc:%x", rc);
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -4157,7 +4199,7 @@ static int qeth_setadp_promisc_mode_cb(struct qeth_card *card,
|
|||
setparms->data.mode = SET_PROMISC_MODE_OFF;
|
||||
}
|
||||
card->info.promisc_mode = setparms->data.mode;
|
||||
return 0;
|
||||
return (cmd->hdr.return_code) ? -EIO : 0;
|
||||
}
|
||||
|
||||
void qeth_setadp_promisc_mode(struct qeth_card *card)
|
||||
|
@ -4209,12 +4251,15 @@ static int qeth_setadpparms_change_macaddr_cb(struct qeth_card *card,
|
|||
|
||||
QETH_CARD_TEXT(card, 4, "chgmaccb");
|
||||
if (qeth_setadpparms_inspect_rc(cmd))
|
||||
return 0;
|
||||
return -EIO;
|
||||
|
||||
adp_cmd = &cmd->data.setadapterparms;
|
||||
if (!is_valid_ether_addr(adp_cmd->data.change_addr.addr))
|
||||
return -EADDRNOTAVAIL;
|
||||
|
||||
if (IS_LAYER2(card) && IS_OSD(card) && !IS_VM_NIC(card) &&
|
||||
!(adp_cmd->hdr.flags & QETH_SETADP_FLAGS_VIRTUAL_MAC))
|
||||
return 0;
|
||||
return -EADDRNOTAVAIL;
|
||||
|
||||
ether_addr_copy(card->dev->dev_addr, adp_cmd->data.change_addr.addr);
|
||||
return 0;
|
||||
|
@ -4253,7 +4298,7 @@ static int qeth_setadpparms_set_access_ctrl_cb(struct qeth_card *card,
|
|||
|
||||
QETH_CARD_TEXT(card, 4, "setaccb");
|
||||
if (cmd->hdr.return_code)
|
||||
return 0;
|
||||
return -EIO;
|
||||
qeth_setadpparms_inspect_rc(cmd);
|
||||
|
||||
access_ctrl_req = &cmd->data.setadapterparms.data.set_access_ctrl;
|
||||
|
@ -4327,7 +4372,7 @@ static int qeth_setadpparms_set_access_ctrl_cb(struct qeth_card *card,
|
|||
card->options.isolation = card->options.prev_isolation;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
return (cmd->hdr.return_code) ? -EIO : 0;
|
||||
}
|
||||
|
||||
static int qeth_setadpparms_set_access_ctrl(struct qeth_card *card,
|
||||
|
@ -4461,27 +4506,6 @@ static int qeth_mdio_read(struct net_device *dev, int phy_id, int regnum)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int qeth_send_ipa_snmp_cmd(struct qeth_card *card,
|
||||
struct qeth_cmd_buffer *iob, int len,
|
||||
int (*reply_cb)(struct qeth_card *, struct qeth_reply *,
|
||||
unsigned long),
|
||||
void *reply_param)
|
||||
{
|
||||
u16 s1, s2;
|
||||
|
||||
QETH_CARD_TEXT(card, 4, "sendsnmp");
|
||||
|
||||
/* adjust PDU length fields in IPA_PDU_HEADER */
|
||||
s1 = (u32) IPA_PDU_HEADER_SIZE + len;
|
||||
s2 = (u32) len;
|
||||
memcpy(QETH_IPA_PDU_LEN_TOTAL(iob->data), &s1, 2);
|
||||
memcpy(QETH_IPA_PDU_LEN_PDU1(iob->data), &s2, 2);
|
||||
memcpy(QETH_IPA_PDU_LEN_PDU2(iob->data), &s2, 2);
|
||||
memcpy(QETH_IPA_PDU_LEN_PDU3(iob->data), &s2, 2);
|
||||
return qeth_send_control_data(card, IPA_PDU_HEADER_SIZE + len, iob,
|
||||
reply_cb, reply_param);
|
||||
}
|
||||
|
||||
static int qeth_snmp_command_cb(struct qeth_card *card,
|
||||
struct qeth_reply *reply, unsigned long sdata)
|
||||
{
|
||||
|
@ -4499,13 +4523,13 @@ static int qeth_snmp_command_cb(struct qeth_card *card,
|
|||
|
||||
if (cmd->hdr.return_code) {
|
||||
QETH_CARD_TEXT_(card, 4, "scer1%x", cmd->hdr.return_code);
|
||||
return 0;
|
||||
return -EIO;
|
||||
}
|
||||
if (cmd->data.setadapterparms.hdr.return_code) {
|
||||
cmd->hdr.return_code =
|
||||
cmd->data.setadapterparms.hdr.return_code;
|
||||
QETH_CARD_TEXT_(card, 4, "scer2%x", cmd->hdr.return_code);
|
||||
return 0;
|
||||
return -EIO;
|
||||
}
|
||||
data_len = *((__u16 *)QETH_IPA_PDU_LEN_PDU1(data));
|
||||
if (cmd->data.setadapterparms.hdr.seq_no == 1) {
|
||||
|
@ -4520,9 +4544,8 @@ static int qeth_snmp_command_cb(struct qeth_card *card,
|
|||
|
||||
/* check if there is enough room in userspace */
|
||||
if ((qinfo->udata_len - qinfo->udata_offset) < data_len) {
|
||||
QETH_CARD_TEXT_(card, 4, "scer3%i", -ENOMEM);
|
||||
cmd->hdr.return_code = IPA_RC_ENOMEM;
|
||||
return 0;
|
||||
QETH_CARD_TEXT_(card, 4, "scer3%i", -ENOSPC);
|
||||
return -ENOSPC;
|
||||
}
|
||||
QETH_CARD_TEXT_(card, 4, "snore%i",
|
||||
cmd->data.setadapterparms.hdr.used_total);
|
||||
|
@ -4587,10 +4610,13 @@ static int qeth_snmp_command(struct qeth_card *card, char __user *udata)
|
|||
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_snmp_cmd(card, iob, QETH_SETADP_BASE_LEN + req_len,
|
||||
qeth_snmp_command_cb, (void *)&qinfo);
|
||||
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",
|
||||
CARD_DEVID(card), rc);
|
||||
|
@ -4614,16 +4640,14 @@ static int qeth_setadpparms_query_oat_cb(struct qeth_card *card,
|
|||
|
||||
QETH_CARD_TEXT(card, 3, "qoatcb");
|
||||
if (qeth_setadpparms_inspect_rc(cmd))
|
||||
return 0;
|
||||
return -EIO;
|
||||
|
||||
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;
|
||||
}
|
||||
if (resdatalen > (priv->buffer_len - priv->response_len))
|
||||
return -ENOSPC;
|
||||
|
||||
memcpy((priv->buffer + priv->response_len), resdata,
|
||||
resdatalen);
|
||||
|
@ -4696,9 +4720,7 @@ static int qeth_query_oat_command(struct qeth_card *card, char __user *udata)
|
|||
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:
|
||||
vfree(priv.buffer);
|
||||
|
@ -4715,7 +4737,7 @@ static int qeth_query_card_info_cb(struct qeth_card *card,
|
|||
|
||||
QETH_CARD_TEXT(card, 2, "qcrdincb");
|
||||
if (qeth_setadpparms_inspect_rc(cmd))
|
||||
return 0;
|
||||
return -EIO;
|
||||
|
||||
card_info = &cmd->data.setadapterparms.data.card_info;
|
||||
carrier_info->card_type = card_info->card_type;
|
||||
|
@ -5117,12 +5139,10 @@ retriable:
|
|||
rc = qeth_send_startlan(card);
|
||||
if (rc) {
|
||||
QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc);
|
||||
if (rc == IPA_RC_LAN_OFFLINE) {
|
||||
dev_warn(&card->gdev->dev,
|
||||
"The LAN is offline\n");
|
||||
if (rc == -ENETDOWN) {
|
||||
dev_warn(&card->gdev->dev, "The LAN is offline\n");
|
||||
*carrier_ok = false;
|
||||
} else {
|
||||
rc = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
|
@ -5392,7 +5412,7 @@ static int qeth_setassparms_get_caps_cb(struct qeth_card *card,
|
|||
struct qeth_ipa_caps *caps = reply->param;
|
||||
|
||||
if (qeth_setassparms_inspect_rc(cmd))
|
||||
return 0;
|
||||
return -EIO;
|
||||
|
||||
caps->supported = cmd->data.setassparms.data.caps.supported;
|
||||
caps->enabled = cmd->data.setassparms.data.caps.enabled;
|
||||
|
@ -5402,18 +5422,18 @@ static int qeth_setassparms_get_caps_cb(struct qeth_card *card,
|
|||
int qeth_setassparms_cb(struct qeth_card *card,
|
||||
struct qeth_reply *reply, unsigned long data)
|
||||
{
|
||||
struct qeth_ipa_cmd *cmd;
|
||||
struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
|
||||
|
||||
QETH_CARD_TEXT(card, 4, "defadpcb");
|
||||
|
||||
cmd = (struct qeth_ipa_cmd *) data;
|
||||
if (cmd->hdr.return_code == 0) {
|
||||
cmd->hdr.return_code = cmd->data.setassparms.hdr.return_code;
|
||||
if (cmd->hdr.prot_version == QETH_PROT_IPV4)
|
||||
card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled;
|
||||
if (cmd->hdr.prot_version == QETH_PROT_IPV6)
|
||||
card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled;
|
||||
}
|
||||
if (cmd->hdr.return_code)
|
||||
return -EIO;
|
||||
|
||||
cmd->hdr.return_code = cmd->data.setassparms.hdr.return_code;
|
||||
if (cmd->hdr.prot_version == QETH_PROT_IPV4)
|
||||
card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled;
|
||||
if (cmd->hdr.prot_version == QETH_PROT_IPV6)
|
||||
card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qeth_setassparms_cb);
|
||||
|
@ -6279,120 +6299,91 @@ int qeth_core_ethtool_get_link_ksettings(struct net_device *netdev,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(qeth_core_ethtool_get_link_ksettings);
|
||||
|
||||
/* Callback to handle checksum offload command reply from OSA card.
|
||||
* Verify that required features have been enabled on the card.
|
||||
* Return error in hdr->return_code as this value is checked by caller.
|
||||
*
|
||||
* Always returns zero to indicate no further messages from the OSA card.
|
||||
*/
|
||||
static int qeth_ipa_checksum_run_cmd_cb(struct qeth_card *card,
|
||||
struct qeth_reply *reply,
|
||||
unsigned long data)
|
||||
static int qeth_start_csum_cb(struct qeth_card *card, struct qeth_reply *reply,
|
||||
unsigned long data)
|
||||
{
|
||||
struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
|
||||
struct qeth_checksum_cmd *chksum_cb =
|
||||
(struct qeth_checksum_cmd *)reply->param;
|
||||
u32 *features = reply->param;
|
||||
|
||||
QETH_CARD_TEXT(card, 4, "chkdoccb");
|
||||
if (qeth_setassparms_inspect_rc(cmd))
|
||||
return 0;
|
||||
return -EIO;
|
||||
|
||||
memset(chksum_cb, 0, sizeof(*chksum_cb));
|
||||
if (cmd->data.setassparms.hdr.command_code == IPA_CMD_ASS_START) {
|
||||
chksum_cb->supported =
|
||||
cmd->data.setassparms.data.chksum.supported;
|
||||
QETH_CARD_TEXT_(card, 3, "strt:%x", chksum_cb->supported);
|
||||
}
|
||||
if (cmd->data.setassparms.hdr.command_code == IPA_CMD_ASS_ENABLE) {
|
||||
chksum_cb->supported =
|
||||
cmd->data.setassparms.data.chksum.supported;
|
||||
chksum_cb->enabled =
|
||||
cmd->data.setassparms.data.chksum.enabled;
|
||||
QETH_CARD_TEXT_(card, 3, "supp:%x", chksum_cb->supported);
|
||||
QETH_CARD_TEXT_(card, 3, "enab:%x", chksum_cb->enabled);
|
||||
}
|
||||
*features = cmd->data.setassparms.data.flags_32bit;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Send command to OSA card and check results. */
|
||||
static int qeth_ipa_checksum_run_cmd(struct qeth_card *card,
|
||||
enum qeth_ipa_funcs ipa_func,
|
||||
__u16 cmd_code, long data,
|
||||
struct qeth_checksum_cmd *chksum_cb,
|
||||
enum qeth_prot_versions prot)
|
||||
static int qeth_set_csum_off(struct qeth_card *card, enum qeth_ipa_funcs cstype,
|
||||
enum qeth_prot_versions prot)
|
||||
{
|
||||
struct qeth_cmd_buffer *iob;
|
||||
return qeth_send_simple_setassparms_prot(card, cstype,
|
||||
IPA_CMD_ASS_STOP, 0, prot);
|
||||
}
|
||||
|
||||
QETH_CARD_TEXT(card, 4, "chkdocmd");
|
||||
iob = qeth_get_setassparms_cmd(card, ipa_func, cmd_code,
|
||||
sizeof(__u32), prot);
|
||||
static int qeth_set_csum_on(struct qeth_card *card, enum qeth_ipa_funcs cstype,
|
||||
enum qeth_prot_versions prot)
|
||||
{
|
||||
u32 required_features = QETH_IPA_CHECKSUM_UDP | QETH_IPA_CHECKSUM_TCP;
|
||||
struct qeth_cmd_buffer *iob;
|
||||
struct qeth_ipa_caps caps;
|
||||
u32 features;
|
||||
int rc;
|
||||
|
||||
/* some L3 HW requires combined L3+L4 csum offload: */
|
||||
if (IS_LAYER3(card) && prot == QETH_PROT_IPV4 &&
|
||||
cstype == IPA_OUTBOUND_CHECKSUM)
|
||||
required_features |= QETH_IPA_CHECKSUM_IP_HDR;
|
||||
|
||||
iob = qeth_get_setassparms_cmd(card, cstype, IPA_CMD_ASS_START, 0,
|
||||
prot);
|
||||
if (!iob)
|
||||
return -ENOMEM;
|
||||
|
||||
__ipa_cmd(iob)->data.setassparms.data.flags_32bit = (__u32) data;
|
||||
return qeth_send_ipa_cmd(card, iob, qeth_ipa_checksum_run_cmd_cb,
|
||||
chksum_cb);
|
||||
}
|
||||
|
||||
static int qeth_send_checksum_on(struct qeth_card *card, int cstype,
|
||||
enum qeth_prot_versions prot)
|
||||
{
|
||||
u32 required_features = QETH_IPA_CHECKSUM_UDP | QETH_IPA_CHECKSUM_TCP;
|
||||
struct qeth_checksum_cmd chksum_cb;
|
||||
int rc;
|
||||
|
||||
if (prot == QETH_PROT_IPV4)
|
||||
required_features |= QETH_IPA_CHECKSUM_IP_HDR;
|
||||
rc = qeth_ipa_checksum_run_cmd(card, cstype, IPA_CMD_ASS_START, 0,
|
||||
&chksum_cb, prot);
|
||||
if (!rc) {
|
||||
if ((required_features & chksum_cb.supported) !=
|
||||
required_features)
|
||||
rc = -EIO;
|
||||
else if (!(QETH_IPA_CHECKSUM_LP2LP & chksum_cb.supported) &&
|
||||
cstype == IPA_INBOUND_CHECKSUM)
|
||||
dev_warn(&card->gdev->dev,
|
||||
"Hardware checksumming is performed only if %s and its peer use different OSA Express 3 ports\n",
|
||||
QETH_CARD_IFNAME(card));
|
||||
}
|
||||
if (rc) {
|
||||
qeth_send_simple_setassparms_prot(card, cstype,
|
||||
IPA_CMD_ASS_STOP, 0, prot);
|
||||
dev_warn(&card->gdev->dev,
|
||||
"Starting HW IPv%d checksumming for %s failed, using SW checksumming\n",
|
||||
prot, QETH_CARD_IFNAME(card));
|
||||
rc = qeth_send_ipa_cmd(card, iob, qeth_start_csum_cb, &features);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if ((required_features & features) != required_features) {
|
||||
qeth_set_csum_off(card, cstype, prot);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
rc = qeth_ipa_checksum_run_cmd(card, cstype, IPA_CMD_ASS_ENABLE,
|
||||
chksum_cb.supported, &chksum_cb,
|
||||
|
||||
iob = qeth_get_setassparms_cmd(card, cstype, IPA_CMD_ASS_ENABLE, 4,
|
||||
prot);
|
||||
if (!rc) {
|
||||
if ((required_features & chksum_cb.enabled) !=
|
||||
required_features)
|
||||
rc = -EIO;
|
||||
if (!iob) {
|
||||
qeth_set_csum_off(card, cstype, prot);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (features & QETH_IPA_CHECKSUM_LP2LP)
|
||||
required_features |= QETH_IPA_CHECKSUM_LP2LP;
|
||||
__ipa_cmd(iob)->data.setassparms.data.flags_32bit = required_features;
|
||||
rc = qeth_send_ipa_cmd(card, iob, qeth_setassparms_get_caps_cb, &caps);
|
||||
if (rc) {
|
||||
qeth_send_simple_setassparms_prot(card, cstype,
|
||||
IPA_CMD_ASS_STOP, 0, prot);
|
||||
dev_warn(&card->gdev->dev,
|
||||
"Enabling HW IPv%d checksumming for %s failed, using SW checksumming\n",
|
||||
prot, QETH_CARD_IFNAME(card));
|
||||
qeth_set_csum_off(card, cstype, prot);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (!qeth_ipa_caps_supported(&caps, required_features) ||
|
||||
!qeth_ipa_caps_enabled(&caps, required_features)) {
|
||||
qeth_set_csum_off(card, cstype, prot);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
dev_info(&card->gdev->dev, "HW Checksumming (%sbound IPv%d) enabled\n",
|
||||
cstype == IPA_INBOUND_CHECKSUM ? "in" : "out", prot);
|
||||
if (!qeth_ipa_caps_enabled(&caps, QETH_IPA_CHECKSUM_LP2LP) &&
|
||||
cstype == IPA_OUTBOUND_CHECKSUM)
|
||||
dev_warn(&card->gdev->dev,
|
||||
"Hardware checksumming is performed only if %s and its peer use different OSA Express 3 ports\n",
|
||||
QETH_CARD_IFNAME(card));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qeth_set_ipa_csum(struct qeth_card *card, bool on, int cstype,
|
||||
enum qeth_prot_versions prot)
|
||||
{
|
||||
int rc = (on) ? qeth_send_checksum_on(card, cstype, prot)
|
||||
: qeth_send_simple_setassparms_prot(card, cstype,
|
||||
IPA_CMD_ASS_STOP, 0,
|
||||
prot);
|
||||
return rc ? -EIO : 0;
|
||||
return on ? qeth_set_csum_on(card, cstype, prot) :
|
||||
qeth_set_csum_off(card, cstype, prot);
|
||||
}
|
||||
|
||||
static int qeth_start_tso_cb(struct qeth_card *card, struct qeth_reply *reply,
|
||||
|
@ -6402,7 +6393,7 @@ static int qeth_start_tso_cb(struct qeth_card *card, struct qeth_reply *reply,
|
|||
struct qeth_tso_start_data *tso_data = reply->param;
|
||||
|
||||
if (qeth_setassparms_inspect_rc(cmd))
|
||||
return 0;
|
||||
return -EIO;
|
||||
|
||||
tso_data->mss = cmd->data.setassparms.data.tso.mss;
|
||||
tso_data->supported = cmd->data.setassparms.data.tso.supported;
|
||||
|
@ -6468,10 +6459,7 @@ static int qeth_set_tso_on(struct qeth_card *card,
|
|||
static int qeth_set_ipa_tso(struct qeth_card *card, bool on,
|
||||
enum qeth_prot_versions prot)
|
||||
{
|
||||
int rc = on ? qeth_set_tso_on(card, prot) :
|
||||
qeth_set_tso_off(card, prot);
|
||||
|
||||
return rc ? -EIO : 0;
|
||||
return on ? qeth_set_tso_on(card, prot) : qeth_set_tso_off(card, prot);
|
||||
}
|
||||
|
||||
static int qeth_set_ipa_rx_csum(struct qeth_card *card, bool on)
|
||||
|
|
|
@ -125,24 +125,13 @@ unsigned char DM_ACT[] = {
|
|||
|
||||
unsigned char IPA_PDU_HEADER[] = {
|
||||
0x00, 0xe0, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77,
|
||||
0x00, 0x00, 0x00, 0x14, 0x00, 0x00,
|
||||
(IPA_PDU_HEADER_SIZE+sizeof(struct qeth_ipa_cmd)) / 256,
|
||||
(IPA_PDU_HEADER_SIZE+sizeof(struct qeth_ipa_cmd)) % 256,
|
||||
0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00,
|
||||
0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||
0xc1, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x24,
|
||||
sizeof(struct qeth_ipa_cmd) / 256,
|
||||
sizeof(struct qeth_ipa_cmd) % 256,
|
||||
0x00,
|
||||
sizeof(struct qeth_ipa_cmd) / 256,
|
||||
sizeof(struct qeth_ipa_cmd) % 256,
|
||||
0x05,
|
||||
0x77, 0x77, 0x77, 0x77,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x05, 0x77, 0x77, 0x77, 0x77,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00,
|
||||
sizeof(struct qeth_ipa_cmd) / 256,
|
||||
sizeof(struct qeth_ipa_cmd) % 256,
|
||||
0x00, 0x00, 0x00, 0x40,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
|
||||
};
|
||||
|
||||
struct ipa_rc_msg {
|
||||
|
@ -212,12 +201,10 @@ static const struct ipa_rc_msg qeth_ipa_rc_msg[] = {
|
|||
{IPA_RC_LAN_OFFLINE, "STRTLAN_LAN_DISABLED - LAN offline"},
|
||||
{IPA_RC_VEPA_TO_VEB_TRANSITION, "Adj. switch disabled port mode RR"},
|
||||
{IPA_RC_INVALID_IP_VERSION2, "Invalid IP version"},
|
||||
{IPA_RC_ENOMEM, "Memory problem"},
|
||||
/* default for qeth_get_ipa_msg(): */
|
||||
{IPA_RC_FFFF, "Unknown Error"}
|
||||
};
|
||||
|
||||
|
||||
|
||||
const char *qeth_get_ipa_msg(enum qeth_ipa_return_codes rc)
|
||||
{
|
||||
int x;
|
||||
|
|
|
@ -21,8 +21,6 @@
|
|||
extern unsigned char IPA_PDU_HEADER[];
|
||||
#define QETH_IPA_CMD_DEST_ADDR(buffer) (buffer + 0x2c)
|
||||
|
||||
#define IPA_CMD_LENGTH (IPA_PDU_HEADER_SIZE + sizeof(struct qeth_ipa_cmd))
|
||||
|
||||
#define QETH_SEQ_NO_LENGTH 4
|
||||
#define QETH_MPC_TOKEN_LENGTH 4
|
||||
#define QETH_MCL_LENGTH 4
|
||||
|
@ -231,7 +229,6 @@ enum qeth_ipa_return_codes {
|
|||
IPA_RC_LAN_OFFLINE = 0xe080,
|
||||
IPA_RC_VEPA_TO_VEB_TRANSITION = 0xe090,
|
||||
IPA_RC_INVALID_IP_VERSION2 = 0xf001,
|
||||
IPA_RC_ENOMEM = 0xfffe,
|
||||
IPA_RC_FFFF = 0xffff
|
||||
};
|
||||
/* for VNIC Characteristics */
|
||||
|
@ -419,12 +416,6 @@ enum qeth_ipa_checksum_bits {
|
|||
QETH_IPA_CHECKSUM_LP2LP = 0x0020
|
||||
};
|
||||
|
||||
/* IPA Assist checksum offload reply layout. */
|
||||
struct qeth_checksum_cmd {
|
||||
__u32 supported;
|
||||
__u32 enabled;
|
||||
} __packed;
|
||||
|
||||
enum qeth_ipa_large_send_caps {
|
||||
QETH_IPA_LARGE_SEND_TCP = 0x00000001,
|
||||
};
|
||||
|
@ -440,7 +431,6 @@ struct qeth_ipacmd_setassparms {
|
|||
union {
|
||||
__u32 flags_32bit;
|
||||
struct qeth_ipa_caps caps;
|
||||
struct qeth_checksum_cmd chksum;
|
||||
struct qeth_arp_cache_entry arp_entry;
|
||||
struct qeth_arp_query_data query_arp;
|
||||
struct qeth_tso_start_data tso;
|
||||
|
@ -834,15 +824,10 @@ 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_SETASS_BASE_LEN (IPA_PDU_HEADER_SIZE + \
|
||||
sizeof(struct qeth_ipacmd_hdr) + \
|
||||
sizeof(struct qeth_ipacmd_setassparms_hdr))
|
||||
#define QETH_SETADP_BASE_LEN (sizeof(struct qeth_ipacmd_hdr) + \
|
||||
sizeof(struct qeth_ipacmd_setadpparms_hdr))
|
||||
#define QETH_SNMP_SETADP_CMDLENGTH 16
|
||||
|
||||
#define QETH_ARP_DATA_SIZE 3968
|
||||
#define QETH_ARP_CMD_LEN (QETH_ARP_DATA_SIZE + 8)
|
||||
/* Helper functions */
|
||||
#define IS_IPA_REPLY(cmd) ((cmd->hdr.initiator == IPA_CMD_INITIATOR_HOST) || \
|
||||
(cmd->hdr.initiator == IPA_CMD_INITIATOR_OSA_REPLY))
|
||||
|
|
|
@ -35,7 +35,7 @@ static void qeth_l2_vnicc_init(struct qeth_card *card);
|
|||
static bool qeth_l2_vnicc_recover_timeout(struct qeth_card *card, u32 vnicc,
|
||||
u32 *timeout);
|
||||
|
||||
static int qeth_setdelmac_makerc(struct qeth_card *card, int retcode)
|
||||
static int qeth_l2_setdelmac_makerc(struct qeth_card *card, u16 retcode)
|
||||
{
|
||||
int rc;
|
||||
|
||||
|
@ -62,9 +62,6 @@ static int qeth_setdelmac_makerc(struct qeth_card *card, int retcode)
|
|||
case IPA_RC_L2_MAC_NOT_FOUND:
|
||||
rc = -ENOENT;
|
||||
break;
|
||||
case -ENOMEM:
|
||||
rc = -ENOMEM;
|
||||
break;
|
||||
default:
|
||||
rc = -EIO;
|
||||
break;
|
||||
|
@ -72,6 +69,15 @@ static int qeth_setdelmac_makerc(struct qeth_card *card, int retcode)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int qeth_l2_send_setdelmac_cb(struct qeth_card *card,
|
||||
struct qeth_reply *reply,
|
||||
unsigned long data)
|
||||
{
|
||||
struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
|
||||
|
||||
return qeth_l2_setdelmac_makerc(card, cmd->hdr.return_code);
|
||||
}
|
||||
|
||||
static int qeth_l2_send_setdelmac(struct qeth_card *card, __u8 *mac,
|
||||
enum qeth_ipa_cmds ipacmd)
|
||||
{
|
||||
|
@ -85,8 +91,7 @@ static int qeth_l2_send_setdelmac(struct qeth_card *card, __u8 *mac,
|
|||
cmd = __ipa_cmd(iob);
|
||||
cmd->data.setdelmac.mac_length = ETH_ALEN;
|
||||
ether_addr_copy(cmd->data.setdelmac.mac, mac);
|
||||
return qeth_setdelmac_makerc(card, qeth_send_ipa_cmd(card, iob,
|
||||
NULL, NULL));
|
||||
return qeth_send_ipa_cmd(card, iob, qeth_l2_send_setdelmac_cb, NULL);
|
||||
}
|
||||
|
||||
static int qeth_l2_send_setmac(struct qeth_card *card, __u8 *mac)
|
||||
|
@ -205,7 +210,7 @@ static void qeth_l2_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
|
|||
}
|
||||
}
|
||||
|
||||
static int qeth_setdelvlan_makerc(struct qeth_card *card, int retcode)
|
||||
static int qeth_l2_setdelvlan_makerc(struct qeth_card *card, u16 retcode)
|
||||
{
|
||||
if (retcode)
|
||||
QETH_CARD_TEXT_(card, 2, "err%04x", retcode);
|
||||
|
@ -221,8 +226,6 @@ static int qeth_setdelvlan_makerc(struct qeth_card *card, int retcode)
|
|||
return -ENOENT;
|
||||
case IPA_RC_L2_VLAN_ID_NOT_ALLOWED:
|
||||
return -EPERM;
|
||||
case -ENOMEM:
|
||||
return -ENOMEM;
|
||||
default:
|
||||
return -EIO;
|
||||
}
|
||||
|
@ -240,9 +243,8 @@ static int qeth_l2_send_setdelvlan_cb(struct qeth_card *card,
|
|||
cmd->data.setdelvlan.vlan_id,
|
||||
CARD_DEVID(card), cmd->hdr.return_code);
|
||||
QETH_CARD_TEXT_(card, 2, "L2VL%4x", cmd->hdr.command);
|
||||
QETH_CARD_TEXT_(card, 2, "err%d", cmd->hdr.return_code);
|
||||
}
|
||||
return 0;
|
||||
return qeth_l2_setdelvlan_makerc(card, cmd->hdr.return_code);
|
||||
}
|
||||
|
||||
static int qeth_l2_send_setdelvlan(struct qeth_card *card, __u16 i,
|
||||
|
@ -257,8 +259,7 @@ static int qeth_l2_send_setdelvlan(struct qeth_card *card, __u16 i,
|
|||
return -ENOMEM;
|
||||
cmd = __ipa_cmd(iob);
|
||||
cmd->data.setdelvlan.vlan_id = i;
|
||||
return qeth_setdelvlan_makerc(card, qeth_send_ipa_cmd(card, iob,
|
||||
qeth_l2_send_setdelvlan_cb, NULL));
|
||||
return qeth_send_ipa_cmd(card, iob, qeth_l2_send_setdelvlan_cb, NULL);
|
||||
}
|
||||
|
||||
static int qeth_l2_vlan_rx_add_vid(struct net_device *dev,
|
||||
|
@ -393,7 +394,7 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card)
|
|||
|
||||
if (!IS_OSN(card)) {
|
||||
rc = qeth_setadpparms_change_macaddr(card);
|
||||
if (!rc && is_valid_ether_addr(card->dev->dev_addr))
|
||||
if (!rc)
|
||||
goto out;
|
||||
QETH_DBF_MESSAGE(2, "READ_MAC Assist failed on device %x: %#x\n",
|
||||
CARD_DEVID(card), rc);
|
||||
|
@ -1124,20 +1125,14 @@ static int qeth_osn_send_control_data(struct qeth_card *card, int len,
|
|||
}
|
||||
|
||||
static int qeth_osn_send_ipa_cmd(struct qeth_card *card,
|
||||
struct qeth_cmd_buffer *iob, int data_len)
|
||||
struct qeth_cmd_buffer *iob)
|
||||
{
|
||||
u16 s1, s2;
|
||||
u16 length;
|
||||
|
||||
QETH_CARD_TEXT(card, 4, "osndipa");
|
||||
|
||||
qeth_prepare_ipa_cmd(card, iob);
|
||||
s1 = (u16)(IPA_PDU_HEADER_SIZE + data_len);
|
||||
s2 = (u16)data_len;
|
||||
memcpy(QETH_IPA_PDU_LEN_TOTAL(iob->data), &s1, 2);
|
||||
memcpy(QETH_IPA_PDU_LEN_PDU1(iob->data), &s2, 2);
|
||||
memcpy(QETH_IPA_PDU_LEN_PDU2(iob->data), &s2, 2);
|
||||
memcpy(QETH_IPA_PDU_LEN_PDU3(iob->data), &s2, 2);
|
||||
return qeth_osn_send_control_data(card, s1, iob);
|
||||
memcpy(&length, QETH_IPA_PDU_LEN_TOTAL(iob->data), 2);
|
||||
return qeth_osn_send_control_data(card, length, iob);
|
||||
}
|
||||
|
||||
int qeth_osn_assist(struct net_device *dev, void *data, int data_len)
|
||||
|
@ -1154,8 +1149,9 @@ int qeth_osn_assist(struct net_device *dev, void *data, int data_len)
|
|||
if (!qeth_card_hw_is_reachable(card))
|
||||
return -ENODEV;
|
||||
iob = qeth_wait_for_buffer(&card->write);
|
||||
qeth_prepare_ipa_cmd(card, iob, (u16) data_len);
|
||||
memcpy(__ipa_cmd(iob), data, data_len);
|
||||
return qeth_osn_send_ipa_cmd(card, iob, data_len);
|
||||
return qeth_osn_send_ipa_cmd(card, iob);
|
||||
}
|
||||
EXPORT_SYMBOL(qeth_osn_assist);
|
||||
|
||||
|
@ -1412,8 +1408,6 @@ static void qeth_bridge_host_event(struct qeth_card *card,
|
|||
/* SETBRIDGEPORT support; sending commands */
|
||||
|
||||
struct _qeth_sbp_cbctl {
|
||||
u16 ipa_rc;
|
||||
u16 cmd_rc;
|
||||
union {
|
||||
u32 supported;
|
||||
struct {
|
||||
|
@ -1423,23 +1417,21 @@ struct _qeth_sbp_cbctl {
|
|||
} data;
|
||||
};
|
||||
|
||||
/**
|
||||
* qeth_bridgeport_makerc() - derive "traditional" error from hardware codes.
|
||||
* @card: qeth_card structure pointer, for debug messages.
|
||||
* @cbctl: state structure with hardware return codes.
|
||||
* @setcmd: IPA command code
|
||||
*
|
||||
* Returns negative errno-compatible error indication or 0 on success.
|
||||
*/
|
||||
static int qeth_bridgeport_makerc(struct qeth_card *card,
|
||||
struct _qeth_sbp_cbctl *cbctl, enum qeth_ipa_sbp_cmd setcmd)
|
||||
struct qeth_ipa_cmd *cmd)
|
||||
{
|
||||
struct qeth_ipacmd_setbridgeport *sbp = &cmd->data.sbp;
|
||||
enum qeth_ipa_sbp_cmd setcmd = sbp->hdr.command_code;
|
||||
u16 ipa_rc = cmd->hdr.return_code;
|
||||
u16 sbp_rc = sbp->hdr.return_code;
|
||||
int rc;
|
||||
int is_iqd = (card->info.type == QETH_CARD_TYPE_IQD);
|
||||
|
||||
if ((is_iqd && (cbctl->ipa_rc == IPA_RC_SUCCESS)) ||
|
||||
(!is_iqd && (cbctl->ipa_rc == cbctl->cmd_rc)))
|
||||
switch (cbctl->cmd_rc) {
|
||||
if (ipa_rc == IPA_RC_SUCCESS && sbp_rc == IPA_RC_SUCCESS)
|
||||
return 0;
|
||||
|
||||
if ((IS_IQD(card) && ipa_rc == IPA_RC_SUCCESS) ||
|
||||
(!IS_IQD(card) && ipa_rc == sbp_rc)) {
|
||||
switch (sbp_rc) {
|
||||
case IPA_RC_SUCCESS:
|
||||
rc = 0;
|
||||
break;
|
||||
|
@ -1503,8 +1495,8 @@ static int qeth_bridgeport_makerc(struct qeth_card *card,
|
|||
default:
|
||||
rc = -EIO;
|
||||
}
|
||||
else
|
||||
switch (cbctl->ipa_rc) {
|
||||
} else {
|
||||
switch (ipa_rc) {
|
||||
case IPA_RC_NOTSUPP:
|
||||
rc = -EOPNOTSUPP;
|
||||
break;
|
||||
|
@ -1514,10 +1506,11 @@ static int qeth_bridgeport_makerc(struct qeth_card *card,
|
|||
default:
|
||||
rc = -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
if (rc) {
|
||||
QETH_CARD_TEXT_(card, 2, "SBPi%04x", cbctl->ipa_rc);
|
||||
QETH_CARD_TEXT_(card, 2, "SBPc%04x", cbctl->cmd_rc);
|
||||
QETH_CARD_TEXT_(card, 2, "SBPi%04x", ipa_rc);
|
||||
QETH_CARD_TEXT_(card, 2, "SBPc%04x", sbp_rc);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
@ -1549,15 +1542,15 @@ static int qeth_bridgeport_query_support_cb(struct qeth_card *card,
|
|||
{
|
||||
struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
|
||||
struct _qeth_sbp_cbctl *cbctl = (struct _qeth_sbp_cbctl *)reply->param;
|
||||
int rc;
|
||||
|
||||
QETH_CARD_TEXT(card, 2, "brqsupcb");
|
||||
cbctl->ipa_rc = cmd->hdr.return_code;
|
||||
cbctl->cmd_rc = cmd->data.sbp.hdr.return_code;
|
||||
if ((cbctl->ipa_rc == 0) && (cbctl->cmd_rc == 0)) {
|
||||
cbctl->data.supported =
|
||||
cmd->data.sbp.data.query_cmds_supp.supported_cmds;
|
||||
} else {
|
||||
cbctl->data.supported = 0;
|
||||
}
|
||||
rc = qeth_bridgeport_makerc(card, cmd);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
cbctl->data.supported =
|
||||
cmd->data.sbp.data.query_cmds_supp.supported_cmds;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1578,12 +1571,11 @@ static void qeth_bridgeport_query_support(struct qeth_card *card)
|
|||
sizeof(struct qeth_sbp_query_cmds_supp));
|
||||
if (!iob)
|
||||
return;
|
||||
|
||||
if (qeth_send_ipa_cmd(card, iob, qeth_bridgeport_query_support_cb,
|
||||
(void *)&cbctl) ||
|
||||
qeth_bridgeport_makerc(card, &cbctl,
|
||||
IPA_SBP_QUERY_COMMANDS_SUPPORTED)) {
|
||||
/* non-zero makerc signifies failure, and produce messages */
|
||||
&cbctl)) {
|
||||
card->options.sbp.role = QETH_SBP_ROLE_NONE;
|
||||
card->options.sbp.supported_funcs = 0;
|
||||
return;
|
||||
}
|
||||
card->options.sbp.supported_funcs = cbctl.data.supported;
|
||||
|
@ -1595,16 +1587,16 @@ static int qeth_bridgeport_query_ports_cb(struct qeth_card *card,
|
|||
struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
|
||||
struct qeth_sbp_query_ports *qports = &cmd->data.sbp.data.query_ports;
|
||||
struct _qeth_sbp_cbctl *cbctl = (struct _qeth_sbp_cbctl *)reply->param;
|
||||
int rc;
|
||||
|
||||
QETH_CARD_TEXT(card, 2, "brqprtcb");
|
||||
cbctl->ipa_rc = cmd->hdr.return_code;
|
||||
cbctl->cmd_rc = cmd->data.sbp.hdr.return_code;
|
||||
if ((cbctl->ipa_rc != 0) || (cbctl->cmd_rc != 0))
|
||||
return 0;
|
||||
rc = qeth_bridgeport_makerc(card, cmd);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (qports->entry_length != sizeof(struct qeth_sbp_port_entry)) {
|
||||
cbctl->cmd_rc = 0xffff;
|
||||
QETH_CARD_TEXT_(card, 2, "SBPs%04x", qports->entry_length);
|
||||
return 0;
|
||||
return -EINVAL;
|
||||
}
|
||||
/* first entry contains the state of the local port */
|
||||
if (qports->num_entries > 0) {
|
||||
|
@ -1629,7 +1621,6 @@ static int qeth_bridgeport_query_ports_cb(struct qeth_card *card,
|
|||
int qeth_bridgeport_query_ports(struct qeth_card *card,
|
||||
enum qeth_sbp_roles *role, enum qeth_sbp_states *state)
|
||||
{
|
||||
int rc = 0;
|
||||
struct qeth_cmd_buffer *iob;
|
||||
struct _qeth_sbp_cbctl cbctl = {
|
||||
.data = {
|
||||
|
@ -1646,22 +1637,18 @@ int qeth_bridgeport_query_ports(struct qeth_card *card,
|
|||
iob = qeth_sbp_build_cmd(card, IPA_SBP_QUERY_BRIDGE_PORTS, 0);
|
||||
if (!iob)
|
||||
return -ENOMEM;
|
||||
rc = qeth_send_ipa_cmd(card, iob, qeth_bridgeport_query_ports_cb,
|
||||
(void *)&cbctl);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
return qeth_bridgeport_makerc(card, &cbctl, IPA_SBP_QUERY_BRIDGE_PORTS);
|
||||
|
||||
return qeth_send_ipa_cmd(card, iob, qeth_bridgeport_query_ports_cb,
|
||||
&cbctl);
|
||||
}
|
||||
|
||||
static int qeth_bridgeport_set_cb(struct qeth_card *card,
|
||||
struct qeth_reply *reply, unsigned long data)
|
||||
{
|
||||
struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *)data;
|
||||
struct _qeth_sbp_cbctl *cbctl = (struct _qeth_sbp_cbctl *)reply->param;
|
||||
|
||||
QETH_CARD_TEXT(card, 2, "brsetrcb");
|
||||
cbctl->ipa_rc = cmd->hdr.return_code;
|
||||
cbctl->cmd_rc = cmd->data.sbp.hdr.return_code;
|
||||
return 0;
|
||||
return qeth_bridgeport_makerc(card, cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1673,10 +1660,8 @@ static int qeth_bridgeport_set_cb(struct qeth_card *card,
|
|||
*/
|
||||
int qeth_bridgeport_setrole(struct qeth_card *card, enum qeth_sbp_roles role)
|
||||
{
|
||||
int rc = 0;
|
||||
int cmdlength;
|
||||
struct qeth_cmd_buffer *iob;
|
||||
struct _qeth_sbp_cbctl cbctl;
|
||||
enum qeth_ipa_sbp_cmd setcmd;
|
||||
|
||||
QETH_CARD_TEXT(card, 2, "brsetrol");
|
||||
|
@ -1701,11 +1686,8 @@ int qeth_bridgeport_setrole(struct qeth_card *card, enum qeth_sbp_roles role)
|
|||
iob = qeth_sbp_build_cmd(card, setcmd, cmdlength);
|
||||
if (!iob)
|
||||
return -ENOMEM;
|
||||
rc = qeth_send_ipa_cmd(card, iob, qeth_bridgeport_set_cb,
|
||||
(void *)&cbctl);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
return qeth_bridgeport_makerc(card, &cbctl, setcmd);
|
||||
|
||||
return qeth_send_ipa_cmd(card, iob, qeth_bridgeport_set_cb, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1809,7 +1791,7 @@ static bool qeth_bridgeport_is_in_use(struct qeth_card *card)
|
|||
/* VNIC Characteristics support */
|
||||
|
||||
/* handle VNICC IPA command return codes; convert to error codes */
|
||||
static int qeth_l2_vnicc_makerc(struct qeth_card *card, int ipa_rc)
|
||||
static int qeth_l2_vnicc_makerc(struct qeth_card *card, u16 ipa_rc)
|
||||
{
|
||||
int rc;
|
||||
|
||||
|
@ -1867,7 +1849,7 @@ static int qeth_l2_vnicc_request_cb(struct qeth_card *card,
|
|||
|
||||
QETH_CARD_TEXT(card, 2, "vniccrcb");
|
||||
if (cmd->hdr.return_code)
|
||||
return 0;
|
||||
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;
|
||||
|
@ -1888,7 +1870,6 @@ static int qeth_l2_vnicc_request(struct qeth_card *card,
|
|||
struct qeth_ipacmd_vnicc *req;
|
||||
struct qeth_cmd_buffer *iob;
|
||||
struct qeth_ipa_cmd *cmd;
|
||||
int rc;
|
||||
|
||||
QETH_CARD_TEXT(card, 2, "vniccreq");
|
||||
|
||||
|
@ -1931,10 +1912,7 @@ static int qeth_l2_vnicc_request(struct qeth_card *card,
|
|||
}
|
||||
|
||||
/* send request */
|
||||
rc = qeth_send_ipa_cmd(card, iob, qeth_l2_vnicc_request_cb,
|
||||
(void *) cbctl);
|
||||
|
||||
return qeth_l2_vnicc_makerc(card, rc);
|
||||
return qeth_send_ipa_cmd(card, iob, qeth_l2_vnicc_request_cb, cbctl);
|
||||
}
|
||||
|
||||
/* VNICC query VNIC characteristics request */
|
||||
|
|
|
@ -253,8 +253,7 @@ static int qeth_l3_add_ip(struct qeth_card *card, struct qeth_ipaddr *tmp_addr)
|
|||
} else
|
||||
rc = qeth_l3_register_addr_entry(card, addr);
|
||||
|
||||
if (!rc || (rc == IPA_RC_DUPLICATE_IP_ADDRESS) ||
|
||||
(rc == IPA_RC_LAN_OFFLINE)) {
|
||||
if (!rc || rc == -EADDRINUSE || rc == -ENETDOWN) {
|
||||
addr->disp_flag = QETH_DISP_ADDR_DO_NOTHING;
|
||||
if (addr->ref_counter < 1) {
|
||||
qeth_l3_deregister_addr_entry(card, addr);
|
||||
|
@ -338,10 +337,28 @@ static void qeth_l3_recover_ip(struct qeth_card *card)
|
|||
|
||||
}
|
||||
|
||||
static int qeth_l3_setdelip_cb(struct qeth_card *card, struct qeth_reply *reply,
|
||||
unsigned long data)
|
||||
{
|
||||
struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
|
||||
|
||||
switch (cmd->hdr.return_code) {
|
||||
case IPA_RC_SUCCESS:
|
||||
return 0;
|
||||
case IPA_RC_DUPLICATE_IP_ADDRESS:
|
||||
return -EADDRINUSE;
|
||||
case IPA_RC_MC_ADDR_NOT_FOUND:
|
||||
return -ENOENT;
|
||||
case IPA_RC_LAN_OFFLINE:
|
||||
return -ENETDOWN;
|
||||
default:
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
static int qeth_l3_send_setdelmc(struct qeth_card *card,
|
||||
struct qeth_ipaddr *addr, int ipacmd)
|
||||
{
|
||||
int rc;
|
||||
struct qeth_cmd_buffer *iob;
|
||||
struct qeth_ipa_cmd *cmd;
|
||||
|
||||
|
@ -358,9 +375,7 @@ static int qeth_l3_send_setdelmc(struct qeth_card *card,
|
|||
else
|
||||
memcpy(&cmd->data.setdelipm.ip4, &addr->u.a4.addr, 4);
|
||||
|
||||
rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
|
||||
|
||||
return rc;
|
||||
return qeth_send_ipa_cmd(card, iob, qeth_l3_setdelip_cb, NULL);
|
||||
}
|
||||
|
||||
static void qeth_l3_fill_netmask(u8 *netmask, unsigned int len)
|
||||
|
@ -422,7 +437,7 @@ static int qeth_l3_send_setdelip(struct qeth_card *card,
|
|||
cmd->data.setdelip4.flags = flags;
|
||||
}
|
||||
|
||||
return qeth_send_ipa_cmd(card, iob, NULL, NULL);
|
||||
return qeth_send_ipa_cmd(card, iob, qeth_l3_setdelip_cb, NULL);
|
||||
}
|
||||
|
||||
static int qeth_l3_send_setrouting(struct qeth_card *card,
|
||||
|
@ -942,12 +957,13 @@ static int qeth_l3_start_ipassists(struct qeth_card *card)
|
|||
static int qeth_l3_iqd_read_initial_mac_cb(struct qeth_card *card,
|
||||
struct qeth_reply *reply, unsigned long data)
|
||||
{
|
||||
struct qeth_ipa_cmd *cmd;
|
||||
struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
|
||||
|
||||
cmd = (struct qeth_ipa_cmd *) data;
|
||||
if (cmd->hdr.return_code == 0)
|
||||
ether_addr_copy(card->dev->dev_addr,
|
||||
cmd->data.create_destroy_addr.unique_id);
|
||||
if (cmd->hdr.return_code)
|
||||
return -EIO;
|
||||
|
||||
ether_addr_copy(card->dev->dev_addr,
|
||||
cmd->data.create_destroy_addr.unique_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -975,19 +991,18 @@ static int qeth_l3_iqd_read_initial_mac(struct qeth_card *card)
|
|||
static int qeth_l3_get_unique_id_cb(struct qeth_card *card,
|
||||
struct qeth_reply *reply, unsigned long data)
|
||||
{
|
||||
struct qeth_ipa_cmd *cmd;
|
||||
struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
|
||||
|
||||
cmd = (struct qeth_ipa_cmd *) data;
|
||||
if (cmd->hdr.return_code == 0)
|
||||
if (cmd->hdr.return_code == 0) {
|
||||
card->info.unique_id = *((__u16 *)
|
||||
&cmd->data.create_destroy_addr.unique_id[6]);
|
||||
else {
|
||||
card->info.unique_id = UNIQUE_ID_IF_CREATE_ADDR_FAILED |
|
||||
UNIQUE_ID_NOT_BY_CARD;
|
||||
dev_warn(&card->gdev->dev, "The network adapter failed to "
|
||||
"generate a unique ID\n");
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
|
||||
card->info.unique_id = UNIQUE_ID_IF_CREATE_ADDR_FAILED |
|
||||
UNIQUE_ID_NOT_BY_CARD;
|
||||
dev_warn(&card->gdev->dev, "The network adapter failed to generate a unique ID\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static int qeth_l3_get_unique_id(struct qeth_card *card)
|
||||
|
@ -1070,7 +1085,7 @@ qeth_diags_trace_cb(struct qeth_card *card, struct qeth_reply *reply,
|
|||
cmd->data.diagass.action, CARD_DEVID(card));
|
||||
}
|
||||
|
||||
return 0;
|
||||
return rc ? -EIO : 0;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -1481,14 +1496,14 @@ static void qeth_l3_set_rx_mode(struct net_device *dev)
|
|||
switch (addr->disp_flag) {
|
||||
case QETH_DISP_ADDR_DELETE:
|
||||
rc = qeth_l3_deregister_addr_entry(card, addr);
|
||||
if (!rc || rc == IPA_RC_MC_ADDR_NOT_FOUND) {
|
||||
if (!rc || rc == -ENOENT) {
|
||||
hash_del(&addr->hnode);
|
||||
kfree(addr);
|
||||
}
|
||||
break;
|
||||
case QETH_DISP_ADDR_ADD:
|
||||
rc = qeth_l3_register_addr_entry(card, addr);
|
||||
if (rc && rc != IPA_RC_LAN_OFFLINE) {
|
||||
if (rc && rc != -ENETDOWN) {
|
||||
hash_del(&addr->hnode);
|
||||
kfree(addr);
|
||||
break;
|
||||
|
@ -1509,7 +1524,7 @@ static void qeth_l3_set_rx_mode(struct net_device *dev)
|
|||
qeth_l3_handle_promisc_mode(card);
|
||||
}
|
||||
|
||||
static int qeth_l3_arp_makerc(int rc)
|
||||
static int qeth_l3_arp_makerc(u16 rc)
|
||||
{
|
||||
switch (rc) {
|
||||
case IPA_RC_SUCCESS:
|
||||
|
@ -1526,8 +1541,18 @@ static int qeth_l3_arp_makerc(int rc)
|
|||
}
|
||||
}
|
||||
|
||||
static int qeth_l3_arp_cmd_cb(struct qeth_card *card, struct qeth_reply *reply,
|
||||
unsigned long data)
|
||||
{
|
||||
struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
|
||||
|
||||
qeth_setassparms_cb(card, reply, data);
|
||||
return qeth_l3_arp_makerc(cmd->hdr.return_code);
|
||||
}
|
||||
|
||||
static int qeth_l3_arp_set_no_entries(struct qeth_card *card, int no_entries)
|
||||
{
|
||||
struct qeth_cmd_buffer *iob;
|
||||
int rc;
|
||||
|
||||
QETH_CARD_TEXT(card, 3, "arpstnoe");
|
||||
|
@ -1542,13 +1567,19 @@ static int qeth_l3_arp_set_no_entries(struct qeth_card *card, int no_entries)
|
|||
if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) {
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
rc = qeth_send_simple_setassparms(card, IPA_ARP_PROCESSING,
|
||||
IPA_CMD_ASS_ARP_SET_NO_ENTRIES,
|
||||
no_entries);
|
||||
|
||||
iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
|
||||
IPA_CMD_ASS_ARP_SET_NO_ENTRIES, 4,
|
||||
QETH_PROT_IPV4);
|
||||
if (!iob)
|
||||
return -ENOMEM;
|
||||
|
||||
__ipa_cmd(iob)->data.setassparms.data.flags_32bit = (u32) no_entries;
|
||||
rc = qeth_send_ipa_cmd(card, iob, qeth_l3_arp_cmd_cb, NULL);
|
||||
if (rc)
|
||||
QETH_DBF_MESSAGE(2, "Could not set number of ARP entries on device %x: %#x\n",
|
||||
CARD_DEVID(card), rc);
|
||||
return qeth_l3_arp_makerc(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static __u32 get_arp_entry_size(struct qeth_card *card,
|
||||
|
@ -1599,7 +1630,6 @@ static int qeth_l3_arp_query_cb(struct qeth_card *card,
|
|||
struct qeth_ipa_cmd *cmd;
|
||||
struct qeth_arp_query_data *qdata;
|
||||
struct qeth_arp_query_info *qinfo;
|
||||
int i;
|
||||
int e;
|
||||
int entrybytes_done;
|
||||
int stripped_bytes;
|
||||
|
@ -1613,13 +1643,13 @@ static int qeth_l3_arp_query_cb(struct qeth_card *card,
|
|||
if (cmd->hdr.return_code) {
|
||||
QETH_CARD_TEXT(card, 4, "arpcberr");
|
||||
QETH_CARD_TEXT_(card, 4, "%i", cmd->hdr.return_code);
|
||||
return 0;
|
||||
return qeth_l3_arp_makerc(cmd->hdr.return_code);
|
||||
}
|
||||
if (cmd->data.setassparms.hdr.return_code) {
|
||||
cmd->hdr.return_code = cmd->data.setassparms.hdr.return_code;
|
||||
QETH_CARD_TEXT(card, 4, "setaperr");
|
||||
QETH_CARD_TEXT_(card, 4, "%i", cmd->hdr.return_code);
|
||||
return 0;
|
||||
return qeth_l3_arp_makerc(cmd->hdr.return_code);
|
||||
}
|
||||
qdata = &cmd->data.setassparms.data.query_arp;
|
||||
QETH_CARD_TEXT_(card, 4, "anoen%i", qdata->no_entries);
|
||||
|
@ -1646,9 +1676,9 @@ static int qeth_l3_arp_query_cb(struct qeth_card *card,
|
|||
break;
|
||||
|
||||
if ((qinfo->udata_len - qinfo->udata_offset) < esize) {
|
||||
QETH_CARD_TEXT_(card, 4, "qaer3%i", -ENOMEM);
|
||||
cmd->hdr.return_code = IPA_RC_ENOMEM;
|
||||
goto out_error;
|
||||
QETH_CARD_TEXT_(card, 4, "qaer3%i", -ENOSPC);
|
||||
memset(qinfo->udata, 0, 4);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
memcpy(qinfo->udata + qinfo->udata_offset,
|
||||
|
@ -1671,10 +1701,6 @@ static int qeth_l3_arp_query_cb(struct qeth_card *card,
|
|||
memcpy(qinfo->udata + QETH_QARP_MASK_OFFSET, &qdata->reply_bits, 2);
|
||||
QETH_CARD_TEXT_(card, 4, "rc%i", 0);
|
||||
return 0;
|
||||
out_error:
|
||||
i = 0;
|
||||
memcpy(qinfo->udata, &i, 4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qeth_l3_query_arp_cache_info(struct qeth_card *card,
|
||||
|
@ -1696,13 +1722,11 @@ static int qeth_l3_query_arp_cache_info(struct qeth_card *card,
|
|||
return -ENOMEM;
|
||||
cmd = __ipa_cmd(iob);
|
||||
cmd->data.setassparms.data.query_arp.request_bits = 0x000F;
|
||||
rc = qeth_send_control_data(card,
|
||||
QETH_SETASS_BASE_LEN + QETH_ARP_CMD_LEN,
|
||||
iob, qeth_l3_arp_query_cb, qinfo);
|
||||
rc = qeth_send_ipa_cmd(card, iob, qeth_l3_arp_query_cb, qinfo);
|
||||
if (rc)
|
||||
QETH_DBF_MESSAGE(2, "Error while querying ARP cache on device %x: %#x\n",
|
||||
CARD_DEVID(card), rc);
|
||||
return qeth_l3_arp_makerc(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int qeth_l3_arp_query(struct qeth_card *card, char __user *udata)
|
||||
|
@ -1784,16 +1808,16 @@ static int qeth_l3_arp_modify_entry(struct qeth_card *card,
|
|||
cmd_entry = &__ipa_cmd(iob)->data.setassparms.data.arp_entry;
|
||||
ether_addr_copy(cmd_entry->macaddr, entry->macaddr);
|
||||
memcpy(cmd_entry->ipaddr, entry->ipaddr, 4);
|
||||
rc = qeth_send_ipa_cmd(card, iob, qeth_setassparms_cb, NULL);
|
||||
rc = qeth_send_ipa_cmd(card, iob, qeth_l3_arp_cmd_cb, NULL);
|
||||
if (rc)
|
||||
QETH_DBF_MESSAGE(2, "Could not modify (cmd: %#x) ARP entry on device %x: %#x\n",
|
||||
arp_cmd, CARD_DEVID(card), rc);
|
||||
|
||||
return qeth_l3_arp_makerc(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int qeth_l3_arp_flush_cache(struct qeth_card *card)
|
||||
{
|
||||
struct qeth_cmd_buffer *iob;
|
||||
int rc;
|
||||
|
||||
QETH_CARD_TEXT(card, 3, "arpflush");
|
||||
|
@ -1808,12 +1832,18 @@ static int qeth_l3_arp_flush_cache(struct qeth_card *card)
|
|||
if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) {
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
rc = qeth_send_simple_setassparms(card, IPA_ARP_PROCESSING,
|
||||
IPA_CMD_ASS_ARP_FLUSH_CACHE, 0);
|
||||
|
||||
iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
|
||||
IPA_CMD_ASS_ARP_FLUSH_CACHE, 0,
|
||||
QETH_PROT_IPV4);
|
||||
if (!iob)
|
||||
return -ENOMEM;
|
||||
|
||||
rc = qeth_send_ipa_cmd(card, iob, qeth_l3_arp_cmd_cb, NULL);
|
||||
if (rc)
|
||||
QETH_DBF_MESSAGE(2, "Could not flush ARP cache on device %x: %#x\n",
|
||||
CARD_DEVID(card), rc);
|
||||
return qeth_l3_arp_makerc(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
|
||||
|
|
Загрузка…
Ссылка в новой задаче