aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers/s390/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/net')
-rw-r--r--drivers/s390/net/ism_drv.c2
-rw-r--r--drivers/s390/net/qeth_core.h10
-rw-r--r--drivers/s390/net/qeth_core_main.c269
-rw-r--r--drivers/s390/net/qeth_core_mpc.c16
-rw-r--r--drivers/s390/net/qeth_core_mpc.h17
-rw-r--r--drivers/s390/net/qeth_core_sys.c20
-rw-r--r--drivers/s390/net/qeth_l2_main.c14
-rw-r--r--drivers/s390/net/qeth_l3_main.c20
8 files changed, 169 insertions, 199 deletions
diff --git a/drivers/s390/net/ism_drv.c b/drivers/s390/net/ism_drv.c
index c7fade836d83..5fbe9eae84d1 100644
--- a/drivers/s390/net/ism_drv.c
+++ b/drivers/s390/net/ism_drv.c
@@ -231,7 +231,7 @@ static int ism_alloc_dmb(struct ism_dev *ism, struct smcd_dmb *dmb)
bit = find_next_zero_bit(ism->sba_bitmap, ISM_NR_DMBS,
ISM_DMB_BIT_OFFSET);
if (bit == ISM_NR_DMBS)
- return -ENOMEM;
+ return -ENOSPC;
dmb->sba_idx = bit;
}
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index 51ea56b73a97..ecfd6d152e86 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -721,7 +721,6 @@ struct qeth_card_options {
struct qeth_vnicc_info vnicc; /* VNICC options */
enum qeth_discipline_id layer;
enum qeth_ipa_isolation_modes isolation;
- enum qeth_ipa_isolation_modes prev_isolation;
int sniffer;
enum qeth_cq cq;
char hsuid[9];
@@ -765,6 +764,7 @@ struct qeth_rx {
u8 buf_element;
int e_offset;
int qdio_err;
+ u8 bufs_refill;
};
struct carrier_info {
@@ -804,14 +804,13 @@ struct qeth_card {
struct workqueue_struct *event_wq;
struct workqueue_struct *cmd_wq;
wait_queue_head_t wait_q;
- DECLARE_HASHTABLE(mac_htable, 4);
DECLARE_HASHTABLE(ip_htable, 4);
DECLARE_HASHTABLE(local_addrs4, 4);
DECLARE_HASHTABLE(local_addrs6, 4);
spinlock_t local_addrs4_lock;
spinlock_t local_addrs6_lock;
struct mutex ip_lock;
- DECLARE_HASHTABLE(ip_mc_htable, 4);
+ DECLARE_HASHTABLE(rx_mode_addrs, 4);
struct work_struct rx_mode_work;
struct work_struct kernel_thread_starter;
spinlock_t thread_mask_lock;
@@ -835,7 +834,6 @@ struct qeth_card {
struct napi_struct napi;
struct qeth_rx rx;
struct delayed_work buffer_reclaim_work;
- int reclaim_index;
struct work_struct close_dev_work;
};
@@ -1071,6 +1069,9 @@ int qeth_query_switch_attributes(struct qeth_card *card,
struct qeth_switch_info *sw_info);
int qeth_query_card_info(struct qeth_card *card,
struct carrier_info *carrier_info);
+int qeth_setadpparms_set_access_ctrl(struct qeth_card *card,
+ enum qeth_ipa_isolation_modes mode);
+
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,
@@ -1078,7 +1079,6 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
int elements_needed);
int qeth_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
void qeth_dbf_longtext(debug_info_t *id, int level, char *text, ...);
-int qeth_set_access_ctrl_online(struct qeth_card *card, int fallback);
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 *);
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 88e998de2d03..bba1b54b8aa3 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -204,12 +204,17 @@ EXPORT_SYMBOL_GPL(qeth_threads_running);
void qeth_clear_working_pool_list(struct qeth_card *card)
{
struct qeth_buffer_pool_entry *pool_entry, *tmp;
+ struct qeth_qdio_q *queue = card->qdio.in_q;
+ unsigned int i;
QETH_CARD_TEXT(card, 5, "clwrklst");
list_for_each_entry_safe(pool_entry, tmp,
&card->qdio.in_buf_pool.entry_list, list){
list_del(&pool_entry->list);
}
+
+ for (i = 0; i < ARRAY_SIZE(queue->bufs); i++)
+ queue->bufs[i].pool_entry = NULL;
}
EXPORT_SYMBOL_GPL(qeth_clear_working_pool_list);
@@ -969,7 +974,7 @@ void qeth_clear_ipacmd_list(struct qeth_card *card)
spin_lock_irqsave(&card->lock, flags);
list_for_each_entry(iob, &card->cmd_waiter_list, list)
- qeth_notify_cmd(iob, -EIO);
+ qeth_notify_cmd(iob, -ECANCELED);
spin_unlock_irqrestore(&card->lock, flags);
}
EXPORT_SYMBOL_GPL(qeth_clear_ipacmd_list);
@@ -1647,6 +1652,7 @@ static void qeth_setup_card(struct qeth_card *card)
qeth_init_qdio_info(card);
INIT_DELAYED_WORK(&card->buffer_reclaim_work, qeth_buffer_reclaim_work);
INIT_WORK(&card->close_dev_work, qeth_close_dev_handler);
+ hash_init(card->rx_mode_addrs);
hash_init(card->local_addrs4);
hash_init(card->local_addrs6);
spin_lock_init(&card->local_addrs4_lock);
@@ -2025,7 +2031,7 @@ static bool qeth_mpc_match_reply(struct qeth_cmd_buffer *iob,
}
static struct qeth_cmd_buffer *qeth_mpc_alloc_cmd(struct qeth_card *card,
- void *data,
+ const void *data,
unsigned int data_length)
{
struct qeth_cmd_buffer *iob;
@@ -2436,6 +2442,17 @@ static int qeth_cm_setup(struct qeth_card *card)
return qeth_send_control_data(card, iob, qeth_cm_setup_cb, NULL);
}
+static bool qeth_is_supported_link_type(struct qeth_card *card, u8 link_type)
+{
+ if (link_type == QETH_LINK_TYPE_LANE_TR ||
+ link_type == QETH_LINK_TYPE_HSTR) {
+ dev_err(&card->gdev->dev, "Unsupported Token Ring device\n");
+ return false;
+ }
+
+ return true;
+}
+
static int qeth_update_max_mtu(struct qeth_card *card, unsigned int max_mtu)
{
struct net_device *dev = card->dev;
@@ -2495,8 +2512,8 @@ static int qeth_ulp_enable_cb(struct qeth_card *card, struct qeth_reply *reply,
{
__u16 mtu, framesize;
__u16 len;
- __u8 link_type;
struct qeth_cmd_buffer *iob;
+ u8 link_type = 0;
QETH_CARD_TEXT(card, 2, "ulpenacb");
@@ -2516,9 +2533,11 @@ static int qeth_ulp_enable_cb(struct qeth_card *card, struct qeth_reply *reply,
if (len >= QETH_MPC_DIFINFO_LEN_INDICATES_LINK_TYPE) {
memcpy(&link_type,
QETH_ULP_ENABLE_RESP_LINK_TYPE(iob->data), 1);
- card->info.link_type = link_type;
- } else
- card->info.link_type = 0;
+ if (!qeth_is_supported_link_type(card, link_type))
+ return -EPROTONOSUPPORT;
+ }
+
+ card->info.link_type = link_type;
QETH_CARD_TEXT_(card, 2, "link%d", card->info.link_type);
return 0;
}
@@ -2951,7 +2970,7 @@ static struct qeth_buffer_pool_entry *qeth_find_free_buffer_pool_entry(
static int qeth_init_input_buffer(struct qeth_card *card,
struct qeth_qdio_buffer *buf)
{
- struct qeth_buffer_pool_entry *pool_entry;
+ struct qeth_buffer_pool_entry *pool_entry = buf->pool_entry;
int i;
if ((card->options.cq == QETH_CQ_ENABLED) && (!buf->rx_skb)) {
@@ -2962,9 +2981,13 @@ static int qeth_init_input_buffer(struct qeth_card *card,
return -ENOMEM;
}
- pool_entry = qeth_find_free_buffer_pool_entry(card);
- if (!pool_entry)
- return -ENOBUFS;
+ if (!pool_entry) {
+ pool_entry = qeth_find_free_buffer_pool_entry(card);
+ if (!pool_entry)
+ return -ENOBUFS;
+
+ buf->pool_entry = pool_entry;
+ }
/*
* since the buffer is accessed only from the input_tasklet
@@ -2972,8 +2995,6 @@ static int qeth_init_input_buffer(struct qeth_card *card,
* the QETH_IN_BUF_REQUEUE_THRESHOLD we should never run out off
* buffers
*/
-
- buf->pool_entry = pool_entry;
for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i) {
buf->buffer->element[i].length = PAGE_SIZE;
buf->buffer->element[i].addr =
@@ -3001,6 +3022,7 @@ static unsigned int qeth_tx_select_bulk_max(struct qeth_card *card,
static int qeth_init_qdio_queues(struct qeth_card *card)
{
+ unsigned int rx_bufs = card->qdio.in_buf_pool.buf_count;
unsigned int i;
int rc;
@@ -3012,16 +3034,14 @@ static int qeth_init_qdio_queues(struct qeth_card *card)
qeth_initialize_working_pool_list(card);
/*give only as many buffers to hardware as we have buffer pool entries*/
- for (i = 0; i < card->qdio.in_buf_pool.buf_count - 1; i++) {
+ for (i = 0; i < rx_bufs; i++) {
rc = qeth_init_input_buffer(card, &card->qdio.in_q->bufs[i]);
if (rc)
return rc;
}
- card->qdio.in_q->next_buf_to_init =
- card->qdio.in_buf_pool.buf_count - 1;
- rc = do_QDIO(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT, 0, 0,
- card->qdio.in_buf_pool.buf_count - 1);
+ card->qdio.in_q->next_buf_to_init = QDIO_BUFNR(rx_bufs);
+ rc = do_QDIO(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT, 0, 0, rx_bufs);
if (rc) {
QETH_CARD_TEXT_(card, 2, "1err%d", rc);
return rc;
@@ -3100,7 +3120,6 @@ struct qeth_cmd_buffer *qeth_ipa_alloc_cmd(struct qeth_card *card,
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;
@@ -3116,7 +3135,7 @@ struct qeth_cmd_buffer *qeth_ipa_alloc_cmd(struct qeth_card *card,
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->adapter_type = QETH_LINK_TYPE_FAST_ETH;
hdr->rel_adapter_no = (u8) card->dev->dev_port;
hdr->prim_version_no = IS_LAYER2(card) ? 2 : 1;
hdr->param_count = 1;
@@ -3199,18 +3218,22 @@ static int qeth_query_setadapterparms_cb(struct qeth_card *card,
struct qeth_reply *reply, unsigned long data)
{
struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
+ struct qeth_query_cmds_supp *query_cmd;
QETH_CARD_TEXT(card, 3, "quyadpcb");
if (qeth_setadpparms_inspect_rc(cmd))
return -EIO;
- if (cmd->data.setadapterparms.data.query_cmds_supp.lan_type & 0x7f) {
- card->info.link_type =
- cmd->data.setadapterparms.data.query_cmds_supp.lan_type;
+ query_cmd = &cmd->data.setadapterparms.data.query_cmds_supp;
+ if (query_cmd->lan_type & 0x7f) {
+ if (!qeth_is_supported_link_type(card, query_cmd->lan_type))
+ return -EPROTONOSUPPORT;
+
+ card->info.link_type = query_cmd->lan_type;
QETH_CARD_TEXT_(card, 2, "lnk %d", card->info.link_type);
}
- card->options.adp.supported =
- cmd->data.setadapterparms.data.query_cmds_supp.supported_cmds;
+
+ card->options.adp.supported = query_cmd->supported_cmds;
return 0;
}
@@ -3468,20 +3491,15 @@ static int qeth_check_qdio_errors(struct qeth_card *card,
return 0;
}
-static void qeth_queue_input_buffer(struct qeth_card *card, int index)
+static unsigned int qeth_rx_refill_queue(struct qeth_card *card,
+ unsigned int count)
{
struct qeth_qdio_q *queue = card->qdio.in_q;
struct list_head *lh;
- int count;
int i;
int rc;
int newcount = 0;
- count = (index < queue->next_buf_to_init)?
- card->qdio.in_buf_pool.buf_count -
- (queue->next_buf_to_init - index) :
- card->qdio.in_buf_pool.buf_count -
- (queue->next_buf_to_init + QDIO_MAX_BUFFERS_PER_Q - index);
/* only requeue at a certain threshold to avoid SIGAs */
if (count >= QETH_IN_BUF_REQUEUE_THRESHOLD(card)) {
for (i = queue->next_buf_to_init;
@@ -3509,21 +3527,13 @@ static void qeth_queue_input_buffer(struct qeth_card *card, int index)
i++;
if (i == card->qdio.in_buf_pool.buf_count) {
QETH_CARD_TEXT(card, 2, "qsarbw");
- card->reclaim_index = index;
schedule_delayed_work(
&card->buffer_reclaim_work,
QETH_RECLAIM_WORK_TIME);
}
- return;
+ return 0;
}
- /*
- * according to old code it should be avoided to requeue all
- * 128 buffers in order to benefit from PCI avoidance.
- * this function keeps at least one buffer (the buffer at
- * 'index') un-requeued -> this buffer is the first buffer that
- * will be requeued the next time
- */
rc = do_QDIO(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT, 0,
queue->next_buf_to_init, count);
if (rc) {
@@ -3531,7 +3541,10 @@ static void qeth_queue_input_buffer(struct qeth_card *card, int index)
}
queue->next_buf_to_init = QDIO_BUFNR(queue->next_buf_to_init +
count);
+ return count;
}
+
+ return 0;
}
static void qeth_buffer_reclaim_work(struct work_struct *work)
@@ -3539,8 +3552,10 @@ static void qeth_buffer_reclaim_work(struct work_struct *work)
struct qeth_card *card = container_of(work, struct qeth_card,
buffer_reclaim_work.work);
- QETH_CARD_TEXT_(card, 2, "brw:%x", card->reclaim_index);
- qeth_queue_input_buffer(card, card->reclaim_index);
+ local_bh_disable();
+ napi_schedule(&card->napi);
+ /* kick-start the NAPI softirq: */
+ local_bh_enable();
}
static void qeth_handle_send_error(struct qeth_card *card,
@@ -4541,7 +4556,6 @@ static int qeth_setadpparms_set_access_ctrl_cb(struct qeth_card *card,
{
struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
struct qeth_set_access_ctrl *access_ctrl_req;
- int fallback = *(int *)reply->param;
QETH_CARD_TEXT(card, 4, "setaccb");
@@ -4555,70 +4569,54 @@ static int qeth_setadpparms_set_access_ctrl_cb(struct qeth_card *card,
cmd->data.setadapterparms.hdr.return_code);
switch (qeth_setadpparms_inspect_rc(cmd)) {
case SET_ACCESS_CTRL_RC_SUCCESS:
- if (card->options.isolation == ISOLATION_MODE_NONE) {
+ if (access_ctrl_req->subcmd_code == ISOLATION_MODE_NONE)
dev_info(&card->gdev->dev,
"QDIO data connection isolation is deactivated\n");
- } else {
+ else
dev_info(&card->gdev->dev,
"QDIO data connection isolation is activated\n");
- }
- break;
+ return 0;
case SET_ACCESS_CTRL_RC_ALREADY_NOT_ISOLATED:
QETH_DBF_MESSAGE(2, "QDIO data connection isolation on device %x already deactivated\n",
CARD_DEVID(card));
- if (fallback)
- card->options.isolation = card->options.prev_isolation;
- break;
+ return 0;
case SET_ACCESS_CTRL_RC_ALREADY_ISOLATED:
QETH_DBF_MESSAGE(2, "QDIO data connection isolation on device %x already activated\n",
CARD_DEVID(card));
- if (fallback)
- card->options.isolation = card->options.prev_isolation;
- break;
+ return 0;
case SET_ACCESS_CTRL_RC_NOT_SUPPORTED:
dev_err(&card->gdev->dev, "Adapter does not "
"support QDIO data connection isolation\n");
- break;
+ return -EOPNOTSUPP;
case SET_ACCESS_CTRL_RC_NONE_SHARED_ADAPTER:
dev_err(&card->gdev->dev,
"Adapter is dedicated. "
"QDIO data connection isolation not supported\n");
- if (fallback)
- card->options.isolation = card->options.prev_isolation;
- break;
+ return -EOPNOTSUPP;
case SET_ACCESS_CTRL_RC_ACTIVE_CHECKSUM_OFF:
dev_err(&card->gdev->dev,
"TSO does not permit QDIO data connection isolation\n");
- if (fallback)
- card->options.isolation = card->options.prev_isolation;
- break;
+ return -EPERM;
case SET_ACCESS_CTRL_RC_REFLREL_UNSUPPORTED:
dev_err(&card->gdev->dev, "The adjacent switch port does not "
"support reflective relay mode\n");
- if (fallback)
- card->options.isolation = card->options.prev_isolation;
- break;
+ return -EOPNOTSUPP;
case SET_ACCESS_CTRL_RC_REFLREL_FAILED:
dev_err(&card->gdev->dev, "The reflective relay mode cannot be "
"enabled at the adjacent switch port");
- if (fallback)
- card->options.isolation = card->options.prev_isolation;
- break;
+ return -EREMOTEIO;
case SET_ACCESS_CTRL_RC_REFLREL_DEACT_FAILED:
dev_warn(&card->gdev->dev, "Turning off reflective relay mode "
"at the adjacent switch failed\n");
- break;
+ /* benign error while disabling ISOLATION_MODE_FWD */
+ return 0;
default:
- /* this should never happen */
- if (fallback)
- card->options.isolation = card->options.prev_isolation;
- break;
+ return -EIO;
}
- return (cmd->hdr.return_code) ? -EIO : 0;
}
-static int qeth_setadpparms_set_access_ctrl(struct qeth_card *card,
- enum qeth_ipa_isolation_modes isolation, int fallback)
+int qeth_setadpparms_set_access_ctrl(struct qeth_card *card,
+ enum qeth_ipa_isolation_modes mode)
{
int rc;
struct qeth_cmd_buffer *iob;
@@ -4627,42 +4625,28 @@ static int qeth_setadpparms_set_access_ctrl(struct qeth_card *card,
QETH_CARD_TEXT(card, 4, "setacctl");
+ if (!qeth_adp_supported(card, IPA_SETADP_SET_ACCESS_CONTROL)) {
+ dev_err(&card->gdev->dev,
+ "Adapter does not support QDIO data connection isolation\n");
+ return -EOPNOTSUPP;
+ }
+
iob = qeth_get_adapter_cmd(card, IPA_SETADP_SET_ACCESS_CONTROL,
SETADP_DATA_SIZEOF(set_access_ctrl));
if (!iob)
return -ENOMEM;
cmd = __ipa_cmd(iob);
access_ctrl_req = &cmd->data.setadapterparms.data.set_access_ctrl;
- access_ctrl_req->subcmd_code = isolation;
+ access_ctrl_req->subcmd_code = mode;
rc = qeth_send_ipa_cmd(card, iob, qeth_setadpparms_set_access_ctrl_cb,
- &fallback);
- QETH_CARD_TEXT_(card, 2, "rc=%d", rc);
- return rc;
-}
-
-int qeth_set_access_ctrl_online(struct qeth_card *card, int fallback)
-{
- int rc = 0;
-
- QETH_CARD_TEXT(card, 4, "setactlo");
-
- if ((IS_OSD(card) || IS_OSX(card)) &&
- qeth_adp_supported(card, IPA_SETADP_SET_ACCESS_CONTROL)) {
- rc = qeth_setadpparms_set_access_ctrl(card,
- card->options.isolation, fallback);
- if (rc) {
- QETH_DBF_MESSAGE(3, "IPA(SET_ACCESS_CTRL(%d) on device %x: sent failed\n",
- rc, CARD_DEVID(card));
- rc = -EOPNOTSUPP;
- }
- } else if (card->options.isolation != ISOLATION_MODE_NONE) {
- card->options.isolation = ISOLATION_MODE_NONE;
-
- dev_err(&card->gdev->dev, "Adapter does not "
- "support QDIO data connection isolation\n");
- rc = -EOPNOTSUPP;
+ NULL);
+ if (rc) {
+ QETH_CARD_TEXT_(card, 2, "rc=%d", rc);
+ QETH_DBF_MESSAGE(3, "IPA(SET_ACCESS_CTRL(%d) on device %x: sent failed\n",
+ rc, CARD_DEVID(card));
}
+
return rc;
}
@@ -4850,26 +4834,24 @@ static int qeth_snmp_command(struct qeth_card *card, char __user *udata)
}
static int qeth_setadpparms_query_oat_cb(struct qeth_card *card,
- struct qeth_reply *reply, unsigned long data)
+ struct qeth_reply *reply,
+ unsigned long data)
{
struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *)data;
- struct qeth_qoat_priv *priv;
- char *resdata;
+ struct qeth_qoat_priv *priv = reply->param;
int resdatalen;
QETH_CARD_TEXT(card, 3, "qoatcb");
if (qeth_setadpparms_inspect_rc(cmd))
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))
return -ENOSPC;
- memcpy((priv->buffer + priv->response_len), resdata,
- resdatalen);
+ memcpy(priv->buffer + priv->response_len,
+ &cmd->data.setadapterparms.hdr, resdatalen);
priv->response_len += resdatalen;
if (cmd->data.setadapterparms.hdr.seq_no <
@@ -4890,24 +4872,17 @@ static int qeth_query_oat_command(struct qeth_card *card, char __user *udata)
QETH_CARD_TEXT(card, 3, "qoatcmd");
- if (!qeth_adp_supported(card, IPA_SETADP_QUERY_OAT)) {
- rc = -EOPNOTSUPP;
- goto out;
- }
+ if (!qeth_adp_supported(card, IPA_SETADP_QUERY_OAT))
+ return -EOPNOTSUPP;
- if (copy_from_user(&oat_data, udata,
- sizeof(struct qeth_query_oat_data))) {
- rc = -EFAULT;
- goto out;
- }
+ if (copy_from_user(&oat_data, udata, sizeof(oat_data)))
+ return -EFAULT;
priv.buffer_len = oat_data.buffer_len;
priv.response_len = 0;
priv.buffer = vzalloc(oat_data.buffer_len);
- if (!priv.buffer) {
- rc = -ENOMEM;
- goto out;
- }
+ if (!priv.buffer)
+ return -ENOMEM;
iob = qeth_get_adapter_cmd(card, IPA_SETADP_QUERY_OAT,
SETADP_DATA_SIZEOF(query_oat));
@@ -4919,30 +4894,19 @@ static int qeth_query_oat_command(struct qeth_card *card, char __user *udata)
oat_req = &cmd->data.setadapterparms.data.query_oat;
oat_req->subcmd_code = oat_data.command;
- rc = qeth_send_ipa_cmd(card, iob, qeth_setadpparms_query_oat_cb,
- &priv);
+ rc = qeth_send_ipa_cmd(card, iob, qeth_setadpparms_query_oat_cb, &priv);
if (!rc) {
- if (is_compat_task())
- tmp = compat_ptr(oat_data.ptr);
- else
- tmp = (void __user *)(unsigned long)oat_data.ptr;
-
- if (copy_to_user(tmp, priv.buffer,
- priv.response_len)) {
- rc = -EFAULT;
- goto out_free;
- }
-
+ tmp = is_compat_task() ? compat_ptr(oat_data.ptr) :
+ u64_to_user_ptr(oat_data.ptr);
oat_data.response_len = priv.response_len;
- if (copy_to_user(udata, &oat_data,
- sizeof(struct qeth_query_oat_data)))
+ if (copy_to_user(tmp, priv.buffer, priv.response_len) ||
+ copy_to_user(udata, &oat_data, sizeof(oat_data)))
rc = -EFAULT;
}
out_free:
vfree(priv.buffer);
-out:
return rc;
}
@@ -5331,9 +5295,12 @@ retriable:
(card->info.hwtrap && qeth_hw_trap(card, QETH_DIAGS_TRAP_ARM)))
card->info.hwtrap = 0;
- rc = qeth_set_access_ctrl_online(card, 0);
- if (rc)
- goto out;
+ if (card->options.isolation != ISOLATION_MODE_NONE) {
+ rc = qeth_setadpparms_set_access_ctrl(card,
+ card->options.isolation);
+ if (rc)
+ goto out;
+ }
rc = qeth_init_qdio_queues(card);
if (rc) {
@@ -5767,6 +5734,7 @@ static unsigned int qeth_extract_skbs(struct qeth_card *card, int budget,
static unsigned int qeth_rx_poll(struct qeth_card *card, int budget)
{
+ struct qeth_rx *ctx = &card->rx;
unsigned int work_done = 0;
while (budget > 0) {
@@ -5802,8 +5770,11 @@ static unsigned int qeth_rx_poll(struct qeth_card *card, int budget)
if (done) {
QETH_CARD_STAT_INC(card, rx_bufs);
qeth_put_buffer_pool_entry(card, buffer->pool_entry);
- qeth_queue_input_buffer(card, card->rx.b_index);
+ buffer->pool_entry = NULL;
card->rx.b_count--;
+ ctx->bufs_refill++;
+ ctx->bufs_refill -= qeth_rx_refill_queue(card,
+ ctx->bufs_refill);
/* Step forward to next buffer: */
card->rx.b_index = QDIO_BUFNR(card->rx.b_index + 1);
@@ -5843,9 +5814,16 @@ int qeth_poll(struct napi_struct *napi, int budget)
if (card->options.cq == QETH_CQ_ENABLED)
qeth_cq_poll(card);
- /* Exhausted the RX budget. Keep IRQ disabled, we get called again. */
- if (budget && work_done >= budget)
- return work_done;
+ if (budget) {
+ struct qeth_rx *ctx = &card->rx;
+
+ /* Process any substantial refill backlog: */
+ ctx->bufs_refill -= qeth_rx_refill_queue(card, ctx->bufs_refill);
+
+ /* Exhausted the RX budget. Keep IRQ disabled, we get called again. */
+ if (work_done >= budget)
+ return work_done;
+ }
if (napi_complete_done(napi, work_done) &&
qdio_start_irq(CARD_DDEV(card)))
@@ -6841,7 +6819,7 @@ netdev_features_t qeth_features_check(struct sk_buff *skb,
/* Traffic with local next-hop is not eligible for some offloads: */
if (skb->ip_summed == CHECKSUM_PARTIAL &&
- card->options.isolation != ISOLATION_MODE_FWD) {
+ READ_ONCE(card->options.isolation) != ISOLATION_MODE_FWD) {
netdev_features_t restricted = 0;
if (skb_is_gso(skb) && !netif_needs_gso(skb, features))
@@ -7032,6 +7010,7 @@ int qeth_stop(struct net_device *dev)
}
napi_disable(&card->napi);
+ cancel_delayed_work_sync(&card->buffer_reclaim_work);
qdio_stop_irq(CARD_DDEV(card));
return 0;
diff --git a/drivers/s390/net/qeth_core_mpc.c b/drivers/s390/net/qeth_core_mpc.c
index e3f4866c158e..68c2588b9dcc 100644
--- a/drivers/s390/net/qeth_core_mpc.c
+++ b/drivers/s390/net/qeth_core_mpc.c
@@ -10,7 +10,7 @@
#include <asm/cio.h>
#include "qeth_core_mpc.h"
-unsigned char IDX_ACTIVATE_READ[] = {
+const unsigned char IDX_ACTIVATE_READ[] = {
0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
0x19, 0x01, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc1,
@@ -18,7 +18,7 @@ unsigned char IDX_ACTIVATE_READ[] = {
0x00, 0x00
};
-unsigned char IDX_ACTIVATE_WRITE[] = {
+const unsigned char IDX_ACTIVATE_WRITE[] = {
0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
0x15, 0x01, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc1,
@@ -26,7 +26,7 @@ unsigned char IDX_ACTIVATE_WRITE[] = {
0x00, 0x00
};
-unsigned char CM_ENABLE[] = {
+const unsigned char CM_ENABLE[] = {
0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x63,
0x10, 0x00, 0x00, 0x01,
@@ -45,7 +45,7 @@ unsigned char CM_ENABLE[] = {
0xff, 0xff, 0xff
};
-unsigned char CM_SETUP[] = {
+const unsigned char CM_SETUP[] = {
0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x64,
0x10, 0x00, 0x00, 0x01,
@@ -65,7 +65,7 @@ unsigned char CM_SETUP[] = {
0x04, 0x06, 0xc8, 0x00
};
-unsigned char ULP_ENABLE[] = {
+const unsigned char ULP_ENABLE[] = {
0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x6b,
0x10, 0x00, 0x00, 0x01,
@@ -85,7 +85,7 @@ unsigned char ULP_ENABLE[] = {
0xf1, 0x00, 0x00
};
-unsigned char ULP_SETUP[] = {
+const unsigned char ULP_SETUP[] = {
0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x6c,
0x10, 0x00, 0x00, 0x01,
@@ -107,7 +107,7 @@ unsigned char ULP_SETUP[] = {
0x00, 0x00, 0x00, 0x00
};
-unsigned char DM_ACT[] = {
+const unsigned char DM_ACT[] = {
0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x55,
0x10, 0x00, 0x00, 0x01,
@@ -123,7 +123,7 @@ unsigned char DM_ACT[] = {
0x05, 0x40, 0x01, 0x01, 0x00
};
-unsigned char IPA_PDU_HEADER[] = {
+const unsigned char IPA_PDU_HEADER[] = {
0x00, 0xe0, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77,
0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
diff --git a/drivers/s390/net/qeth_core_mpc.h b/drivers/s390/net/qeth_core_mpc.h
index 9d6f39d8f9ab..b459def0fb26 100644
--- a/drivers/s390/net/qeth_core_mpc.h
+++ b/drivers/s390/net/qeth_core_mpc.h
@@ -13,13 +13,13 @@
#include <uapi/linux/if_ether.h>
#include <uapi/linux/in6.h>
+extern const unsigned char IPA_PDU_HEADER[];
#define IPA_PDU_HEADER_SIZE 0x40
#define QETH_IPA_PDU_LEN_TOTAL(buffer) (buffer + 0x0e)
#define QETH_IPA_PDU_LEN_PDU1(buffer) (buffer + 0x26)
#define QETH_IPA_PDU_LEN_PDU2(buffer) (buffer + 0x29)
#define QETH_IPA_PDU_LEN_PDU3(buffer) (buffer + 0x3a)
-extern unsigned char IPA_PDU_HEADER[];
#define QETH_IPA_CMD_DEST_ADDR(buffer) (buffer + 0x2c)
#define QETH_SEQ_NO_LENGTH 4
@@ -858,7 +858,7 @@ extern const char *qeth_get_ipa_cmd_name(enum qeth_ipa_cmds cmd);
/* END OF IP Assist related definitions */
/*****************************************************************************/
-extern unsigned char CM_ENABLE[];
+extern const unsigned char CM_ENABLE[];
#define CM_ENABLE_SIZE 0x63
#define QETH_CM_ENABLE_ISSUER_RM_TOKEN(buffer) (buffer + 0x2c)
#define QETH_CM_ENABLE_FILTER_TOKEN(buffer) (buffer + 0x53)
@@ -868,7 +868,7 @@ extern unsigned char CM_ENABLE[];
(PDU_ENCAPSULATION(buffer) + 0x13)
-extern unsigned char CM_SETUP[];
+extern const unsigned char CM_SETUP[];
#define CM_SETUP_SIZE 0x64
#define QETH_CM_SETUP_DEST_ADDR(buffer) (buffer + 0x2c)
#define QETH_CM_SETUP_CONNECTION_TOKEN(buffer) (buffer + 0x51)
@@ -877,7 +877,7 @@ extern unsigned char CM_SETUP[];
#define QETH_CM_SETUP_RESP_DEST_ADDR(buffer) \
(PDU_ENCAPSULATION(buffer) + 0x1a)
-extern unsigned char ULP_ENABLE[];
+extern const unsigned char ULP_ENABLE[];
#define ULP_ENABLE_SIZE 0x6b
#define QETH_ULP_ENABLE_LINKNUM(buffer) (buffer + 0x61)
#define QETH_ULP_ENABLE_DEST_ADDR(buffer) (buffer + 0x2c)
@@ -898,7 +898,7 @@ extern unsigned char ULP_ENABLE[];
#define QETH_ULP_ENABLE_PROT_TYPE(buffer) (buffer + 0x50)
#define QETH_IPA_CMD_PROT_TYPE(buffer) (buffer + 0x19)
-extern unsigned char ULP_SETUP[];
+extern const unsigned char ULP_SETUP[];
#define ULP_SETUP_SIZE 0x6c
#define QETH_ULP_SETUP_DEST_ADDR(buffer) (buffer + 0x2c)
#define QETH_ULP_SETUP_CONNECTION_TOKEN(buffer) (buffer + 0x51)
@@ -910,7 +910,7 @@ extern unsigned char ULP_SETUP[];
(PDU_ENCAPSULATION(buffer) + 0x1a)
-extern unsigned char DM_ACT[];
+extern const unsigned char DM_ACT[];
#define DM_ACT_SIZE 0x55
#define QETH_DM_ACT_DEST_ADDR(buffer) (buffer + 0x2c)
#define QETH_DM_ACT_CONNECTION_TOKEN(buffer) (buffer + 0x51)
@@ -921,9 +921,8 @@ extern unsigned char DM_ACT[];
#define QETH_PDU_HEADER_SEQ_NO(buffer) (buffer + 0x1c)
#define QETH_PDU_HEADER_ACK_SEQ_NO(buffer) (buffer + 0x20)
-extern unsigned char IDX_ACTIVATE_READ[];
-extern unsigned char IDX_ACTIVATE_WRITE[];
-
+extern const unsigned char IDX_ACTIVATE_READ[];
+extern const unsigned char IDX_ACTIVATE_WRITE[];
#define IDX_ACTIVATE_SIZE 0x22
#define QETH_IDX_ACT_PNO(buffer) (buffer+0x0b)
#define QETH_IDX_ACT_ISSUER_RM_TOKEN(buffer) (buffer + 0x0c)
diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c
index c901c942fed7..8def82336f53 100644
--- a/drivers/s390/net/qeth_core_sys.c
+++ b/drivers/s390/net/qeth_core_sys.c
@@ -448,19 +448,17 @@ static ssize_t qeth_dev_isolation_store(struct device *dev,
rc = -EINVAL;
goto out;
}
- rc = count;
-
- /* defer IP assist if device is offline (until discipline->set_online)*/
- card->options.prev_isolation = card->options.isolation;
- card->options.isolation = isolation;
- if (qeth_card_hw_is_reachable(card)) {
- int ipa_rc = qeth_set_access_ctrl_online(card, 1);
- if (ipa_rc != 0)
- rc = ipa_rc;
- }
+
+ if (qeth_card_hw_is_reachable(card))
+ rc = qeth_setadpparms_set_access_ctrl(card, isolation);
+
+ if (!rc)
+ WRITE_ONCE(card->options.isolation, isolation);
+
out:
mutex_unlock(&card->conf_mutex);
- return rc;
+
+ return rc ? rc : count;
}
static DEVICE_ATTR(isolation, 0644, qeth_dev_isolation_show,
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index 2d3bca3c0141..8b342a88ff5c 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -156,7 +156,7 @@ static void qeth_l2_drain_rx_mode_cache(struct qeth_card *card)
struct hlist_node *tmp;
int i;
- hash_for_each_safe(card->mac_htable, i, tmp, mac, hnode) {
+ hash_for_each_safe(card->rx_mode_addrs, i, tmp, mac, hnode) {
hash_del(&mac->hnode);
kfree(mac);
}
@@ -285,7 +285,6 @@ static void qeth_l2_stop_card(struct qeth_card *card)
if (card->state == CARD_STATE_SOFTSETUP) {
qeth_clear_ipacmd_list(card);
qeth_drain_output_queues(card);
- cancel_delayed_work_sync(&card->buffer_reclaim_work);
card->state = CARD_STATE_DOWN;
}
@@ -438,7 +437,7 @@ static void qeth_l2_add_mac(struct qeth_card *card, struct netdev_hw_addr *ha)
u32 mac_hash = get_unaligned((u32 *)(&ha->addr[2]));
struct qeth_mac *mac;
- hash_for_each_possible(card->mac_htable, mac, hnode, mac_hash) {
+ hash_for_each_possible(card->rx_mode_addrs, mac, hnode, mac_hash) {
if (ether_addr_equal_64bits(ha->addr, mac->mac_addr)) {
mac->disp_flag = QETH_DISP_ADDR_DO_NOTHING;
return;
@@ -452,7 +451,7 @@ static void qeth_l2_add_mac(struct qeth_card *card, struct netdev_hw_addr *ha)
ether_addr_copy(mac->mac_addr, ha->addr);
mac->disp_flag = QETH_DISP_ADDR_ADD;
- hash_add(card->mac_htable, &mac->hnode, mac_hash);
+ hash_add(card->rx_mode_addrs, &mac->hnode, mac_hash);
}
static void qeth_l2_rx_mode_work(struct work_struct *work)
@@ -475,7 +474,7 @@ static void qeth_l2_rx_mode_work(struct work_struct *work)
qeth_l2_add_mac(card, ha);
netif_addr_unlock_bh(dev);
- hash_for_each_safe(card->mac_htable, i, tmp, mac, hnode) {
+ hash_for_each_safe(card->rx_mode_addrs, i, tmp, mac, hnode) {
switch (mac->disp_flag) {
case QETH_DISP_ADDR_DELETE:
qeth_l2_remove_mac(card, mac->mac_addr);
@@ -601,7 +600,6 @@ static int qeth_l2_probe_device(struct ccwgroup_device *gdev)
return rc;
}
- hash_init(card->mac_htable);
INIT_WORK(&card->rx_mode_work, qeth_l2_rx_mode_work);
return 0;
}
@@ -1142,6 +1140,10 @@ static void qeth_bridge_state_change(struct qeth_card *card,
int extrasize;
QETH_CARD_TEXT(card, 2, "brstchng");
+ if (qports->num_entries == 0) {
+ QETH_CARD_TEXT(card, 2, "BPempty");
+ return;
+ }
if (qports->entry_length != sizeof(struct qeth_sbp_port_entry)) {
QETH_CARD_TEXT_(card, 2, "BPsz%04x", qports->entry_length);
return;
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index 1e50aa0297a3..fe44b0249e34 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -58,7 +58,7 @@ static struct qeth_ipaddr *qeth_l3_find_addr_by_ip(struct qeth_card *card,
struct qeth_ipaddr *addr;
if (query->is_multicast) {
- hash_for_each_possible(card->ip_mc_htable, addr, hnode, key)
+ hash_for_each_possible(card->rx_mode_addrs, addr, hnode, key)
if (qeth_l3_addr_match_ip(addr, query))
return addr;
} else {
@@ -239,7 +239,7 @@ static void qeth_l3_drain_rx_mode_cache(struct qeth_card *card)
struct hlist_node *tmp;
int i;
- hash_for_each_safe(card->ip_mc_htable, i, tmp, addr, hnode) {
+ hash_for_each_safe(card->rx_mode_addrs, i, tmp, addr, hnode) {
hash_del(&addr->hnode);
kfree(addr);
}
@@ -1093,7 +1093,7 @@ static int qeth_l3_add_mcast_rtnl(struct net_device *dev, int vid, void *arg)
if (!ipm)
continue;
- hash_add(card->ip_mc_htable, &ipm->hnode,
+ hash_add(card->rx_mode_addrs, &ipm->hnode,
qeth_l3_ipaddr_hash(ipm));
}
@@ -1124,8 +1124,8 @@ walk_ipv6:
if (!ipm)
continue;
- hash_add(card->ip_mc_htable,
- &ipm->hnode, qeth_l3_ipaddr_hash(ipm));
+ hash_add(card->rx_mode_addrs, &ipm->hnode,
+ qeth_l3_ipaddr_hash(ipm));
}
read_unlock_bh(&in6_dev->lock);
@@ -1169,7 +1169,6 @@ static void qeth_l3_stop_card(struct qeth_card *card)
qeth_l3_clear_ip_htable(card, 1);
qeth_clear_ipacmd_list(card);
qeth_drain_output_queues(card);
- cancel_delayed_work_sync(&card->buffer_reclaim_work);
card->state = CARD_STATE_DOWN;
}
@@ -1219,7 +1218,7 @@ static void qeth_l3_rx_mode_work(struct work_struct *work)
vlan_for_each(card->dev, qeth_l3_add_mcast_rtnl, card);
rtnl_unlock();
- hash_for_each_safe(card->ip_mc_htable, i, tmp, addr, hnode) {
+ hash_for_each_safe(card->rx_mode_addrs, i, tmp, addr, hnode) {
switch (addr->disp_flag) {
case QETH_DISP_ADDR_DELETE:
rc = qeth_l3_deregister_addr_entry(card, addr);
@@ -1919,12 +1918,6 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
return rc;
if (IS_OSD(card) || IS_OSX(card)) {
- if ((card->info.link_type == QETH_LINK_TYPE_LANE_TR) ||
- (card->info.link_type == QETH_LINK_TYPE_HSTR)) {
- pr_info("qeth_l3: ignoring TR device\n");
- return -ENODEV;
- }
-
card->dev->netdev_ops = &qeth_l3_osa_netdev_ops;
/*IPv6 address autoconfiguration stuff*/
@@ -2004,7 +1997,6 @@ static int qeth_l3_probe_device(struct ccwgroup_device *gdev)
}
}
- hash_init(card->ip_mc_htable);
INIT_WORK(&card->rx_mode_work, qeth_l3_rx_mode_work);
return 0;
}