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: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
72919b6b3b
@ -82,6 +82,7 @@ enum qdio_irq_states {
|
||||
#define QDIO_SIGA_WRITE 0x00
|
||||
#define QDIO_SIGA_READ 0x01
|
||||
#define QDIO_SIGA_SYNC 0x02
|
||||
#define QDIO_SIGA_WRITEM 0x03
|
||||
#define QDIO_SIGA_WRITEQ 0x04
|
||||
#define QDIO_SIGA_QEBSM_FLAG 0x80
|
||||
|
||||
|
@ -310,18 +310,19 @@ static inline int qdio_siga_sync_q(struct qdio_q *q)
|
||||
return qdio_siga_sync(q, q->mask, 0);
|
||||
}
|
||||
|
||||
static int qdio_siga_output(struct qdio_q *q, unsigned int *busy_bit,
|
||||
unsigned long aob)
|
||||
static int qdio_siga_output(struct qdio_q *q, unsigned int count,
|
||||
unsigned int *busy_bit, unsigned long aob)
|
||||
{
|
||||
unsigned long schid = *((u32 *) &q->irq_ptr->schid);
|
||||
unsigned int fc = QDIO_SIGA_WRITE;
|
||||
u64 start_time = 0;
|
||||
int retries = 0, cc;
|
||||
unsigned long laob = 0;
|
||||
|
||||
if (aob) {
|
||||
fc = QDIO_SIGA_WRITEQ;
|
||||
laob = 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;
|
||||
}
|
||||
|
||||
if (is_qebsm(q)) {
|
||||
@ -329,7 +330,7 @@ static int qdio_siga_output(struct qdio_q *q, unsigned int *busy_bit,
|
||||
fc |= QDIO_SIGA_QEBSM_FLAG;
|
||||
}
|
||||
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 */
|
||||
if (unlikely(*busy_bit)) {
|
||||
@ -781,7 +782,8 @@ static inline int qdio_outbound_q_moved(struct qdio_q *q, unsigned int start)
|
||||
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;
|
||||
unsigned int busy_bit;
|
||||
@ -793,7 +795,7 @@ static int qdio_kick_outbound_q(struct qdio_q *q, unsigned long aob)
|
||||
retry:
|
||||
qperf_inc(q, siga_write);
|
||||
|
||||
cc = qdio_siga_output(q, &busy_bit, aob);
|
||||
cc = qdio_siga_output(q, count, &busy_bit, aob);
|
||||
switch (cc) {
|
||||
case 0:
|
||||
break;
|
||||
@ -1526,7 +1528,7 @@ set:
|
||||
* @count: how many buffers are filled
|
||||
*/
|
||||
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;
|
||||
unsigned char state = 0;
|
||||
@ -1549,13 +1551,10 @@ static int handle_outbound(struct qdio_q *q, unsigned int callflags,
|
||||
if (queue_type(q) == QDIO_IQDIO_QFMT) {
|
||||
unsigned long phys_aob = 0;
|
||||
|
||||
/* One SIGA-W per buffer required for unicast HSI */
|
||||
WARN_ON_ONCE(count > 1 && !multicast_outbound(q));
|
||||
|
||||
if (q->u.out.use_cq)
|
||||
if (q->u.out.use_cq && count == 1)
|
||||
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)) {
|
||||
rc = qdio_siga_sync_q(q);
|
||||
} else if (count < QDIO_MAX_BUFFERS_PER_Q &&
|
||||
@ -1564,7 +1563,7 @@ static int handle_outbound(struct qdio_q *q, unsigned int callflags,
|
||||
/* The previous buffer is not processed yet, tack on. */
|
||||
qperf_inc(q, fast_requeue);
|
||||
} else {
|
||||
rc = qdio_kick_outbound_q(q, 0);
|
||||
rc = qdio_kick_outbound_q(q, count, 0);
|
||||
}
|
||||
|
||||
/* Let drivers implement their own completion scanning: */
|
||||
|
@ -532,6 +532,8 @@ struct qeth_qdio_out_q {
|
||||
struct timer_list timer;
|
||||
struct qeth_hdr *prev_hdr;
|
||||
u8 bulk_start;
|
||||
u8 bulk_count;
|
||||
u8 bulk_max;
|
||||
};
|
||||
|
||||
#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)
|
||||
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,
|
||||
unsigned int elements)
|
||||
{
|
||||
|
@ -1513,7 +1513,6 @@ int qeth_qdio_clear_card(struct qeth_card *card, int use_halt)
|
||||
rc = qeth_clear_halt_card(card, use_halt);
|
||||
if (rc)
|
||||
QETH_CARD_TEXT_(card, 3, "2err%d", rc);
|
||||
card->state = CARD_STATE_DOWN;
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qeth_qdio_clear_card);
|
||||
@ -2634,6 +2633,18 @@ static int qeth_init_input_buffer(struct qeth_card *card,
|
||||
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)
|
||||
{
|
||||
unsigned int i;
|
||||
@ -2673,6 +2684,8 @@ int qeth_init_qdio_queues(struct qeth_card *card)
|
||||
queue->do_pack = 0;
|
||||
queue->prev_hdr = NULL;
|
||||
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->set_pci_flags_count, 0);
|
||||
atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
|
||||
@ -3107,7 +3120,7 @@ static void qeth_queue_input_buffer(struct qeth_card *card, int index)
|
||||
for (i = queue->next_buf_to_init;
|
||||
i < queue->next_buf_to_init + count; ++i) {
|
||||
if (qeth_init_input_buffer(card,
|
||||
&queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q])) {
|
||||
&queue->bufs[QDIO_BUFNR(i)])) {
|
||||
break;
|
||||
} else {
|
||||
newcount++;
|
||||
@ -3149,8 +3162,8 @@ static void qeth_queue_input_buffer(struct qeth_card *card, int index)
|
||||
if (rc) {
|
||||
QETH_CARD_TEXT(card, 2, "qinberr");
|
||||
}
|
||||
queue->next_buf_to_init = (queue->next_buf_to_init + count) %
|
||||
QDIO_MAX_BUFFERS_PER_Q;
|
||||
queue->next_buf_to_init = QDIO_BUFNR(queue->next_buf_to_init +
|
||||
count);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3198,7 +3211,7 @@ static int qeth_prep_flush_pack_buffer(struct qeth_qdio_out_q *queue)
|
||||
/* it's a packing buffer */
|
||||
atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED);
|
||||
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 0;
|
||||
@ -3252,7 +3265,8 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index,
|
||||
unsigned int qdio_flags;
|
||||
|
||||
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->buffer->element[buf->next_element_to_fill - 1].eflags |=
|
||||
SBAL_EFLAGS_LAST_ENTRY;
|
||||
@ -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)
|
||||
{
|
||||
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->bulk_count = 0;
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
|
||||
for (i = first_element; i < first_element + count; ++i) {
|
||||
int bidx = i % QDIO_MAX_BUFFERS_PER_Q;
|
||||
struct qdio_buffer *buffer = cq->qdio_bufs[bidx];
|
||||
struct qdio_buffer *buffer = cq->qdio_bufs[QDIO_BUFNR(i)];
|
||||
int e = 0;
|
||||
|
||||
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,
|
||||
"QDIO reported an error, rc=%i\n", rc);
|
||||
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,
|
||||
@ -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_qdio_out_q *queue = card->qdio.out_qs[__queue];
|
||||
struct qeth_qdio_out_buffer *buffer;
|
||||
struct net_device *dev = card->dev;
|
||||
struct netdev_queue *txq;
|
||||
int i;
|
||||
@ -3482,10 +3495,10 @@ static void qeth_qdio_output_handler(struct ccw_device *ccwdev,
|
||||
}
|
||||
|
||||
for (i = first_element; i < (first_element + count); ++i) {
|
||||
int bidx = i % QDIO_MAX_BUFFERS_PER_Q;
|
||||
buffer = queue->bufs[bidx];
|
||||
qeth_handle_send_error(card, buffer, qdio_error);
|
||||
qeth_clear_output_buffer(queue, buffer, qdio_error, 0);
|
||||
struct qeth_qdio_out_buffer *buf = queue->bufs[QDIO_BUFNR(i)];
|
||||
|
||||
qeth_handle_send_error(card, buf, qdio_error);
|
||||
qeth_clear_output_buffer(queue, buf, qdio_error, 0);
|
||||
}
|
||||
|
||||
atomic_sub(count, &queue->used_buffers);
|
||||
@ -3680,10 +3693,10 @@ check_layout:
|
||||
}
|
||||
|
||||
static bool qeth_iqd_may_bulk(struct qeth_qdio_out_q *queue,
|
||||
struct qeth_qdio_out_buffer *buffer,
|
||||
struct sk_buff *curr_skb,
|
||||
struct qeth_hdr *curr_hdr)
|
||||
{
|
||||
struct qeth_qdio_out_buffer *buffer = queue->bufs[queue->bulk_start];
|
||||
struct qeth_hdr *prev_hdr = queue->prev_hdr;
|
||||
|
||||
if (!prev_hdr)
|
||||
@ -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,
|
||||
unsigned int hd_len)
|
||||
{
|
||||
struct qeth_qdio_out_buffer *buffer = queue->bufs[queue->bulk_start];
|
||||
unsigned int bytes = qdisc_pkt_len(skb);
|
||||
struct qeth_qdio_out_buffer *buffer;
|
||||
unsigned int next_element;
|
||||
struct netdev_queue *txq;
|
||||
bool stopped = false;
|
||||
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));
|
||||
|
||||
/* 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,
|
||||
if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY)
|
||||
return -EBUSY;
|
||||
|
||||
if ((buffer->next_element_to_fill + elements > queue->max_elements) ||
|
||||
!qeth_iqd_may_bulk(queue, buffer, skb, hdr)) {
|
||||
atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED);
|
||||
qeth_flush_queue(queue);
|
||||
buffer = queue->bufs[queue->bulk_start];
|
||||
flush = !qeth_iqd_may_bulk(queue, 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);
|
||||
queue->bulk_count++;
|
||||
}
|
||||
|
||||
if (queue->bulk_count >= queue->bulk_max)
|
||||
flush = true;
|
||||
|
||||
if (flush)
|
||||
qeth_flush_queue(queue);
|
||||
|
||||
buffer = queue->bufs[QDIO_BUFNR(queue->bulk_start +
|
||||
queue->bulk_count)];
|
||||
|
||||
/* Sanity-check again: */
|
||||
if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY)
|
||||
@ -3848,7 +3874,13 @@ static int __qeth_xmit(struct qeth_card *card, struct qeth_qdio_out_q *queue,
|
||||
|
||||
if (flush || next_element >= queue->max_elements) {
|
||||
atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED);
|
||||
qeth_flush_queue(queue);
|
||||
queue->bulk_count++;
|
||||
|
||||
if (queue->bulk_count >= queue->bulk_max)
|
||||
flush = true;
|
||||
|
||||
if (flush)
|
||||
qeth_flush_queue(queue);
|
||||
}
|
||||
|
||||
if (stopped && !qeth_out_queue_is_full(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);
|
||||
flush_count++;
|
||||
queue->next_buf_to_fill =
|
||||
(queue->next_buf_to_fill + 1) %
|
||||
QDIO_MAX_BUFFERS_PER_Q;
|
||||
QDIO_BUFNR(queue->next_buf_to_fill + 1);
|
||||
buffer = queue->bufs[queue->next_buf_to_fill];
|
||||
|
||||
/* 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,
|
||||
if (!queue->do_pack || stopped || next_element >= queue->max_elements) {
|
||||
flush_count++;
|
||||
atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED);
|
||||
queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) %
|
||||
QDIO_MAX_BUFFERS_PER_Q;
|
||||
queue->next_buf_to_fill =
|
||||
QDIO_BUFNR(queue->next_buf_to_fill + 1);
|
||||
}
|
||||
|
||||
if (flush_count)
|
||||
@ -4261,7 +4292,6 @@ int qeth_set_access_ctrl_online(struct qeth_card *card, int fallback)
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qeth_set_access_ctrl_online);
|
||||
|
||||
void qeth_tx_timeout(struct net_device *dev)
|
||||
{
|
||||
@ -4977,6 +5007,15 @@ retriable:
|
||||
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;
|
||||
out:
|
||||
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)
|
||||
card->rx.b_count--;
|
||||
if (card->rx.b_count) {
|
||||
card->rx.b_index =
|
||||
(card->rx.b_index + 1) %
|
||||
QDIO_MAX_BUFFERS_PER_Q;
|
||||
QDIO_BUFNR(card->rx.b_index + 1);
|
||||
card->rx.b_element =
|
||||
&card->qdio.in_q
|
||||
->bufs[card->rx.b_index]
|
||||
@ -5182,9 +5220,9 @@ int qeth_poll(struct napi_struct *napi, int budget)
|
||||
}
|
||||
}
|
||||
|
||||
napi_complete_done(napi, work_done);
|
||||
if (qdio_start_irq(card->data.ccwdev, 0))
|
||||
napi_schedule(&card->napi);
|
||||
if (napi_complete_done(napi, work_done) &&
|
||||
qdio_start_irq(CARD_DDEV(card), 0))
|
||||
napi_schedule(napi);
|
||||
out:
|
||||
return work_done;
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include <asm/qeth.h>
|
||||
#include <uapi/linux/if_ether.h>
|
||||
#include <uapi/linux/in6.h>
|
||||
|
||||
#define IPA_PDU_HEADER_SIZE 0x40
|
||||
#define QETH_IPA_PDU_LEN_TOTAL(buffer) (buffer + 0x0e)
|
||||
@ -365,8 +366,7 @@ struct qeth_ipacmd_setdelip6 {
|
||||
struct qeth_ipacmd_setdelipm {
|
||||
__u8 mac[6];
|
||||
__u8 padding[2];
|
||||
__u8 ip6[12];
|
||||
__u8 ip4[4];
|
||||
struct in6_addr ip;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct qeth_ipacmd_layer2setdelmac {
|
||||
|
@ -759,14 +759,6 @@ add_napi:
|
||||
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)
|
||||
{
|
||||
/* Set BridgePort features */
|
||||
@ -797,13 +789,6 @@ static int qeth_l2_set_online(struct ccwgroup_device *gdev)
|
||||
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);
|
||||
if (card->options.sbp.supported_funcs)
|
||||
dev_info(&card->gdev->dev,
|
||||
@ -825,12 +810,6 @@ static int qeth_l2_set_online(struct ccwgroup_device *gdev)
|
||||
/* softsetup */
|
||||
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);
|
||||
if (rc) {
|
||||
QETH_CARD_TEXT_(card, 2, "6err%d", rc);
|
||||
|
@ -24,7 +24,6 @@ enum qeth_ip_types {
|
||||
struct qeth_ipaddr {
|
||||
struct hlist_node hnode;
|
||||
enum qeth_ip_types type;
|
||||
unsigned char mac[ETH_ALEN];
|
||||
u8 is_multicast:1;
|
||||
u8 in_progress:1;
|
||||
u8 disp_flag:2;
|
||||
@ -37,7 +36,7 @@ struct qeth_ipaddr {
|
||||
enum qeth_prot_versions proto;
|
||||
union {
|
||||
struct {
|
||||
unsigned int addr;
|
||||
__be32 addr;
|
||||
unsigned int mask;
|
||||
} a4;
|
||||
struct {
|
||||
@ -74,12 +73,10 @@ static inline bool qeth_l3_addr_match_all(struct qeth_ipaddr *a1,
|
||||
* so 'proto' and 'addr' match for sure.
|
||||
*
|
||||
* For ucast:
|
||||
* - 'mac' is always 0.
|
||||
* - 'mask'/'pfxlen' for RXIP/VIPA is always 0. For NORMAL, matching
|
||||
* values are required to avoid mixups in takeover eligibility.
|
||||
*
|
||||
* For mcast,
|
||||
* - 'mac' is mapped from the IP, and thus always matches.
|
||||
* - 'mask'/'pfxlen' is always 0.
|
||||
*/
|
||||
if (a1->type != a2->type)
|
||||
@ -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;
|
||||
}
|
||||
|
||||
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;
|
||||
u8 *point;
|
||||
|
||||
if (addr->proto == QETH_PROT_IPV6) {
|
||||
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;
|
||||
if (addr->proto == QETH_PROT_IPV6)
|
||||
return ipv6_addr_hash(&addr->u.a6.addr);
|
||||
else
|
||||
return ipv4_addr_hash(addr->u.a4.addr);
|
||||
}
|
||||
|
||||
struct qeth_ipato_entry {
|
||||
|
@ -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,
|
||||
struct qeth_ipaddr *query)
|
||||
{
|
||||
u64 key = qeth_l3_ipaddr_hash(query);
|
||||
u32 key = qeth_l3_ipaddr_hash(query);
|
||||
struct qeth_ipaddr *addr;
|
||||
|
||||
if (query->is_multicast) {
|
||||
@ -381,12 +381,13 @@ static int qeth_l3_send_setdelmc(struct qeth_card *card,
|
||||
if (!iob)
|
||||
return -ENOMEM;
|
||||
cmd = __ipa_cmd(iob);
|
||||
ether_addr_copy(cmd->data.setdelipm.mac, addr->mac);
|
||||
if (addr->proto == QETH_PROT_IPV6)
|
||||
memcpy(cmd->data.setdelipm.ip6, &addr->u.a6.addr,
|
||||
sizeof(struct in6_addr));
|
||||
else
|
||||
memcpy(&cmd->data.setdelipm.ip4, &addr->u.a4.addr, 4);
|
||||
if (addr->proto == QETH_PROT_IPV6) {
|
||||
cmd->data.setdelipm.ip = addr->u.a6.addr;
|
||||
ipv6_eth_mc_map(&addr->u.a6.addr, cmd->data.setdelipm.mac);
|
||||
} else {
|
||||
cmd->data.setdelipm.ip.s6_addr32[3] = addr->u.a4.addr;
|
||||
ip_eth_mc_map(addr->u.a4.addr, cmd->data.setdelipm.mac);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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_source_mac(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)
|
||||
|
||||
for (im4 = rcu_dereference(in4_dev->mc_list); im4 != NULL;
|
||||
im4 = rcu_dereference(im4->next_rcu)) {
|
||||
ip_eth_mc_map(im4->multiaddr, tmp->mac);
|
||||
tmp->u.a4.addr = be32_to_cpu(im4->multiaddr);
|
||||
tmp->u.a4.addr = im4->multiaddr;
|
||||
tmp->is_multicast = 1;
|
||||
|
||||
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)
|
||||
ipm = qeth_l3_get_addr_buffer(QETH_PROT_IPV4);
|
||||
if (!ipm)
|
||||
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->disp_flag = QETH_DISP_ADDR_ADD;
|
||||
hash_add(card->ip_mc_htable,
|
||||
@ -1209,9 +1207,7 @@ static void qeth_l3_add_mc6_to_hash(struct qeth_card *card,
|
||||
return;
|
||||
|
||||
for (im6 = in6_dev->mc_list; im6 != NULL; im6 = im6->next) {
|
||||
ipv6_eth_mc_map(&im6->mca_addr, tmp->mac);
|
||||
memcpy(&tmp->u.a6.addr, &im6->mca_addr.s6_addr,
|
||||
sizeof(struct in6_addr));
|
||||
tmp->u.a6.addr = im6->mca_addr;
|
||||
tmp->is_multicast = 1;
|
||||
|
||||
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,
|
||||
if (!ipm)
|
||||
continue;
|
||||
|
||||
ether_addr_copy(ipm->mac, tmp->mac);
|
||||
memcpy(&ipm->u.a6.addr, &im6->mca_addr.s6_addr,
|
||||
sizeof(struct in6_addr));
|
||||
ipm->u.a6.addr = im6->mca_addr;
|
||||
ipm->is_multicast = 1;
|
||||
ipm->disp_flag = QETH_DISP_ADDR_ADD;
|
||||
hash_add(card->ip_mc_htable,
|
||||
@ -2313,13 +2307,6 @@ static int qeth_l3_set_online(struct ccwgroup_device *gdev)
|
||||
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;
|
||||
qeth_print_status_message(card);
|
||||
|
||||
@ -2557,7 +2544,7 @@ static int qeth_l3_ip_event(struct notifier_block *this,
|
||||
QETH_CARD_TEXT(card, 3, "ipevent");
|
||||
|
||||
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);
|
||||
|
||||
return qeth_l3_handle_ip_event(card, &addr, event);
|
||||
|
Loading…
Reference in New Issue
Block a user