mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 03:27:44 -04:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1699 commits) bnx2/bnx2x: Unsupported Ethtool operations should return -EINVAL. vlan: Calling vlan_hwaccel_do_receive() is always valid. tproxy: use the interface primary IP address as a default value for --on-ip tproxy: added IPv6 support to the socket match cxgb3: function namespace cleanup tproxy: added IPv6 support to the TPROXY target tproxy: added IPv6 socket lookup function to nf_tproxy_core be2net: Changes to use only priority codes allowed by f/w tproxy: allow non-local binds of IPv6 sockets if IP_TRANSPARENT is enabled tproxy: added tproxy sockopt interface in the IPV6 layer tproxy: added udp6_lib_lookup function tproxy: added const specifiers to udp lookup functions tproxy: split off ipv6 defragmentation to a separate module l2tp: small cleanup nf_nat: restrict ICMP translation for embedded header can: mcp251x: fix generation of error frames can: mcp251x: fix endless loop in interrupt handler if CANINTF_MERRF is set can-raw: add msg_flags to distinguish local traffic 9p: client code cleanup rds: make local functions/variables static ... Fix up conflicts in net/core/dev.c, drivers/net/pcmcia/smc91c92_cs.c and drivers/net/wireless/ath/ath9k/debug.c as per David
This commit is contained in:
commit
5f05647dd8
1341 changed files with 157282 additions and 84033 deletions
|
|
@ -208,6 +208,7 @@ struct qdio_dev_perf_stat {
|
|||
unsigned int eqbs_partial;
|
||||
unsigned int sqbs;
|
||||
unsigned int sqbs_partial;
|
||||
unsigned int int_discarded;
|
||||
} ____cacheline_aligned;
|
||||
|
||||
struct qdio_queue_perf_stat {
|
||||
|
|
@ -222,6 +223,10 @@ struct qdio_queue_perf_stat {
|
|||
unsigned int nr_sbal_total;
|
||||
};
|
||||
|
||||
enum qdio_queue_irq_states {
|
||||
QDIO_QUEUE_IRQS_DISABLED,
|
||||
};
|
||||
|
||||
struct qdio_input_q {
|
||||
/* input buffer acknowledgement flag */
|
||||
int polling;
|
||||
|
|
@ -231,6 +236,10 @@ struct qdio_input_q {
|
|||
int ack_count;
|
||||
/* last time of noticing incoming data */
|
||||
u64 timestamp;
|
||||
/* upper-layer polling flag */
|
||||
unsigned long queue_irq_state;
|
||||
/* callback to start upper-layer polling */
|
||||
void (*queue_start_poll) (struct ccw_device *, int, unsigned long);
|
||||
};
|
||||
|
||||
struct qdio_output_q {
|
||||
|
|
@ -399,6 +408,26 @@ static inline int multicast_outbound(struct qdio_q *q)
|
|||
#define sub_buf(bufnr, dec) \
|
||||
((bufnr - dec) & QDIO_MAX_BUFFERS_MASK)
|
||||
|
||||
#define queue_irqs_enabled(q) \
|
||||
(test_bit(QDIO_QUEUE_IRQS_DISABLED, &q->u.in.queue_irq_state) == 0)
|
||||
#define queue_irqs_disabled(q) \
|
||||
(test_bit(QDIO_QUEUE_IRQS_DISABLED, &q->u.in.queue_irq_state) != 0)
|
||||
|
||||
#define TIQDIO_SHARED_IND 63
|
||||
|
||||
/* device state change indicators */
|
||||
struct indicator_t {
|
||||
u32 ind; /* u32 because of compare-and-swap performance */
|
||||
atomic_t count; /* use count, 0 or 1 for non-shared indicators */
|
||||
};
|
||||
|
||||
extern struct indicator_t *q_indicators;
|
||||
|
||||
static inline int shared_ind(struct qdio_irq *irq_ptr)
|
||||
{
|
||||
return irq_ptr->dsci == &q_indicators[TIQDIO_SHARED_IND].ind;
|
||||
}
|
||||
|
||||
/* prototypes for thin interrupt */
|
||||
void qdio_setup_thinint(struct qdio_irq *irq_ptr);
|
||||
int qdio_establish_thinint(struct qdio_irq *irq_ptr);
|
||||
|
|
|
|||
|
|
@ -56,9 +56,16 @@ static int qstat_show(struct seq_file *m, void *v)
|
|||
|
||||
seq_printf(m, "DSCI: %d nr_used: %d\n",
|
||||
*(u32 *)q->irq_ptr->dsci, atomic_read(&q->nr_buf_used));
|
||||
seq_printf(m, "ftc: %d last_move: %d\n", q->first_to_check, q->last_move);
|
||||
seq_printf(m, "polling: %d ack start: %d ack count: %d\n",
|
||||
q->u.in.polling, q->u.in.ack_start, q->u.in.ack_count);
|
||||
seq_printf(m, "ftc: %d last_move: %d\n",
|
||||
q->first_to_check, q->last_move);
|
||||
if (q->is_input_q) {
|
||||
seq_printf(m, "polling: %d ack start: %d ack count: %d\n",
|
||||
q->u.in.polling, q->u.in.ack_start,
|
||||
q->u.in.ack_count);
|
||||
seq_printf(m, "IRQs disabled: %u\n",
|
||||
test_bit(QDIO_QUEUE_IRQS_DISABLED,
|
||||
&q->u.in.queue_irq_state));
|
||||
}
|
||||
seq_printf(m, "SBAL states:\n");
|
||||
seq_printf(m, "|0 |8 |16 |24 |32 |40 |48 |56 63|\n");
|
||||
|
||||
|
|
@ -113,22 +120,6 @@ static int qstat_show(struct seq_file *m, void *v)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t qstat_seq_write(struct file *file, const char __user *buf,
|
||||
size_t count, loff_t *off)
|
||||
{
|
||||
struct seq_file *seq = file->private_data;
|
||||
struct qdio_q *q = seq->private;
|
||||
|
||||
if (!q)
|
||||
return 0;
|
||||
if (q->is_input_q)
|
||||
xchg(q->irq_ptr->dsci, 1);
|
||||
local_bh_disable();
|
||||
tasklet_schedule(&q->tasklet);
|
||||
local_bh_enable();
|
||||
return count;
|
||||
}
|
||||
|
||||
static int qstat_seq_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
return single_open(filp, qstat_show,
|
||||
|
|
@ -139,7 +130,6 @@ static const struct file_operations debugfs_fops = {
|
|||
.owner = THIS_MODULE,
|
||||
.open = qstat_seq_open,
|
||||
.read = seq_read,
|
||||
.write = qstat_seq_write,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
|
@ -166,7 +156,8 @@ static char *qperf_names[] = {
|
|||
"QEBSM eqbs",
|
||||
"QEBSM eqbs partial",
|
||||
"QEBSM sqbs",
|
||||
"QEBSM sqbs partial"
|
||||
"QEBSM sqbs partial",
|
||||
"Discarded interrupts"
|
||||
};
|
||||
|
||||
static int qperf_show(struct seq_file *m, void *v)
|
||||
|
|
|
|||
|
|
@ -884,8 +884,19 @@ static void qdio_int_handler_pci(struct qdio_irq *irq_ptr)
|
|||
if (unlikely(irq_ptr->state == QDIO_IRQ_STATE_STOPPED))
|
||||
return;
|
||||
|
||||
for_each_input_queue(irq_ptr, q, i)
|
||||
tasklet_schedule(&q->tasklet);
|
||||
for_each_input_queue(irq_ptr, q, i) {
|
||||
if (q->u.in.queue_start_poll) {
|
||||
/* skip if polling is enabled or already in work */
|
||||
if (test_and_set_bit(QDIO_QUEUE_IRQS_DISABLED,
|
||||
&q->u.in.queue_irq_state)) {
|
||||
qperf_inc(q, int_discarded);
|
||||
continue;
|
||||
}
|
||||
q->u.in.queue_start_poll(q->irq_ptr->cdev, q->nr,
|
||||
q->irq_ptr->int_parm);
|
||||
} else
|
||||
tasklet_schedule(&q->tasklet);
|
||||
}
|
||||
|
||||
if (!(irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED))
|
||||
return;
|
||||
|
|
@ -1519,6 +1530,129 @@ int do_QDIO(struct ccw_device *cdev, unsigned int callflags,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(do_QDIO);
|
||||
|
||||
/**
|
||||
* qdio_start_irq - process input buffers
|
||||
* @cdev: associated ccw_device for the qdio subchannel
|
||||
* @nr: input queue number
|
||||
*
|
||||
* Return codes
|
||||
* 0 - success
|
||||
* 1 - irqs not started since new data is available
|
||||
*/
|
||||
int qdio_start_irq(struct ccw_device *cdev, int nr)
|
||||
{
|
||||
struct qdio_q *q;
|
||||
struct qdio_irq *irq_ptr = cdev->private->qdio_data;
|
||||
|
||||
if (!irq_ptr)
|
||||
return -ENODEV;
|
||||
q = irq_ptr->input_qs[nr];
|
||||
|
||||
WARN_ON(queue_irqs_enabled(q));
|
||||
|
||||
if (!shared_ind(q->irq_ptr))
|
||||
xchg(q->irq_ptr->dsci, 0);
|
||||
|
||||
qdio_stop_polling(q);
|
||||
clear_bit(QDIO_QUEUE_IRQS_DISABLED, &q->u.in.queue_irq_state);
|
||||
|
||||
/*
|
||||
* We need to check again to not lose initiative after
|
||||
* resetting the ACK state.
|
||||
*/
|
||||
if (!shared_ind(q->irq_ptr) && *q->irq_ptr->dsci)
|
||||
goto rescan;
|
||||
if (!qdio_inbound_q_done(q))
|
||||
goto rescan;
|
||||
return 0;
|
||||
|
||||
rescan:
|
||||
if (test_and_set_bit(QDIO_QUEUE_IRQS_DISABLED,
|
||||
&q->u.in.queue_irq_state))
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(qdio_start_irq);
|
||||
|
||||
/**
|
||||
* qdio_get_next_buffers - process input buffers
|
||||
* @cdev: associated ccw_device for the qdio subchannel
|
||||
* @nr: input queue number
|
||||
* @bufnr: first filled buffer number
|
||||
* @error: buffers are in error state
|
||||
*
|
||||
* Return codes
|
||||
* < 0 - error
|
||||
* = 0 - no new buffers found
|
||||
* > 0 - number of processed buffers
|
||||
*/
|
||||
int qdio_get_next_buffers(struct ccw_device *cdev, int nr, int *bufnr,
|
||||
int *error)
|
||||
{
|
||||
struct qdio_q *q;
|
||||
int start, end;
|
||||
struct qdio_irq *irq_ptr = cdev->private->qdio_data;
|
||||
|
||||
if (!irq_ptr)
|
||||
return -ENODEV;
|
||||
q = irq_ptr->input_qs[nr];
|
||||
WARN_ON(queue_irqs_enabled(q));
|
||||
|
||||
qdio_sync_after_thinint(q);
|
||||
|
||||
/*
|
||||
* The interrupt could be caused by a PCI request. Check the
|
||||
* PCI capable outbound queues.
|
||||
*/
|
||||
qdio_check_outbound_after_thinint(q);
|
||||
|
||||
if (!qdio_inbound_q_moved(q))
|
||||
return 0;
|
||||
|
||||
/* Note: upper-layer MUST stop processing immediately here ... */
|
||||
if (unlikely(q->irq_ptr->state != QDIO_IRQ_STATE_ACTIVE))
|
||||
return -EIO;
|
||||
|
||||
start = q->first_to_kick;
|
||||
end = q->first_to_check;
|
||||
*bufnr = start;
|
||||
*error = q->qdio_error;
|
||||
|
||||
/* for the next time */
|
||||
q->first_to_kick = end;
|
||||
q->qdio_error = 0;
|
||||
return sub_buf(end, start);
|
||||
}
|
||||
EXPORT_SYMBOL(qdio_get_next_buffers);
|
||||
|
||||
/**
|
||||
* qdio_stop_irq - disable interrupt processing for the device
|
||||
* @cdev: associated ccw_device for the qdio subchannel
|
||||
* @nr: input queue number
|
||||
*
|
||||
* Return codes
|
||||
* 0 - interrupts were already disabled
|
||||
* 1 - interrupts successfully disabled
|
||||
*/
|
||||
int qdio_stop_irq(struct ccw_device *cdev, int nr)
|
||||
{
|
||||
struct qdio_q *q;
|
||||
struct qdio_irq *irq_ptr = cdev->private->qdio_data;
|
||||
|
||||
if (!irq_ptr)
|
||||
return -ENODEV;
|
||||
q = irq_ptr->input_qs[nr];
|
||||
|
||||
if (test_and_set_bit(QDIO_QUEUE_IRQS_DISABLED,
|
||||
&q->u.in.queue_irq_state))
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
EXPORT_SYMBOL(qdio_stop_irq);
|
||||
|
||||
static int __init init_QDIO(void)
|
||||
{
|
||||
int rc;
|
||||
|
|
|
|||
|
|
@ -161,6 +161,7 @@ static void setup_queues(struct qdio_irq *irq_ptr,
|
|||
setup_queues_misc(q, irq_ptr, qdio_init->input_handler, i);
|
||||
|
||||
q->is_input_q = 1;
|
||||
q->u.in.queue_start_poll = qdio_init->queue_start_poll;
|
||||
setup_storage_lists(q, irq_ptr, input_sbal_array, i);
|
||||
input_sbal_array += QDIO_MAX_BUFFERS_PER_Q;
|
||||
|
||||
|
|
|
|||
|
|
@ -25,24 +25,20 @@
|
|||
*/
|
||||
#define TIQDIO_NR_NONSHARED_IND 63
|
||||
#define TIQDIO_NR_INDICATORS (TIQDIO_NR_NONSHARED_IND + 1)
|
||||
#define TIQDIO_SHARED_IND 63
|
||||
|
||||
/* list of thin interrupt input queues */
|
||||
static LIST_HEAD(tiq_list);
|
||||
DEFINE_MUTEX(tiq_list_lock);
|
||||
|
||||
/* adapter local summary indicator */
|
||||
static unsigned char *tiqdio_alsi;
|
||||
static u8 *tiqdio_alsi;
|
||||
|
||||
/* device state change indicators */
|
||||
struct indicator_t {
|
||||
u32 ind; /* u32 because of compare-and-swap performance */
|
||||
atomic_t count; /* use count, 0 or 1 for non-shared indicators */
|
||||
};
|
||||
static struct indicator_t *q_indicators;
|
||||
struct indicator_t *q_indicators;
|
||||
|
||||
static int css_qdio_omit_svs;
|
||||
|
||||
static u64 last_ai_time;
|
||||
|
||||
static inline unsigned long do_clear_global_summary(void)
|
||||
{
|
||||
register unsigned long __fn asm("1") = 3;
|
||||
|
|
@ -116,59 +112,73 @@ void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr)
|
|||
}
|
||||
}
|
||||
|
||||
static inline int shared_ind(struct qdio_irq *irq_ptr)
|
||||
static inline int shared_ind_used(void)
|
||||
{
|
||||
return irq_ptr->dsci == &q_indicators[TIQDIO_SHARED_IND].ind;
|
||||
return atomic_read(&q_indicators[TIQDIO_SHARED_IND].count);
|
||||
}
|
||||
|
||||
/**
|
||||
* tiqdio_thinint_handler - thin interrupt handler for qdio
|
||||
* @ind: pointer to adapter local summary indicator
|
||||
* @drv_data: NULL
|
||||
* @alsi: pointer to adapter local summary indicator
|
||||
* @data: NULL
|
||||
*/
|
||||
static void tiqdio_thinint_handler(void *ind, void *drv_data)
|
||||
static void tiqdio_thinint_handler(void *alsi, void *data)
|
||||
{
|
||||
struct qdio_q *q;
|
||||
|
||||
last_ai_time = S390_lowcore.int_clock;
|
||||
|
||||
/*
|
||||
* SVS only when needed: issue SVS to benefit from iqdio interrupt
|
||||
* avoidance (SVS clears adapter interrupt suppression overwrite)
|
||||
* avoidance (SVS clears adapter interrupt suppression overwrite).
|
||||
*/
|
||||
if (!css_qdio_omit_svs)
|
||||
do_clear_global_summary();
|
||||
|
||||
/*
|
||||
* reset local summary indicator (tiqdio_alsi) to stop adapter
|
||||
* interrupts for now
|
||||
*/
|
||||
xchg((u8 *)ind, 0);
|
||||
/* reset local summary indicator */
|
||||
if (shared_ind_used())
|
||||
xchg(tiqdio_alsi, 0);
|
||||
|
||||
/* protect tiq_list entries, only changed in activate or shutdown */
|
||||
rcu_read_lock();
|
||||
|
||||
/* check for work on all inbound thinint queues */
|
||||
list_for_each_entry_rcu(q, &tiq_list, entry)
|
||||
/* only process queues from changed sets */
|
||||
if (*q->irq_ptr->dsci) {
|
||||
qperf_inc(q, adapter_int);
|
||||
list_for_each_entry_rcu(q, &tiq_list, entry) {
|
||||
|
||||
/* only process queues from changed sets */
|
||||
if (!*q->irq_ptr->dsci)
|
||||
continue;
|
||||
|
||||
if (q->u.in.queue_start_poll) {
|
||||
/* skip if polling is enabled or already in work */
|
||||
if (test_and_set_bit(QDIO_QUEUE_IRQS_DISABLED,
|
||||
&q->u.in.queue_irq_state)) {
|
||||
qperf_inc(q, int_discarded);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* avoid dsci clear here, done after processing */
|
||||
q->u.in.queue_start_poll(q->irq_ptr->cdev, q->nr,
|
||||
q->irq_ptr->int_parm);
|
||||
} else {
|
||||
/* only clear it if the indicator is non-shared */
|
||||
if (!shared_ind(q->irq_ptr))
|
||||
xchg(q->irq_ptr->dsci, 0);
|
||||
/*
|
||||
* don't call inbound processing directly since
|
||||
* that could starve other thinint queues
|
||||
* Call inbound processing but not directly
|
||||
* since that could starve other thinint queues.
|
||||
*/
|
||||
tasklet_schedule(&q->tasklet);
|
||||
}
|
||||
|
||||
qperf_inc(q, adapter_int);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
/*
|
||||
* if we used the shared indicator clear it now after all queues
|
||||
* were processed
|
||||
* If the shared indicator was used clear it now after all queues
|
||||
* were processed.
|
||||
*/
|
||||
if (atomic_read(&q_indicators[TIQDIO_SHARED_IND].count)) {
|
||||
if (shared_ind_used()) {
|
||||
xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 0);
|
||||
|
||||
/* prevent racing */
|
||||
|
|
|
|||
|
|
@ -100,6 +100,6 @@ config QETH_IPV6
|
|||
|
||||
config CCWGROUP
|
||||
tristate
|
||||
default (LCS || CTCM || QETH)
|
||||
default (LCS || CTCM || QETH || CLAW)
|
||||
|
||||
endmenu
|
||||
|
|
|
|||
|
|
@ -540,7 +540,7 @@ void ctc_mpc_dealloc_ch(int port_num)
|
|||
|
||||
CTCM_DBF_TEXT_(MPC_SETUP, CTC_DBF_DEBUG,
|
||||
"%s: %s: refcount = %d\n",
|
||||
CTCM_FUNTAIL, dev->name, atomic_read(&dev->refcnt));
|
||||
CTCM_FUNTAIL, dev->name, netdev_refcnt_read(dev));
|
||||
|
||||
fsm_deltimer(&priv->restart_timer);
|
||||
grp->channels_terminating = 0;
|
||||
|
|
|
|||
|
|
@ -676,6 +676,7 @@ enum qeth_discipline_id {
|
|||
};
|
||||
|
||||
struct qeth_discipline {
|
||||
void (*start_poll)(struct ccw_device *, int, unsigned long);
|
||||
qdio_handler_t *input_handler;
|
||||
qdio_handler_t *output_handler;
|
||||
int (*recover)(void *ptr);
|
||||
|
|
@ -702,6 +703,16 @@ struct qeth_skb_data {
|
|||
#define QETH_SKB_MAGIC 0x71657468
|
||||
#define QETH_SIGA_CC2_RETRIES 3
|
||||
|
||||
struct qeth_rx {
|
||||
int b_count;
|
||||
int b_index;
|
||||
struct qdio_buffer_element *b_element;
|
||||
int e_offset;
|
||||
int qdio_err;
|
||||
};
|
||||
|
||||
#define QETH_NAPI_WEIGHT 128
|
||||
|
||||
struct qeth_card {
|
||||
struct list_head list;
|
||||
enum qeth_card_states state;
|
||||
|
|
@ -749,6 +760,8 @@ struct qeth_card {
|
|||
debug_info_t *debug;
|
||||
struct mutex conf_mutex;
|
||||
struct mutex discipline_mutex;
|
||||
struct napi_struct napi;
|
||||
struct qeth_rx rx;
|
||||
};
|
||||
|
||||
struct qeth_card_list_struct {
|
||||
|
|
@ -831,6 +844,10 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *,
|
|||
struct qdio_buffer *, struct qdio_buffer_element **, int *,
|
||||
struct qeth_hdr **);
|
||||
void qeth_schedule_recovery(struct qeth_card *);
|
||||
void qeth_qdio_start_poll(struct ccw_device *, int, unsigned long);
|
||||
void qeth_qdio_input_handler(struct ccw_device *,
|
||||
unsigned int, unsigned int, int,
|
||||
int, unsigned long);
|
||||
void qeth_qdio_output_handler(struct ccw_device *, unsigned int,
|
||||
int, int, int, unsigned long);
|
||||
void qeth_clear_ipacmd_list(struct qeth_card *);
|
||||
|
|
|
|||
|
|
@ -2911,6 +2911,27 @@ static void qeth_check_outbound_queue(struct qeth_qdio_out_q *queue)
|
|||
}
|
||||
}
|
||||
|
||||
void qeth_qdio_start_poll(struct ccw_device *ccwdev, int queue,
|
||||
unsigned long card_ptr)
|
||||
{
|
||||
struct qeth_card *card = (struct qeth_card *)card_ptr;
|
||||
|
||||
if (card->dev)
|
||||
napi_schedule(&card->napi);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qeth_qdio_start_poll);
|
||||
|
||||
void qeth_qdio_input_handler(struct ccw_device *ccwdev, unsigned int qdio_err,
|
||||
unsigned int queue, int first_element, int count,
|
||||
unsigned long card_ptr)
|
||||
{
|
||||
struct qeth_card *card = (struct qeth_card *)card_ptr;
|
||||
|
||||
if (qdio_err)
|
||||
qeth_schedule_recovery(card);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qeth_qdio_input_handler);
|
||||
|
||||
void qeth_qdio_output_handler(struct ccw_device *ccwdev,
|
||||
unsigned int qdio_error, int __queue, int first_element,
|
||||
int count, unsigned long card_ptr)
|
||||
|
|
@ -3843,6 +3864,7 @@ static int qeth_qdio_establish(struct qeth_card *card)
|
|||
init_data.no_output_qs = card->qdio.no_out_queues;
|
||||
init_data.input_handler = card->discipline.input_handler;
|
||||
init_data.output_handler = card->discipline.output_handler;
|
||||
init_data.queue_start_poll = card->discipline.start_poll;
|
||||
init_data.int_parm = (unsigned long) card;
|
||||
init_data.input_sbal_addr_array = (void **) in_sbal_ptrs;
|
||||
init_data.output_sbal_addr_array = (void **) out_sbal_ptrs;
|
||||
|
|
@ -4513,8 +4535,8 @@ static struct {
|
|||
/* 20 */{"queue 1 buffer usage"},
|
||||
{"queue 2 buffer usage"},
|
||||
{"queue 3 buffer usage"},
|
||||
{"rx handler time"},
|
||||
{"rx handler count"},
|
||||
{"rx poll time"},
|
||||
{"rx poll count"},
|
||||
{"rx do_QDIO time"},
|
||||
{"rx do_QDIO count"},
|
||||
{"tx handler time"},
|
||||
|
|
|
|||
|
|
@ -310,6 +310,8 @@ static void qeth_l2_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
|
|||
struct qeth_vlan_vid *id;
|
||||
|
||||
QETH_CARD_TEXT_(card, 4, "aid:%d", vid);
|
||||
if (!vid)
|
||||
return;
|
||||
if (card->info.type == QETH_CARD_TYPE_OSM) {
|
||||
QETH_CARD_TEXT(card, 3, "aidOSM");
|
||||
return;
|
||||
|
|
@ -407,29 +409,25 @@ static int qeth_l2_stop_card(struct qeth_card *card, int recovery_mode)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static void qeth_l2_process_inbound_buffer(struct qeth_card *card,
|
||||
struct qeth_qdio_buffer *buf, int index)
|
||||
static int qeth_l2_process_inbound_buffer(struct qeth_card *card,
|
||||
int budget, int *done)
|
||||
{
|
||||
struct qdio_buffer_element *element;
|
||||
int work_done = 0;
|
||||
struct sk_buff *skb;
|
||||
struct qeth_hdr *hdr;
|
||||
int offset;
|
||||
unsigned int len;
|
||||
|
||||
/* get first element of current buffer */
|
||||
element = (struct qdio_buffer_element *)&buf->buffer->element[0];
|
||||
offset = 0;
|
||||
if (card->options.performance_stats)
|
||||
card->perf_stats.bufs_rec++;
|
||||
while ((skb = qeth_core_get_next_skb(card, buf->buffer, &element,
|
||||
&offset, &hdr))) {
|
||||
skb->dev = card->dev;
|
||||
/* is device UP ? */
|
||||
if (!(card->dev->flags & IFF_UP)) {
|
||||
dev_kfree_skb_any(skb);
|
||||
continue;
|
||||
*done = 0;
|
||||
BUG_ON(!budget);
|
||||
while (budget) {
|
||||
skb = qeth_core_get_next_skb(card,
|
||||
card->qdio.in_q->bufs[card->rx.b_index].buffer,
|
||||
&card->rx.b_element, &card->rx.e_offset, &hdr);
|
||||
if (!skb) {
|
||||
*done = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
skb->dev = card->dev;
|
||||
switch (hdr->hdr.l2.id) {
|
||||
case QETH_HEADER_TYPE_LAYER2:
|
||||
skb->pkt_type = PACKET_HOST;
|
||||
|
|
@ -441,7 +439,7 @@ static void qeth_l2_process_inbound_buffer(struct qeth_card *card,
|
|||
if (skb->protocol == htons(ETH_P_802_2))
|
||||
*((__u32 *)skb->cb) = ++card->seqno.pkt_seqno;
|
||||
len = skb->len;
|
||||
netif_rx(skb);
|
||||
netif_receive_skb(skb);
|
||||
break;
|
||||
case QETH_HEADER_TYPE_OSN:
|
||||
if (card->info.type == QETH_CARD_TYPE_OSN) {
|
||||
|
|
@ -459,9 +457,87 @@ static void qeth_l2_process_inbound_buffer(struct qeth_card *card,
|
|||
QETH_DBF_HEX(CTRL, 3, hdr, QETH_DBF_CTRL_LEN);
|
||||
continue;
|
||||
}
|
||||
work_done++;
|
||||
budget--;
|
||||
card->stats.rx_packets++;
|
||||
card->stats.rx_bytes += len;
|
||||
}
|
||||
return work_done;
|
||||
}
|
||||
|
||||
static int qeth_l2_poll(struct napi_struct *napi, int budget)
|
||||
{
|
||||
struct qeth_card *card = container_of(napi, struct qeth_card, napi);
|
||||
int work_done = 0;
|
||||
struct qeth_qdio_buffer *buffer;
|
||||
int done;
|
||||
int new_budget = budget;
|
||||
|
||||
if (card->options.performance_stats) {
|
||||
card->perf_stats.inbound_cnt++;
|
||||
card->perf_stats.inbound_start_time = qeth_get_micros();
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (!card->rx.b_count) {
|
||||
card->rx.qdio_err = 0;
|
||||
card->rx.b_count = qdio_get_next_buffers(
|
||||
card->data.ccwdev, 0, &card->rx.b_index,
|
||||
&card->rx.qdio_err);
|
||||
if (card->rx.b_count <= 0) {
|
||||
card->rx.b_count = 0;
|
||||
break;
|
||||
}
|
||||
card->rx.b_element =
|
||||
&card->qdio.in_q->bufs[card->rx.b_index]
|
||||
.buffer->element[0];
|
||||
card->rx.e_offset = 0;
|
||||
}
|
||||
|
||||
while (card->rx.b_count) {
|
||||
buffer = &card->qdio.in_q->bufs[card->rx.b_index];
|
||||
if (!(card->rx.qdio_err &&
|
||||
qeth_check_qdio_errors(card, buffer->buffer,
|
||||
card->rx.qdio_err, "qinerr")))
|
||||
work_done += qeth_l2_process_inbound_buffer(
|
||||
card, new_budget, &done);
|
||||
else
|
||||
done = 1;
|
||||
|
||||
if (done) {
|
||||
if (card->options.performance_stats)
|
||||
card->perf_stats.bufs_rec++;
|
||||
qeth_put_buffer_pool_entry(card,
|
||||
buffer->pool_entry);
|
||||
qeth_queue_input_buffer(card, card->rx.b_index);
|
||||
card->rx.b_count--;
|
||||
if (card->rx.b_count) {
|
||||
card->rx.b_index =
|
||||
(card->rx.b_index + 1) %
|
||||
QDIO_MAX_BUFFERS_PER_Q;
|
||||
card->rx.b_element =
|
||||
&card->qdio.in_q
|
||||
->bufs[card->rx.b_index]
|
||||
.buffer->element[0];
|
||||
card->rx.e_offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (work_done >= budget)
|
||||
goto out;
|
||||
else
|
||||
new_budget = budget - work_done;
|
||||
}
|
||||
}
|
||||
|
||||
napi_complete(napi);
|
||||
if (qdio_start_irq(card->data.ccwdev, 0))
|
||||
napi_schedule(&card->napi);
|
||||
out:
|
||||
if (card->options.performance_stats)
|
||||
card->perf_stats.inbound_time += qeth_get_micros() -
|
||||
card->perf_stats.inbound_start_time;
|
||||
return work_done;
|
||||
}
|
||||
|
||||
static int qeth_l2_send_setdelmac(struct qeth_card *card, __u8 *mac,
|
||||
|
|
@ -755,49 +831,10 @@ tx_drop:
|
|||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
static void qeth_l2_qdio_input_handler(struct ccw_device *ccwdev,
|
||||
unsigned int qdio_err, unsigned int queue,
|
||||
int first_element, int count, unsigned long card_ptr)
|
||||
{
|
||||
struct net_device *net_dev;
|
||||
struct qeth_card *card;
|
||||
struct qeth_qdio_buffer *buffer;
|
||||
int index;
|
||||
int i;
|
||||
|
||||
card = (struct qeth_card *) card_ptr;
|
||||
net_dev = card->dev;
|
||||
if (card->options.performance_stats) {
|
||||
card->perf_stats.inbound_cnt++;
|
||||
card->perf_stats.inbound_start_time = qeth_get_micros();
|
||||
}
|
||||
if (qdio_err & QDIO_ERROR_ACTIVATE_CHECK_CONDITION) {
|
||||
QETH_CARD_TEXT(card, 1, "qdinchk");
|
||||
QETH_CARD_TEXT_(card, 1, "%04X%04X", first_element,
|
||||
count);
|
||||
QETH_CARD_TEXT_(card, 1, "%04X", queue);
|
||||
qeth_schedule_recovery(card);
|
||||
return;
|
||||
}
|
||||
for (i = first_element; i < (first_element + count); ++i) {
|
||||
index = i % QDIO_MAX_BUFFERS_PER_Q;
|
||||
buffer = &card->qdio.in_q->bufs[index];
|
||||
if (!(qdio_err &&
|
||||
qeth_check_qdio_errors(card, buffer->buffer, qdio_err,
|
||||
"qinerr")))
|
||||
qeth_l2_process_inbound_buffer(card, buffer, index);
|
||||
/* clear buffer and give back to hardware */
|
||||
qeth_put_buffer_pool_entry(card, buffer->pool_entry);
|
||||
qeth_queue_input_buffer(card, index);
|
||||
}
|
||||
if (card->options.performance_stats)
|
||||
card->perf_stats.inbound_time += qeth_get_micros() -
|
||||
card->perf_stats.inbound_start_time;
|
||||
}
|
||||
|
||||
static int qeth_l2_open(struct net_device *dev)
|
||||
{
|
||||
struct qeth_card *card = dev->ml_priv;
|
||||
int rc = 0;
|
||||
|
||||
QETH_CARD_TEXT(card, 4, "qethopen");
|
||||
if (card->state != CARD_STATE_SOFTSETUP)
|
||||
|
|
@ -814,18 +851,24 @@ static int qeth_l2_open(struct net_device *dev)
|
|||
|
||||
if (!card->lan_online && netif_carrier_ok(dev))
|
||||
netif_carrier_off(dev);
|
||||
return 0;
|
||||
if (qdio_stop_irq(card->data.ccwdev, 0) >= 0) {
|
||||
napi_enable(&card->napi);
|
||||
napi_schedule(&card->napi);
|
||||
} else
|
||||
rc = -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static int qeth_l2_stop(struct net_device *dev)
|
||||
{
|
||||
struct qeth_card *card = dev->ml_priv;
|
||||
|
||||
QETH_CARD_TEXT(card, 4, "qethstop");
|
||||
netif_tx_disable(dev);
|
||||
if (card->state == CARD_STATE_UP)
|
||||
if (card->state == CARD_STATE_UP) {
|
||||
card->state = CARD_STATE_SOFTSETUP;
|
||||
napi_disable(&card->napi);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -836,8 +879,9 @@ static int qeth_l2_probe_device(struct ccwgroup_device *gdev)
|
|||
INIT_LIST_HEAD(&card->vid_list);
|
||||
INIT_LIST_HEAD(&card->mc_list);
|
||||
card->options.layer2 = 1;
|
||||
card->discipline.start_poll = qeth_qdio_start_poll;
|
||||
card->discipline.input_handler = (qdio_handler_t *)
|
||||
qeth_l2_qdio_input_handler;
|
||||
qeth_qdio_input_handler;
|
||||
card->discipline.output_handler = (qdio_handler_t *)
|
||||
qeth_qdio_output_handler;
|
||||
card->discipline.recover = qeth_l2_recover;
|
||||
|
|
@ -923,6 +967,7 @@ static int qeth_l2_setup_netdev(struct qeth_card *card)
|
|||
card->info.broadcast_capable = 1;
|
||||
qeth_l2_request_initial_mac(card);
|
||||
SET_NETDEV_DEV(card->dev, &card->gdev->dev);
|
||||
netif_napi_add(card->dev, &card->napi, qeth_l2_poll, QETH_NAPI_WEIGHT);
|
||||
return register_netdev(card->dev);
|
||||
}
|
||||
|
||||
|
|
@ -955,6 +1000,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
|
|||
qeth_l2_send_setmac(card, &card->dev->dev_addr[0]);
|
||||
|
||||
card->state = CARD_STATE_HARDSETUP;
|
||||
memset(&card->rx, 0, sizeof(struct qeth_rx));
|
||||
qeth_print_status_message(card);
|
||||
|
||||
/* softsetup */
|
||||
|
|
@ -1086,9 +1132,6 @@ static int qeth_l2_recover(void *ptr)
|
|||
card->use_hard_stop = 1;
|
||||
__qeth_l2_set_offline(card->gdev, 1);
|
||||
rc = __qeth_l2_set_online(card->gdev, 1);
|
||||
/* don't run another scheduled recovery */
|
||||
qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
|
||||
qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
|
||||
if (!rc)
|
||||
dev_info(&card->gdev->dev,
|
||||
"Device successfully recovered!\n");
|
||||
|
|
@ -1099,6 +1142,8 @@ static int qeth_l2_recover(void *ptr)
|
|||
dev_warn(&card->gdev->dev, "The qeth device driver "
|
||||
"failed to recover an error on the device\n");
|
||||
}
|
||||
qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
|
||||
qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -103,12 +103,7 @@ int qeth_l3_string_to_ipaddr4(const char *buf, __u8 *addr)
|
|||
|
||||
void qeth_l3_ipaddr6_to_string(const __u8 *addr, char *buf)
|
||||
{
|
||||
sprintf(buf, "%02x%02x:%02x%02x:%02x%02x:%02x%02x"
|
||||
":%02x%02x:%02x%02x:%02x%02x:%02x%02x",
|
||||
addr[0], addr[1], addr[2], addr[3],
|
||||
addr[4], addr[5], addr[6], addr[7],
|
||||
addr[8], addr[9], addr[10], addr[11],
|
||||
addr[12], addr[13], addr[14], addr[15]);
|
||||
sprintf(buf, "%pI6", addr);
|
||||
}
|
||||
|
||||
int qeth_l3_string_to_ipaddr6(const char *buf, __u8 *addr)
|
||||
|
|
@ -1825,7 +1820,7 @@ static void qeth_l3_add_vlan_mc(struct qeth_card *card)
|
|||
return;
|
||||
|
||||
vg = card->vlangrp;
|
||||
for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
|
||||
for (i = 0; i < VLAN_N_VID; i++) {
|
||||
struct net_device *netdev = vlan_group_get_device(vg, i);
|
||||
if (netdev == NULL ||
|
||||
!(netdev->flags & IFF_UP))
|
||||
|
|
@ -1888,7 +1883,7 @@ static void qeth_l3_add_vlan_mc6(struct qeth_card *card)
|
|||
return;
|
||||
|
||||
vg = card->vlangrp;
|
||||
for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
|
||||
for (i = 0; i < VLAN_N_VID; i++) {
|
||||
struct net_device *netdev = vlan_group_get_device(vg, i);
|
||||
if (netdev == NULL ||
|
||||
!(netdev->flags & IFF_UP))
|
||||
|
|
@ -2018,13 +2013,14 @@ static void qeth_l3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
|
|||
qeth_l3_set_multicast_list(card->dev);
|
||||
}
|
||||
|
||||
static inline __u16 qeth_l3_rebuild_skb(struct qeth_card *card,
|
||||
struct sk_buff *skb, struct qeth_hdr *hdr)
|
||||
static inline int qeth_l3_rebuild_skb(struct qeth_card *card,
|
||||
struct sk_buff *skb, struct qeth_hdr *hdr,
|
||||
unsigned short *vlan_id)
|
||||
{
|
||||
unsigned short vlan_id = 0;
|
||||
__be16 prot;
|
||||
struct iphdr *ip_hdr;
|
||||
unsigned char tg_addr[MAX_ADDR_LEN];
|
||||
int is_vlan = 0;
|
||||
|
||||
if (!(hdr->hdr.l3.flags & QETH_HDR_PASSTHRU)) {
|
||||
prot = htons((hdr->hdr.l3.flags & QETH_HDR_IPV6)? ETH_P_IPV6 :
|
||||
|
|
@ -2087,8 +2083,9 @@ static inline __u16 qeth_l3_rebuild_skb(struct qeth_card *card,
|
|||
|
||||
if (hdr->hdr.l3.ext_flags &
|
||||
(QETH_HDR_EXT_VLAN_FRAME | QETH_HDR_EXT_INCLUDE_VLAN_TAG)) {
|
||||
vlan_id = (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_VLAN_FRAME)?
|
||||
*vlan_id = (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_VLAN_FRAME) ?
|
||||
hdr->hdr.l3.vlan_id : *((u16 *)&hdr->hdr.l3.dest_addr[12]);
|
||||
is_vlan = 1;
|
||||
}
|
||||
|
||||
switch (card->options.checksum_type) {
|
||||
|
|
@ -2109,54 +2106,44 @@ static inline __u16 qeth_l3_rebuild_skb(struct qeth_card *card,
|
|||
skb->ip_summed = CHECKSUM_NONE;
|
||||
}
|
||||
|
||||
return vlan_id;
|
||||
return is_vlan;
|
||||
}
|
||||
|
||||
static void qeth_l3_process_inbound_buffer(struct qeth_card *card,
|
||||
struct qeth_qdio_buffer *buf, int index)
|
||||
static int qeth_l3_process_inbound_buffer(struct qeth_card *card,
|
||||
int budget, int *done)
|
||||
{
|
||||
struct qdio_buffer_element *element;
|
||||
int work_done = 0;
|
||||
struct sk_buff *skb;
|
||||
struct qeth_hdr *hdr;
|
||||
int offset;
|
||||
__u16 vlan_tag = 0;
|
||||
int is_vlan;
|
||||
unsigned int len;
|
||||
/* get first element of current buffer */
|
||||
element = (struct qdio_buffer_element *)&buf->buffer->element[0];
|
||||
offset = 0;
|
||||
if (card->options.performance_stats)
|
||||
card->perf_stats.bufs_rec++;
|
||||
while ((skb = qeth_core_get_next_skb(card, buf->buffer, &element,
|
||||
&offset, &hdr))) {
|
||||
skb->dev = card->dev;
|
||||
/* is device UP ? */
|
||||
if (!(card->dev->flags & IFF_UP)) {
|
||||
dev_kfree_skb_any(skb);
|
||||
continue;
|
||||
}
|
||||
|
||||
*done = 0;
|
||||
BUG_ON(!budget);
|
||||
while (budget) {
|
||||
skb = qeth_core_get_next_skb(card,
|
||||
card->qdio.in_q->bufs[card->rx.b_index].buffer,
|
||||
&card->rx.b_element, &card->rx.e_offset, &hdr);
|
||||
if (!skb) {
|
||||
*done = 1;
|
||||
break;
|
||||
}
|
||||
skb->dev = card->dev;
|
||||
switch (hdr->hdr.l3.id) {
|
||||
case QETH_HEADER_TYPE_LAYER3:
|
||||
vlan_tag = qeth_l3_rebuild_skb(card, skb, hdr);
|
||||
is_vlan = qeth_l3_rebuild_skb(card, skb, hdr,
|
||||
&vlan_tag);
|
||||
len = skb->len;
|
||||
if (vlan_tag && !card->options.sniffer)
|
||||
if (card->vlangrp)
|
||||
vlan_hwaccel_rx(skb, card->vlangrp,
|
||||
vlan_tag);
|
||||
else {
|
||||
dev_kfree_skb_any(skb);
|
||||
continue;
|
||||
}
|
||||
if (is_vlan && !card->options.sniffer)
|
||||
vlan_gro_receive(&card->napi, card->vlangrp,
|
||||
vlan_tag, skb);
|
||||
else
|
||||
netif_rx(skb);
|
||||
napi_gro_receive(&card->napi, skb);
|
||||
break;
|
||||
case QETH_HEADER_TYPE_LAYER2: /* for HiperSockets sniffer */
|
||||
skb->pkt_type = PACKET_HOST;
|
||||
skb->protocol = eth_type_trans(skb, skb->dev);
|
||||
if (card->options.checksum_type == NO_CHECKSUMMING)
|
||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
else
|
||||
skb->ip_summed = CHECKSUM_NONE;
|
||||
len = skb->len;
|
||||
netif_receive_skb(skb);
|
||||
break;
|
||||
|
|
@ -2166,10 +2153,87 @@ static void qeth_l3_process_inbound_buffer(struct qeth_card *card,
|
|||
QETH_DBF_HEX(CTRL, 3, hdr, QETH_DBF_CTRL_LEN);
|
||||
continue;
|
||||
}
|
||||
|
||||
work_done++;
|
||||
budget--;
|
||||
card->stats.rx_packets++;
|
||||
card->stats.rx_bytes += len;
|
||||
}
|
||||
return work_done;
|
||||
}
|
||||
|
||||
static int qeth_l3_poll(struct napi_struct *napi, int budget)
|
||||
{
|
||||
struct qeth_card *card = container_of(napi, struct qeth_card, napi);
|
||||
int work_done = 0;
|
||||
struct qeth_qdio_buffer *buffer;
|
||||
int done;
|
||||
int new_budget = budget;
|
||||
|
||||
if (card->options.performance_stats) {
|
||||
card->perf_stats.inbound_cnt++;
|
||||
card->perf_stats.inbound_start_time = qeth_get_micros();
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (!card->rx.b_count) {
|
||||
card->rx.qdio_err = 0;
|
||||
card->rx.b_count = qdio_get_next_buffers(
|
||||
card->data.ccwdev, 0, &card->rx.b_index,
|
||||
&card->rx.qdio_err);
|
||||
if (card->rx.b_count <= 0) {
|
||||
card->rx.b_count = 0;
|
||||
break;
|
||||
}
|
||||
card->rx.b_element =
|
||||
&card->qdio.in_q->bufs[card->rx.b_index]
|
||||
.buffer->element[0];
|
||||
card->rx.e_offset = 0;
|
||||
}
|
||||
|
||||
while (card->rx.b_count) {
|
||||
buffer = &card->qdio.in_q->bufs[card->rx.b_index];
|
||||
if (!(card->rx.qdio_err &&
|
||||
qeth_check_qdio_errors(card, buffer->buffer,
|
||||
card->rx.qdio_err, "qinerr")))
|
||||
work_done += qeth_l3_process_inbound_buffer(
|
||||
card, new_budget, &done);
|
||||
else
|
||||
done = 1;
|
||||
|
||||
if (done) {
|
||||
if (card->options.performance_stats)
|
||||
card->perf_stats.bufs_rec++;
|
||||
qeth_put_buffer_pool_entry(card,
|
||||
buffer->pool_entry);
|
||||
qeth_queue_input_buffer(card, card->rx.b_index);
|
||||
card->rx.b_count--;
|
||||
if (card->rx.b_count) {
|
||||
card->rx.b_index =
|
||||
(card->rx.b_index + 1) %
|
||||
QDIO_MAX_BUFFERS_PER_Q;
|
||||
card->rx.b_element =
|
||||
&card->qdio.in_q
|
||||
->bufs[card->rx.b_index]
|
||||
.buffer->element[0];
|
||||
card->rx.e_offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (work_done >= budget)
|
||||
goto out;
|
||||
else
|
||||
new_budget = budget - work_done;
|
||||
}
|
||||
}
|
||||
|
||||
napi_complete(napi);
|
||||
if (qdio_start_irq(card->data.ccwdev, 0))
|
||||
napi_schedule(&card->napi);
|
||||
out:
|
||||
if (card->options.performance_stats)
|
||||
card->perf_stats.inbound_time += qeth_get_micros() -
|
||||
card->perf_stats.inbound_start_time;
|
||||
return work_done;
|
||||
}
|
||||
|
||||
static int qeth_l3_verify_vlan_dev(struct net_device *dev,
|
||||
|
|
@ -2183,7 +2247,7 @@ static int qeth_l3_verify_vlan_dev(struct net_device *dev,
|
|||
if (!vg)
|
||||
return rc;
|
||||
|
||||
for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
|
||||
for (i = 0; i < VLAN_N_VID; i++) {
|
||||
if (vlan_group_get_device(vg, i) == dev) {
|
||||
rc = QETH_VLAN_CARD;
|
||||
break;
|
||||
|
|
@ -3103,6 +3167,7 @@ tx_drop:
|
|||
static int qeth_l3_open(struct net_device *dev)
|
||||
{
|
||||
struct qeth_card *card = dev->ml_priv;
|
||||
int rc = 0;
|
||||
|
||||
QETH_CARD_TEXT(card, 4, "qethopen");
|
||||
if (card->state != CARD_STATE_SOFTSETUP)
|
||||
|
|
@ -3113,7 +3178,12 @@ static int qeth_l3_open(struct net_device *dev)
|
|||
|
||||
if (!card->lan_online && netif_carrier_ok(dev))
|
||||
netif_carrier_off(dev);
|
||||
return 0;
|
||||
if (qdio_stop_irq(card->data.ccwdev, 0) >= 0) {
|
||||
napi_enable(&card->napi);
|
||||
napi_schedule(&card->napi);
|
||||
} else
|
||||
rc = -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int qeth_l3_stop(struct net_device *dev)
|
||||
|
|
@ -3122,8 +3192,10 @@ static int qeth_l3_stop(struct net_device *dev)
|
|||
|
||||
QETH_CARD_TEXT(card, 4, "qethstop");
|
||||
netif_tx_disable(dev);
|
||||
if (card->state == CARD_STATE_UP)
|
||||
if (card->state == CARD_STATE_UP) {
|
||||
card->state = CARD_STATE_SOFTSETUP;
|
||||
napi_disable(&card->napi);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -3293,57 +3365,19 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
|
|||
card->dev->gso_max_size = 15 * PAGE_SIZE;
|
||||
|
||||
SET_NETDEV_DEV(card->dev, &card->gdev->dev);
|
||||
netif_napi_add(card->dev, &card->napi, qeth_l3_poll, QETH_NAPI_WEIGHT);
|
||||
return register_netdev(card->dev);
|
||||
}
|
||||
|
||||
static void qeth_l3_qdio_input_handler(struct ccw_device *ccwdev,
|
||||
unsigned int qdio_err, unsigned int queue, int first_element,
|
||||
int count, unsigned long card_ptr)
|
||||
{
|
||||
struct net_device *net_dev;
|
||||
struct qeth_card *card;
|
||||
struct qeth_qdio_buffer *buffer;
|
||||
int index;
|
||||
int i;
|
||||
|
||||
card = (struct qeth_card *) card_ptr;
|
||||
net_dev = card->dev;
|
||||
if (card->options.performance_stats) {
|
||||
card->perf_stats.inbound_cnt++;
|
||||
card->perf_stats.inbound_start_time = qeth_get_micros();
|
||||
}
|
||||
if (qdio_err & QDIO_ERROR_ACTIVATE_CHECK_CONDITION) {
|
||||
QETH_CARD_TEXT(card, 1, "qdinchk");
|
||||
QETH_CARD_TEXT_(card, 1, "%04X%04X",
|
||||
first_element, count);
|
||||
QETH_CARD_TEXT_(card, 1, "%04X", queue);
|
||||
qeth_schedule_recovery(card);
|
||||
return;
|
||||
}
|
||||
for (i = first_element; i < (first_element + count); ++i) {
|
||||
index = i % QDIO_MAX_BUFFERS_PER_Q;
|
||||
buffer = &card->qdio.in_q->bufs[index];
|
||||
if (!(qdio_err &&
|
||||
qeth_check_qdio_errors(card, buffer->buffer,
|
||||
qdio_err, "qinerr")))
|
||||
qeth_l3_process_inbound_buffer(card, buffer, index);
|
||||
/* clear buffer and give back to hardware */
|
||||
qeth_put_buffer_pool_entry(card, buffer->pool_entry);
|
||||
qeth_queue_input_buffer(card, index);
|
||||
}
|
||||
if (card->options.performance_stats)
|
||||
card->perf_stats.inbound_time += qeth_get_micros() -
|
||||
card->perf_stats.inbound_start_time;
|
||||
}
|
||||
|
||||
static int qeth_l3_probe_device(struct ccwgroup_device *gdev)
|
||||
{
|
||||
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
|
||||
|
||||
qeth_l3_create_device_attributes(&gdev->dev);
|
||||
card->options.layer2 = 0;
|
||||
card->discipline.start_poll = qeth_qdio_start_poll;
|
||||
card->discipline.input_handler = (qdio_handler_t *)
|
||||
qeth_l3_qdio_input_handler;
|
||||
qeth_qdio_input_handler;
|
||||
card->discipline.output_handler = (qdio_handler_t *)
|
||||
qeth_qdio_output_handler;
|
||||
card->discipline.recover = qeth_l3_recover;
|
||||
|
|
@ -3402,6 +3436,7 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
|
|||
}
|
||||
|
||||
card->state = CARD_STATE_HARDSETUP;
|
||||
memset(&card->rx, 0, sizeof(struct qeth_rx));
|
||||
qeth_print_status_message(card);
|
||||
|
||||
/* softsetup */
|
||||
|
|
@ -3538,9 +3573,6 @@ static int qeth_l3_recover(void *ptr)
|
|||
card->use_hard_stop = 1;
|
||||
__qeth_l3_set_offline(card->gdev, 1);
|
||||
rc = __qeth_l3_set_online(card->gdev, 1);
|
||||
/* don't run another scheduled recovery */
|
||||
qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
|
||||
qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
|
||||
if (!rc)
|
||||
dev_info(&card->gdev->dev,
|
||||
"Device successfully recovered!\n");
|
||||
|
|
@ -3551,6 +3583,8 @@ static int qeth_l3_recover(void *ptr)
|
|||
dev_warn(&card->gdev->dev, "The qeth device driver "
|
||||
"failed to recover an error on the device\n");
|
||||
}
|
||||
qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
|
||||
qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -279,16 +279,12 @@ int zfcp_qdio_send(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
|
|||
static void zfcp_qdio_setup_init_data(struct qdio_initialize *id,
|
||||
struct zfcp_qdio *qdio)
|
||||
{
|
||||
|
||||
memset(id, 0, sizeof(*id));
|
||||
id->cdev = qdio->adapter->ccw_device;
|
||||
id->q_format = QDIO_ZFCP_QFMT;
|
||||
memcpy(id->adapter_name, dev_name(&id->cdev->dev), 8);
|
||||
ASCEBC(id->adapter_name, 8);
|
||||
id->qib_rflags = QIB_RFLAGS_ENABLE_DATA_DIV;
|
||||
id->qib_param_field_format = 0;
|
||||
id->qib_param_field = NULL;
|
||||
id->input_slib_elements = NULL;
|
||||
id->output_slib_elements = NULL;
|
||||
id->no_input_qs = 1;
|
||||
id->no_output_qs = 1;
|
||||
id->input_handler = zfcp_qdio_int_resp;
|
||||
|
|
|
|||
Loading…
Reference in a new issue