Commit 72919b6b authored by David S. Miller's avatar David S. Miller

Merge branch 's390-next'

Julian Wiedmann says:

====================
s390/qeth: updates 2019-10-31

please apply the following series of spooky qeth updates for net-next.

The first two patches add support for an enhanced TX doorbell, which
enables us to do more xmit_more-based bulking.
Note that this requires one patch for the s390/qdio base layer, which
has been graciously acked by Heiko to go through your tree.

The remaining patches are just the usual minor cleanups/improvements.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 4a956bd2 8bf70b68
...@@ -82,6 +82,7 @@ enum qdio_irq_states { ...@@ -82,6 +82,7 @@ enum qdio_irq_states {
#define QDIO_SIGA_WRITE 0x00 #define QDIO_SIGA_WRITE 0x00
#define QDIO_SIGA_READ 0x01 #define QDIO_SIGA_READ 0x01
#define QDIO_SIGA_SYNC 0x02 #define QDIO_SIGA_SYNC 0x02
#define QDIO_SIGA_WRITEM 0x03
#define QDIO_SIGA_WRITEQ 0x04 #define QDIO_SIGA_WRITEQ 0x04
#define QDIO_SIGA_QEBSM_FLAG 0x80 #define QDIO_SIGA_QEBSM_FLAG 0x80
......
...@@ -310,18 +310,19 @@ static inline int qdio_siga_sync_q(struct qdio_q *q) ...@@ -310,18 +310,19 @@ static inline int qdio_siga_sync_q(struct qdio_q *q)
return qdio_siga_sync(q, q->mask, 0); return qdio_siga_sync(q, q->mask, 0);
} }
static int qdio_siga_output(struct qdio_q *q, unsigned int *busy_bit, static int qdio_siga_output(struct qdio_q *q, unsigned int count,
unsigned long aob) unsigned int *busy_bit, unsigned long aob)
{ {
unsigned long schid = *((u32 *) &q->irq_ptr->schid); unsigned long schid = *((u32 *) &q->irq_ptr->schid);
unsigned int fc = QDIO_SIGA_WRITE; unsigned int fc = QDIO_SIGA_WRITE;
u64 start_time = 0; u64 start_time = 0;
int retries = 0, cc; int retries = 0, cc;
unsigned long laob = 0;
if (aob) { if (queue_type(q) == QDIO_IQDIO_QFMT && !multicast_outbound(q)) {
if (count > 1)
fc = QDIO_SIGA_WRITEM;
else if (aob)
fc = QDIO_SIGA_WRITEQ; fc = QDIO_SIGA_WRITEQ;
laob = aob;
} }
if (is_qebsm(q)) { if (is_qebsm(q)) {
...@@ -329,7 +330,7 @@ static int qdio_siga_output(struct qdio_q *q, unsigned int *busy_bit, ...@@ -329,7 +330,7 @@ static int qdio_siga_output(struct qdio_q *q, unsigned int *busy_bit,
fc |= QDIO_SIGA_QEBSM_FLAG; fc |= QDIO_SIGA_QEBSM_FLAG;
} }
again: again:
cc = do_siga_output(schid, q->mask, busy_bit, fc, laob); cc = do_siga_output(schid, q->mask, busy_bit, fc, aob);
/* hipersocket busy condition */ /* hipersocket busy condition */
if (unlikely(*busy_bit)) { if (unlikely(*busy_bit)) {
...@@ -781,7 +782,8 @@ static inline int qdio_outbound_q_moved(struct qdio_q *q, unsigned int start) ...@@ -781,7 +782,8 @@ static inline int qdio_outbound_q_moved(struct qdio_q *q, unsigned int start)
return count; return count;
} }
static int qdio_kick_outbound_q(struct qdio_q *q, unsigned long aob) static int qdio_kick_outbound_q(struct qdio_q *q, unsigned int count,
unsigned long aob)
{ {
int retries = 0, cc; int retries = 0, cc;
unsigned int busy_bit; unsigned int busy_bit;
...@@ -793,7 +795,7 @@ static int qdio_kick_outbound_q(struct qdio_q *q, unsigned long aob) ...@@ -793,7 +795,7 @@ static int qdio_kick_outbound_q(struct qdio_q *q, unsigned long aob)
retry: retry:
qperf_inc(q, siga_write); qperf_inc(q, siga_write);
cc = qdio_siga_output(q, &busy_bit, aob); cc = qdio_siga_output(q, count, &busy_bit, aob);
switch (cc) { switch (cc) {
case 0: case 0:
break; break;
...@@ -1526,7 +1528,7 @@ static int handle_inbound(struct qdio_q *q, unsigned int callflags, ...@@ -1526,7 +1528,7 @@ static int handle_inbound(struct qdio_q *q, unsigned int callflags,
* @count: how many buffers are filled * @count: how many buffers are filled
*/ */
static int handle_outbound(struct qdio_q *q, unsigned int callflags, static int handle_outbound(struct qdio_q *q, unsigned int callflags,
int bufnr, int count) unsigned int bufnr, unsigned int count)
{ {
const unsigned int scan_threshold = q->irq_ptr->scan_threshold; const unsigned int scan_threshold = q->irq_ptr->scan_threshold;
unsigned char state = 0; unsigned char state = 0;
...@@ -1549,13 +1551,10 @@ static int handle_outbound(struct qdio_q *q, unsigned int callflags, ...@@ -1549,13 +1551,10 @@ static int handle_outbound(struct qdio_q *q, unsigned int callflags,
if (queue_type(q) == QDIO_IQDIO_QFMT) { if (queue_type(q) == QDIO_IQDIO_QFMT) {
unsigned long phys_aob = 0; unsigned long phys_aob = 0;
/* One SIGA-W per buffer required for unicast HSI */ if (q->u.out.use_cq && count == 1)
WARN_ON_ONCE(count > 1 && !multicast_outbound(q));
if (q->u.out.use_cq)
phys_aob = qdio_aob_for_buffer(&q->u.out, bufnr); phys_aob = qdio_aob_for_buffer(&q->u.out, bufnr);
rc = qdio_kick_outbound_q(q, phys_aob); rc = qdio_kick_outbound_q(q, count, phys_aob);
} else if (need_siga_sync(q)) { } else if (need_siga_sync(q)) {
rc = qdio_siga_sync_q(q); rc = qdio_siga_sync_q(q);
} else if (count < QDIO_MAX_BUFFERS_PER_Q && } else if (count < QDIO_MAX_BUFFERS_PER_Q &&
...@@ -1564,7 +1563,7 @@ static int handle_outbound(struct qdio_q *q, unsigned int callflags, ...@@ -1564,7 +1563,7 @@ static int handle_outbound(struct qdio_q *q, unsigned int callflags,
/* The previous buffer is not processed yet, tack on. */ /* The previous buffer is not processed yet, tack on. */
qperf_inc(q, fast_requeue); qperf_inc(q, fast_requeue);
} else { } else {
rc = qdio_kick_outbound_q(q, 0); rc = qdio_kick_outbound_q(q, count, 0);
} }
/* Let drivers implement their own completion scanning: */ /* Let drivers implement their own completion scanning: */
......
...@@ -532,6 +532,8 @@ struct qeth_qdio_out_q { ...@@ -532,6 +532,8 @@ struct qeth_qdio_out_q {
struct timer_list timer; struct timer_list timer;
struct qeth_hdr *prev_hdr; struct qeth_hdr *prev_hdr;
u8 bulk_start; u8 bulk_start;
u8 bulk_count;
u8 bulk_max;
}; };
#define qeth_for_each_output_queue(card, q, i) \ #define qeth_for_each_output_queue(card, q, i) \
...@@ -878,6 +880,13 @@ static inline u16 qeth_iqd_translate_txq(struct net_device *dev, u16 txq) ...@@ -878,6 +880,13 @@ static inline u16 qeth_iqd_translate_txq(struct net_device *dev, u16 txq)
return txq; return txq;
} }
static inline bool qeth_iqd_is_mcast_queue(struct qeth_card *card,
struct qeth_qdio_out_q *queue)
{
return qeth_iqd_translate_txq(card->dev, queue->queue_no) ==
QETH_IQD_MCAST_TXQ;
}
static inline void qeth_scrub_qdio_buffer(struct qdio_buffer *buf, static inline void qeth_scrub_qdio_buffer(struct qdio_buffer *buf,
unsigned int elements) unsigned int elements)
{ {
......
...@@ -1513,7 +1513,6 @@ int qeth_qdio_clear_card(struct qeth_card *card, int use_halt) ...@@ -1513,7 +1513,6 @@ int qeth_qdio_clear_card(struct qeth_card *card, int use_halt)
rc = qeth_clear_halt_card(card, use_halt); rc = qeth_clear_halt_card(card, use_halt);
if (rc) if (rc)
QETH_CARD_TEXT_(card, 3, "2err%d", rc); QETH_CARD_TEXT_(card, 3, "2err%d", rc);
card->state = CARD_STATE_DOWN;
return rc; return rc;
} }
EXPORT_SYMBOL_GPL(qeth_qdio_clear_card); EXPORT_SYMBOL_GPL(qeth_qdio_clear_card);
...@@ -2634,6 +2633,18 @@ static int qeth_init_input_buffer(struct qeth_card *card, ...@@ -2634,6 +2633,18 @@ static int qeth_init_input_buffer(struct qeth_card *card,
return 0; return 0;
} }
static unsigned int qeth_tx_select_bulk_max(struct qeth_card *card,
struct qeth_qdio_out_q *queue)
{
if (!IS_IQD(card) ||
qeth_iqd_is_mcast_queue(card, queue) ||
card->options.cq == QETH_CQ_ENABLED ||
qdio_get_ssqd_desc(CARD_DDEV(card), &card->ssqd))
return 1;
return card->ssqd.mmwc ? card->ssqd.mmwc : 1;
}
int qeth_init_qdio_queues(struct qeth_card *card) int qeth_init_qdio_queues(struct qeth_card *card)
{ {
unsigned int i; unsigned int i;
...@@ -2673,6 +2684,8 @@ int qeth_init_qdio_queues(struct qeth_card *card) ...@@ -2673,6 +2684,8 @@ int qeth_init_qdio_queues(struct qeth_card *card)
queue->do_pack = 0; queue->do_pack = 0;
queue->prev_hdr = NULL; queue->prev_hdr = NULL;
queue->bulk_start = 0; queue->bulk_start = 0;
queue->bulk_count = 0;
queue->bulk_max = qeth_tx_select_bulk_max(card, queue);
atomic_set(&queue->used_buffers, 0); atomic_set(&queue->used_buffers, 0);
atomic_set(&queue->set_pci_flags_count, 0); atomic_set(&queue->set_pci_flags_count, 0);
atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
...@@ -3107,7 +3120,7 @@ static void qeth_queue_input_buffer(struct qeth_card *card, int index) ...@@ -3107,7 +3120,7 @@ static void qeth_queue_input_buffer(struct qeth_card *card, int index)
for (i = queue->next_buf_to_init; for (i = queue->next_buf_to_init;
i < queue->next_buf_to_init + count; ++i) { i < queue->next_buf_to_init + count; ++i) {
if (qeth_init_input_buffer(card, if (qeth_init_input_buffer(card,
&queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q])) { &queue->bufs[QDIO_BUFNR(i)])) {
break; break;
} else { } else {
newcount++; newcount++;
...@@ -3149,8 +3162,8 @@ static void qeth_queue_input_buffer(struct qeth_card *card, int index) ...@@ -3149,8 +3162,8 @@ static void qeth_queue_input_buffer(struct qeth_card *card, int index)
if (rc) { if (rc) {
QETH_CARD_TEXT(card, 2, "qinberr"); QETH_CARD_TEXT(card, 2, "qinberr");
} }
queue->next_buf_to_init = (queue->next_buf_to_init + count) % queue->next_buf_to_init = QDIO_BUFNR(queue->next_buf_to_init +
QDIO_MAX_BUFFERS_PER_Q; count);
} }
} }
...@@ -3198,7 +3211,7 @@ static int qeth_prep_flush_pack_buffer(struct qeth_qdio_out_q *queue) ...@@ -3198,7 +3211,7 @@ static int qeth_prep_flush_pack_buffer(struct qeth_qdio_out_q *queue)
/* it's a packing buffer */ /* it's a packing buffer */
atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED); atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED);
queue->next_buf_to_fill = queue->next_buf_to_fill =
(queue->next_buf_to_fill + 1) % QDIO_MAX_BUFFERS_PER_Q; QDIO_BUFNR(queue->next_buf_to_fill + 1);
return 1; return 1;
} }
return 0; return 0;
...@@ -3252,7 +3265,8 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index, ...@@ -3252,7 +3265,8 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index,
unsigned int qdio_flags; unsigned int qdio_flags;
for (i = index; i < index + count; ++i) { for (i = index; i < index + count; ++i) {
int bidx = i % QDIO_MAX_BUFFERS_PER_Q; unsigned int bidx = QDIO_BUFNR(i);
buf = queue->bufs[bidx]; buf = queue->bufs[bidx];
buf->buffer->element[buf->next_element_to_fill - 1].eflags |= buf->buffer->element[buf->next_element_to_fill - 1].eflags |=
SBAL_EFLAGS_LAST_ENTRY; SBAL_EFLAGS_LAST_ENTRY;
...@@ -3318,10 +3332,11 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index, ...@@ -3318,10 +3332,11 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index,
static void qeth_flush_queue(struct qeth_qdio_out_q *queue) static void qeth_flush_queue(struct qeth_qdio_out_q *queue)
{ {
qeth_flush_buffers(queue, queue->bulk_start, 1); qeth_flush_buffers(queue, queue->bulk_start, queue->bulk_count);
queue->bulk_start = QDIO_BUFNR(queue->bulk_start + 1); queue->bulk_start = QDIO_BUFNR(queue->bulk_start + queue->bulk_count);
queue->prev_hdr = NULL; queue->prev_hdr = NULL;
queue->bulk_count = 0;
} }
static void qeth_check_outbound_queue(struct qeth_qdio_out_q *queue) static void qeth_check_outbound_queue(struct qeth_qdio_out_q *queue)
...@@ -3419,8 +3434,7 @@ static void qeth_qdio_cq_handler(struct qeth_card *card, unsigned int qdio_err, ...@@ -3419,8 +3434,7 @@ static void qeth_qdio_cq_handler(struct qeth_card *card, unsigned int qdio_err,
} }
for (i = first_element; i < first_element + count; ++i) { for (i = first_element; i < first_element + count; ++i) {
int bidx = i % QDIO_MAX_BUFFERS_PER_Q; struct qdio_buffer *buffer = cq->qdio_bufs[QDIO_BUFNR(i)];
struct qdio_buffer *buffer = cq->qdio_bufs[bidx];
int e = 0; int e = 0;
while ((e < QDIO_MAX_ELEMENTS_PER_BUFFER) && while ((e < QDIO_MAX_ELEMENTS_PER_BUFFER) &&
...@@ -3441,8 +3455,8 @@ static void qeth_qdio_cq_handler(struct qeth_card *card, unsigned int qdio_err, ...@@ -3441,8 +3455,8 @@ static void qeth_qdio_cq_handler(struct qeth_card *card, unsigned int qdio_err,
"QDIO reported an error, rc=%i\n", rc); "QDIO reported an error, rc=%i\n", rc);
QETH_CARD_TEXT(card, 2, "qcqherr"); QETH_CARD_TEXT(card, 2, "qcqherr");
} }
card->qdio.c_q->next_buf_to_init = (card->qdio.c_q->next_buf_to_init
+ count) % QDIO_MAX_BUFFERS_PER_Q; cq->next_buf_to_init = QDIO_BUFNR(cq->next_buf_to_init + count);
} }
static void qeth_qdio_input_handler(struct ccw_device *ccwdev, static void qeth_qdio_input_handler(struct ccw_device *ccwdev,
...@@ -3468,7 +3482,6 @@ static void qeth_qdio_output_handler(struct ccw_device *ccwdev, ...@@ -3468,7 +3482,6 @@ static void qeth_qdio_output_handler(struct ccw_device *ccwdev,
{ {
struct qeth_card *card = (struct qeth_card *) card_ptr; struct qeth_card *card = (struct qeth_card *) card_ptr;
struct qeth_qdio_out_q *queue = card->qdio.out_qs[__queue]; struct qeth_qdio_out_q *queue = card->qdio.out_qs[__queue];
struct qeth_qdio_out_buffer *buffer;
struct net_device *dev = card->dev; struct net_device *dev = card->dev;
struct netdev_queue *txq; struct netdev_queue *txq;
int i; int i;
...@@ -3482,10 +3495,10 @@ static void qeth_qdio_output_handler(struct ccw_device *ccwdev, ...@@ -3482,10 +3495,10 @@ static void qeth_qdio_output_handler(struct ccw_device *ccwdev,
} }
for (i = first_element; i < (first_element + count); ++i) { for (i = first_element; i < (first_element + count); ++i) {
int bidx = i % QDIO_MAX_BUFFERS_PER_Q; struct qeth_qdio_out_buffer *buf = queue->bufs[QDIO_BUFNR(i)];
buffer = queue->bufs[bidx];
qeth_handle_send_error(card, buffer, qdio_error); qeth_handle_send_error(card, buf, qdio_error);
qeth_clear_output_buffer(queue, buffer, qdio_error, 0); qeth_clear_output_buffer(queue, buf, qdio_error, 0);
} }
atomic_sub(count, &queue->used_buffers); atomic_sub(count, &queue->used_buffers);
...@@ -3680,10 +3693,10 @@ static int qeth_add_hw_header(struct qeth_qdio_out_q *queue, ...@@ -3680,10 +3693,10 @@ static int qeth_add_hw_header(struct qeth_qdio_out_q *queue,
} }
static bool qeth_iqd_may_bulk(struct qeth_qdio_out_q *queue, static bool qeth_iqd_may_bulk(struct qeth_qdio_out_q *queue,
struct qeth_qdio_out_buffer *buffer,
struct sk_buff *curr_skb, struct sk_buff *curr_skb,
struct qeth_hdr *curr_hdr) struct qeth_hdr *curr_hdr)
{ {
struct qeth_qdio_out_buffer *buffer = queue->bufs[queue->bulk_start];
struct qeth_hdr *prev_hdr = queue->prev_hdr; struct qeth_hdr *prev_hdr = queue->prev_hdr;
if (!prev_hdr) if (!prev_hdr)
...@@ -3803,13 +3816,14 @@ static int __qeth_xmit(struct qeth_card *card, struct qeth_qdio_out_q *queue, ...@@ -3803,13 +3816,14 @@ static int __qeth_xmit(struct qeth_card *card, struct qeth_qdio_out_q *queue,
struct qeth_hdr *hdr, unsigned int offset, struct qeth_hdr *hdr, unsigned int offset,
unsigned int hd_len) unsigned int hd_len)
{ {
struct qeth_qdio_out_buffer *buffer = queue->bufs[queue->bulk_start];
unsigned int bytes = qdisc_pkt_len(skb); unsigned int bytes = qdisc_pkt_len(skb);
struct qeth_qdio_out_buffer *buffer;
unsigned int next_element; unsigned int next_element;
struct netdev_queue *txq; struct netdev_queue *txq;
bool stopped = false; bool stopped = false;
bool flush; bool flush;
buffer = queue->bufs[QDIO_BUFNR(queue->bulk_start + queue->bulk_count)];
txq = netdev_get_tx_queue(card->dev, skb_get_queue_mapping(skb)); txq = netdev_get_tx_queue(card->dev, skb_get_queue_mapping(skb));
/* Just a sanity check, the wake/stop logic should ensure that we always /* Just a sanity check, the wake/stop logic should ensure that we always
...@@ -3818,11 +3832,23 @@ static int __qeth_xmit(struct qeth_card *card, struct qeth_qdio_out_q *queue, ...@@ -3818,11 +3832,23 @@ static int __qeth_xmit(struct qeth_card *card, struct qeth_qdio_out_q *queue,
if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY) if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY)
return -EBUSY; return -EBUSY;
if ((buffer->next_element_to_fill + elements > queue->max_elements) || flush = !qeth_iqd_may_bulk(queue, skb, hdr);
!qeth_iqd_may_bulk(queue, buffer, skb, hdr)) {
if (flush ||
(buffer->next_element_to_fill + elements > queue->max_elements)) {
if (buffer->next_element_to_fill > 0) {
atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED); atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED);
queue->bulk_count++;
}
if (queue->bulk_count >= queue->bulk_max)
flush = true;
if (flush)
qeth_flush_queue(queue); qeth_flush_queue(queue);
buffer = queue->bufs[queue->bulk_start];
buffer = queue->bufs[QDIO_BUFNR(queue->bulk_start +
queue->bulk_count)];
/* Sanity-check again: */ /* Sanity-check again: */
if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY) if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY)
...@@ -3848,6 +3874,12 @@ static int __qeth_xmit(struct qeth_card *card, struct qeth_qdio_out_q *queue, ...@@ -3848,6 +3874,12 @@ static int __qeth_xmit(struct qeth_card *card, struct qeth_qdio_out_q *queue,
if (flush || next_element >= queue->max_elements) { if (flush || next_element >= queue->max_elements) {
atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED); atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED);
queue->bulk_count++;
if (queue->bulk_count >= queue->bulk_max)
flush = true;
if (flush)
qeth_flush_queue(queue); qeth_flush_queue(queue);
} }
...@@ -3898,8 +3930,7 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, ...@@ -3898,8 +3930,7 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED); atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED);
flush_count++; flush_count++;
queue->next_buf_to_fill = queue->next_buf_to_fill =
(queue->next_buf_to_fill + 1) % QDIO_BUFNR(queue->next_buf_to_fill + 1);
QDIO_MAX_BUFFERS_PER_Q;
buffer = queue->bufs[queue->next_buf_to_fill]; buffer = queue->bufs[queue->next_buf_to_fill];
/* We stepped forward, so sanity-check again: */ /* We stepped forward, so sanity-check again: */
...@@ -3932,8 +3963,8 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, ...@@ -3932,8 +3963,8 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
if (!queue->do_pack || stopped || next_element >= queue->max_elements) { if (!queue->do_pack || stopped || next_element >= queue->max_elements) {
flush_count++; flush_count++;
atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED); atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED);
queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) % queue->next_buf_to_fill =
QDIO_MAX_BUFFERS_PER_Q; QDIO_BUFNR(queue->next_buf_to_fill + 1);
} }
if (flush_count) if (flush_count)
...@@ -4261,7 +4292,6 @@ int qeth_set_access_ctrl_online(struct qeth_card *card, int fallback) ...@@ -4261,7 +4292,6 @@ int qeth_set_access_ctrl_online(struct qeth_card *card, int fallback)
} }
return rc; return rc;
} }
EXPORT_SYMBOL_GPL(qeth_set_access_ctrl_online);
void qeth_tx_timeout(struct net_device *dev) void qeth_tx_timeout(struct net_device *dev)
{ {
...@@ -4977,6 +5007,15 @@ int qeth_core_hardsetup_card(struct qeth_card *card, bool *carrier_ok) ...@@ -4977,6 +5007,15 @@ int qeth_core_hardsetup_card(struct qeth_card *card, bool *carrier_ok)
goto out; goto out;
} }
} }
if (!qeth_is_diagass_supported(card, QETH_DIAGS_CMD_TRAP) ||
(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;
return 0; return 0;
out: out:
dev_warn(&card->gdev->dev, "The qeth device driver failed to recover " dev_warn(&card->gdev->dev, "The qeth device driver failed to recover "
...@@ -5165,8 +5204,7 @@ int qeth_poll(struct napi_struct *napi, int budget) ...@@ -5165,8 +5204,7 @@ int qeth_poll(struct napi_struct *napi, int budget)
card->rx.b_count--; card->rx.b_count--;
if (card->rx.b_count) { if (card->rx.b_count) {
card->rx.b_index = card->rx.b_index =
(card->rx.b_index + 1) % QDIO_BUFNR(card->rx.b_index + 1);
QDIO_MAX_BUFFERS_PER_Q;
card->rx.b_element = card->rx.b_element =
&card->qdio.in_q &card->qdio.in_q
->bufs[card->rx.b_index] ->bufs[card->rx.b_index]
...@@ -5182,9 +5220,9 @@ int qeth_poll(struct napi_struct *napi, int budget) ...@@ -5182,9 +5220,9 @@ int qeth_poll(struct napi_struct *napi, int budget)
} }
} }
napi_complete_done(napi, work_done); if (napi_complete_done(napi, work_done) &&
if (qdio_start_irq(card->data.ccwdev, 0)) qdio_start_irq(CARD_DDEV(card), 0))
napi_schedule(&card->napi); napi_schedule(napi);
out: out:
return work_done; return work_done;
} }
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <asm/qeth.h> #include <asm/qeth.h>
#include <uapi/linux/if_ether.h> #include <uapi/linux/if_ether.h>
#include <uapi/linux/in6.h>
#define IPA_PDU_HEADER_SIZE 0x40 #define IPA_PDU_HEADER_SIZE 0x40
#define QETH_IPA_PDU_LEN_TOTAL(buffer) (buffer + 0x0e) #define QETH_IPA_PDU_LEN_TOTAL(buffer) (buffer + 0x0e)
...@@ -365,8 +366,7 @@ struct qeth_ipacmd_setdelip6 { ...@@ -365,8 +366,7 @@ struct qeth_ipacmd_setdelip6 {
struct qeth_ipacmd_setdelipm { struct qeth_ipacmd_setdelipm {
__u8 mac[6]; __u8 mac[6];
__u8 padding[2]; __u8 padding[2];
__u8 ip6[12]; struct in6_addr ip;
__u8 ip4[4];
} __attribute__ ((packed)); } __attribute__ ((packed));
struct qeth_ipacmd_layer2setdelmac { struct qeth_ipacmd_layer2setdelmac {
......
...@@ -759,14 +759,6 @@ static int qeth_l2_setup_netdev(struct qeth_card *card, bool carrier_ok) ...@@ -759,14 +759,6 @@ static int qeth_l2_setup_netdev(struct qeth_card *card, bool carrier_ok)
return rc; return rc;
} }
static int qeth_l2_start_ipassists(struct qeth_card *card)
{
/* configure isolation level */
if (qeth_set_access_ctrl_online(card, 0))
return -ENODEV;
return 0;
}
static void qeth_l2_trace_features(struct qeth_card *card) static void qeth_l2_trace_features(struct qeth_card *card)
{ {
/* Set BridgePort features */ /* Set BridgePort features */
...@@ -797,13 +789,6 @@ static int qeth_l2_set_online(struct ccwgroup_device *gdev) ...@@ -797,13 +789,6 @@ static int qeth_l2_set_online(struct ccwgroup_device *gdev)
goto out_remove; goto out_remove;
} }
if (qeth_is_diagass_supported(card, QETH_DIAGS_CMD_TRAP)) {
if (card->info.hwtrap &&
qeth_hw_trap(card, QETH_DIAGS_TRAP_ARM))
card->info.hwtrap = 0;
} else
card->info.hwtrap = 0;
qeth_bridgeport_query_support(card); qeth_bridgeport_query_support(card);
if (card->options.sbp.supported_funcs) if (card->options.sbp.supported_funcs)
dev_info(&card->gdev->dev, dev_info(&card->gdev->dev,
...@@ -825,12 +810,6 @@ static int qeth_l2_set_online(struct ccwgroup_device *gdev) ...@@ -825,12 +810,6 @@ static int qeth_l2_set_online(struct ccwgroup_device *gdev)
/* softsetup */ /* softsetup */
QETH_CARD_TEXT(card, 2, "softsetp"); QETH_CARD_TEXT(card, 2, "softsetp");
if (IS_OSD(card) || IS_OSX(card)) {
rc = qeth_l2_start_ipassists(card);
if (rc)
goto out_remove;
}
rc = qeth_init_qdio_queues(card); rc = qeth_init_qdio_queues(card);
if (rc) { if (rc) {
QETH_CARD_TEXT_(card, 2, "6err%d", rc); QETH_CARD_TEXT_(card, 2, "6err%d", rc);
......
...@@ -24,7 +24,6 @@ enum qeth_ip_types { ...@@ -24,7 +24,6 @@ enum qeth_ip_types {
struct qeth_ipaddr { struct qeth_ipaddr {
struct hlist_node hnode; struct hlist_node hnode;
enum qeth_ip_types type; enum qeth_ip_types type;
unsigned char mac[ETH_ALEN];
u8 is_multicast:1; u8 is_multicast:1;
u8 in_progress:1; u8 in_progress:1;
u8 disp_flag:2; u8 disp_flag:2;
...@@ -37,7 +36,7 @@ struct qeth_ipaddr { ...@@ -37,7 +36,7 @@ struct qeth_ipaddr {
enum qeth_prot_versions proto; enum qeth_prot_versions proto;
union { union {
struct { struct {
unsigned int addr; __be32 addr;
unsigned int mask; unsigned int mask;
} a4; } a4;
struct { struct {
...@@ -74,12 +73,10 @@ static inline bool qeth_l3_addr_match_all(struct qeth_ipaddr *a1, ...@@ -74,12 +73,10 @@ static inline bool qeth_l3_addr_match_all(struct qeth_ipaddr *a1,
* so 'proto' and 'addr' match for sure. * so 'proto' and 'addr' match for sure.
* *
* For ucast: * For ucast:
* - 'mac' is always 0.
* - 'mask'/'pfxlen' for RXIP/VIPA is always 0. For NORMAL, matching * - 'mask'/'pfxlen' for RXIP/VIPA is always 0. For NORMAL, matching
* values are required to avoid mixups in takeover eligibility. * values are required to avoid mixups in takeover eligibility.
* *
* For mcast, * For mcast,
* - 'mac' is mapped from the IP, and thus always matches.
* - 'mask'/'pfxlen' is always 0. * - 'mask'/'pfxlen' is always 0.
*/ */
if (a1->type != a2->type) if (a1->type != a2->type)
...@@ -89,21 +86,12 @@ static inline bool qeth_l3_addr_match_all(struct qeth_ipaddr *a1, ...@@ -89,21 +86,12 @@ static inline bool qeth_l3_addr_match_all(struct qeth_ipaddr *a1,
return a1->u.a4.mask == a2->u.a4.mask; return a1->u.a4.mask == a2->u.a4.mask;
} }
static inline u64 qeth_l3_ipaddr_hash(struct qeth_ipaddr *addr) static inline u32 qeth_l3_ipaddr_hash(struct qeth_ipaddr *addr)
{ {
u64 ret = 0; if (addr->proto == QETH_PROT_IPV6)
u8 *point; return ipv6_addr_hash(&addr->u.a6.addr);
else
if (addr->proto == QETH_PROT_IPV6) { return ipv4_addr_hash(addr->u.a4.addr);
point = (u8 *) &addr->u.a6.addr;
ret = get_unaligned((u64 *)point) ^
get_unaligned((u64 *) (point + 8));
}
if (addr->proto == QETH_PROT_IPV4) {
point = (u8 *) &addr->u.a4.addr;
ret = get_unaligned((u32 *) point);
}
return ret;
} }
struct qeth_ipato_entry { struct qeth_ipato_entry {
......
...@@ -76,7 +76,7 @@ static struct qeth_ipaddr *qeth_l3_get_addr_buffer(enum qeth_prot_versions prot) ...@@ -76,7 +76,7 @@ static struct qeth_ipaddr *qeth_l3_get_addr_buffer(enum qeth_prot_versions prot)
static struct qeth_ipaddr *qeth_l3_find_addr_by_ip(struct qeth_card *card, static struct qeth_ipaddr *qeth_l3_find_addr_by_ip(struct qeth_card *card,
struct qeth_ipaddr *query) struct qeth_ipaddr *query)
{ {
u64 key = qeth_l3_ipaddr_hash(query); u32 key = qeth_l3_ipaddr_hash(query);
struct qeth_ipaddr *addr; struct qeth_ipaddr *addr;
if (query->is_multicast) { if (query->is_multicast) {
...@@ -381,12 +381,13 @@ static int qeth_l3_send_setdelmc(struct qeth_card *card, ...@@ -381,12 +381,13 @@ static int qeth_l3_send_setdelmc(struct qeth_card *card,
if (!iob) if (!iob)
return -ENOMEM; return -ENOMEM;
cmd = __ipa_cmd(iob); cmd = __ipa_cmd(iob);
ether_addr_copy(cmd->data.setdelipm.mac, addr->mac); if (addr->proto == QETH_PROT_IPV6) {
if (addr->proto == QETH_PROT_IPV6) cmd->data.setdelipm.ip = addr->u.a6.addr;
memcpy(cmd->data.setdelipm.ip6, &addr->u.a6.addr, ipv6_eth_mc_map(&addr->u.a6.addr, cmd->data.setdelipm.mac);
sizeof(struct in6_addr)); } else {
else cmd->data.setdelipm.ip.s6_addr32[3] = addr->u.a4.addr;
memcpy(&cmd->data.setdelipm.ip4, &addr->u.a4.addr, 4); ip_eth_mc_map(addr->u.a4.addr, cmd->data.setdelipm.mac);
}
return qeth_send_ipa_cmd(card, iob, qeth_l3_setdelip_cb, NULL); return qeth_send_ipa_cmd(card, iob, qeth_l3_setdelip_cb, NULL);
} }
...@@ -953,8 +954,6 @@ static int qeth_l3_start_ipassists(struct qeth_card *card) ...@@ -953,8 +954,6 @@ static int qeth_l3_start_ipassists(struct qeth_card *card)
{ {
QETH_CARD_TEXT(card, 3, "strtipas"); QETH_CARD_TEXT(card, 3, "strtipas");
if (qeth_set_access_ctrl_online(card, 0))
return -EIO;
qeth_l3_start_ipa_arp_processing(card); /* go on*/ qeth_l3_start_ipa_arp_processing(card); /* go on*/
qeth_l3_start_ipa_source_mac(card); /* go on*/ qeth_l3_start_ipa_source_mac(card); /* go on*/
qeth_l3_start_ipa_vlan(card); /* go on*/ qeth_l3_start_ipa_vlan(card); /* go on*/
...@@ -1129,8 +1128,7 @@ qeth_l3_add_mc_to_hash(struct qeth_card *card, struct in_device *in4_dev) ...@@ -1129,8 +1128,7 @@ qeth_l3_add_mc_to_hash(struct qeth_card *card, struct in_device *in4_dev)
for (im4 = rcu_dereference(in4_dev->mc_list); im4 != NULL; for (im4 = rcu_dereference(in4_dev->mc_list); im4 != NULL;
im4 = rcu_dereference(im4->next_rcu)) { im4 = rcu_dereference(im4->next_rcu)) {
ip_eth_mc_map(im4->multiaddr, tmp->mac); tmp->u.a4.addr = im4->multiaddr;
tmp->u.a4.addr = be32_to_cpu(im4->multiaddr);
tmp->is_multicast = 1; tmp->is_multicast = 1;
ipm = qeth_l3_find_addr_by_ip(card, tmp); ipm = qeth_l3_find_addr_by_ip(card, tmp);
...@@ -1141,8 +1139,8 @@ qeth_l3_add_mc_to_hash(struct qeth_card *card, struct in_device *in4_dev) ...@@ -1141,8 +1139,8 @@ qeth_l3_add_mc_to_hash(struct qeth_card *card, struct in_device *in4_dev)
ipm = qeth_l3_get_addr_buffer(QETH_PROT_IPV4); ipm = qeth_l3_get_addr_buffer(QETH_PROT_IPV4);
if (!ipm) if (!ipm)
continue; continue;
ether_addr_copy(ipm->mac, tmp->mac);
ipm->u.a4.addr = be32_to_cpu(im4->multiaddr); ipm->u.a4.addr = im4->multiaddr;
ipm->is_multicast = 1; ipm->is_multicast = 1;
ipm->disp_flag = QETH_DISP_ADDR_ADD; ipm->disp_flag = QETH_DISP_ADDR_ADD;
hash_add(card->ip_mc_htable, hash_add(card->ip_mc_htable,
...@@ -1209,9 +1207,7 @@ static void qeth_l3_add_mc6_to_hash(struct qeth_card *card, ...@@ -1209,9 +1207,7 @@ static void qeth_l3_add_mc6_to_hash(struct qeth_card *card,
return; return;
for (im6 = in6_dev->mc_list; im6 != NULL; im6 = im6->next) { for (im6 = in6_dev->mc_list; im6 != NULL; im6 = im6->next) {
ipv6_eth_mc_map(&im6->mca_addr, tmp->mac); tmp->u.a6.addr = im6->mca_addr;
memcpy(&tmp->u.a6.addr, &im6->mca_addr.s6_addr,
sizeof(struct in6_addr));
tmp->is_multicast = 1; tmp->is_multicast = 1;
ipm = qeth_l3_find_addr_by_ip(card, tmp); ipm = qeth_l3_find_addr_by_ip(card, tmp);
...@@ -1225,9 +1221,7 @@ static void qeth_l3_add_mc6_to_hash(struct qeth_card *card, ...@@ -1225,9 +1221,7 @@ static void qeth_l3_add_mc6_to_hash(struct qeth_card *card,
if (!ipm) if (!ipm)
continue; continue;
ether_addr_copy(ipm->mac, tmp->mac); ipm->u.a6.addr = im6->mca_addr;
memcpy(&ipm->u.a6.addr, &im6->mca_addr.s6_addr,
sizeof(struct in6_addr));
ipm->is_multicast = 1; ipm->is_multicast = 1;
ipm->disp_flag = QETH_DISP_ADDR_ADD; ipm->disp_flag = QETH_DISP_ADDR_ADD;
hash_add(card->ip_mc_htable, hash_add(card->ip_mc_htable,
...@@ -2313,13 +2307,6 @@ static int qeth_l3_set_online(struct ccwgroup_device *gdev) ...@@ -2313,13 +2307,6 @@ static int qeth_l3_set_online(struct ccwgroup_device *gdev)
goto out_remove; goto out_remove;
} }
if (qeth_is_diagass_supported(card, QETH_DIAGS_CMD_TRAP)) {
if (card->info.hwtrap &&
qeth_hw_trap(card, QETH_DIAGS_TRAP_ARM))
card->info.hwtrap = 0;
} else
card->info.hwtrap = 0;
card->state = CARD_STATE_HARDSETUP; card->state = CARD_STATE_HARDSETUP;
qeth_print_status_message(card); qeth_print_status_message(card);
...@@ -2557,7 +2544,7 @@ static int qeth_l3_ip_event(struct notifier_block *this, ...@@ -2557,7 +2544,7 @@ static int qeth_l3_ip_event(struct notifier_block *this,
QETH_CARD_TEXT(card, 3, "ipevent"); QETH_CARD_TEXT(card, 3, "ipevent");
qeth_l3_init_ipaddr(&addr, QETH_IP_TYPE_NORMAL, QETH_PROT_IPV4); qeth_l3_init_ipaddr(&addr, QETH_IP_TYPE_NORMAL, QETH_PROT_IPV4);
addr.u.a4.addr = be32_to_cpu(ifa->ifa_address); addr.u.a4.addr = ifa->ifa_address;
addr.u.a4.mask = be32_to_cpu(ifa->ifa_mask); addr.u.a4.mask = be32_to_cpu(ifa->ifa_mask);
return qeth_l3_handle_ip_event(card, &addr, event); return qeth_l3_handle_ip_event(card, &addr, event);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment