diff options
Diffstat (limited to 'drivers/char/pcmcia/ipwireless/hardware.c')
-rw-r--r-- | drivers/char/pcmcia/ipwireless/hardware.c | 24 |
1 files changed, 15 insertions, 9 deletions
diff --git a/drivers/char/pcmcia/ipwireless/hardware.c b/drivers/char/pcmcia/ipwireless/hardware.c index fa9d3c945f31..929101ecbae2 100644 --- a/drivers/char/pcmcia/ipwireless/hardware.c +++ b/drivers/char/pcmcia/ipwireless/hardware.c | |||
@@ -251,10 +251,11 @@ struct ipw_hardware { | |||
251 | int init_loops; | 251 | int init_loops; |
252 | struct timer_list setup_timer; | 252 | struct timer_list setup_timer; |
253 | 253 | ||
254 | /* Flag if hw is ready to send next packet */ | ||
254 | int tx_ready; | 255 | int tx_ready; |
255 | struct list_head tx_queue[NL_NUM_OF_PRIORITIES]; | 256 | /* Count of pending packets to be sent */ |
256 | /* True if any packets are queued for transmission */ | ||
257 | int tx_queued; | 257 | int tx_queued; |
258 | struct list_head tx_queue[NL_NUM_OF_PRIORITIES]; | ||
258 | 259 | ||
259 | int rx_bytes_queued; | 260 | int rx_bytes_queued; |
260 | struct list_head rx_queue; | 261 | struct list_head rx_queue; |
@@ -404,6 +405,8 @@ static int do_send_fragment(struct ipw_hardware *hw, const unsigned char *data, | |||
404 | 405 | ||
405 | spin_lock_irqsave(&hw->spinlock, flags); | 406 | spin_lock_irqsave(&hw->spinlock, flags); |
406 | 407 | ||
408 | hw->tx_ready = 0; | ||
409 | |||
407 | if (hw->hw_version == HW_VERSION_1) { | 410 | if (hw->hw_version == HW_VERSION_1) { |
408 | outw((unsigned short) length, hw->base_port + IODWR); | 411 | outw((unsigned short) length, hw->base_port + IODWR); |
409 | 412 | ||
@@ -492,6 +495,7 @@ static int do_send_packet(struct ipw_hardware *hw, struct ipw_tx_packet *packet) | |||
492 | 495 | ||
493 | spin_lock_irqsave(&hw->spinlock, flags); | 496 | spin_lock_irqsave(&hw->spinlock, flags); |
494 | list_add(&packet->queue, &hw->tx_queue[0]); | 497 | list_add(&packet->queue, &hw->tx_queue[0]); |
498 | hw->tx_queued++; | ||
495 | spin_unlock_irqrestore(&hw->spinlock, flags); | 499 | spin_unlock_irqrestore(&hw->spinlock, flags); |
496 | } else { | 500 | } else { |
497 | if (packet->packet_callback) | 501 | if (packet->packet_callback) |
@@ -586,8 +590,10 @@ static struct ipw_rx_packet *pool_allocate(struct ipw_hardware *hw, | |||
586 | packet = kmalloc(sizeof(struct ipw_rx_packet) + | 590 | packet = kmalloc(sizeof(struct ipw_rx_packet) + |
587 | old_packet->length + minimum_free_space, | 591 | old_packet->length + minimum_free_space, |
588 | GFP_ATOMIC); | 592 | GFP_ATOMIC); |
589 | if (!packet) | 593 | if (!packet) { |
594 | kfree(old_packet); | ||
590 | return NULL; | 595 | return NULL; |
596 | } | ||
591 | memcpy(packet, old_packet, | 597 | memcpy(packet, old_packet, |
592 | sizeof(struct ipw_rx_packet) | 598 | sizeof(struct ipw_rx_packet) |
593 | + old_packet->length); | 599 | + old_packet->length); |
@@ -949,12 +955,10 @@ static int send_pending_packet(struct ipw_hardware *hw, int priority_limit) | |||
949 | unsigned long flags; | 955 | unsigned long flags; |
950 | 956 | ||
951 | spin_lock_irqsave(&hw->spinlock, flags); | 957 | spin_lock_irqsave(&hw->spinlock, flags); |
952 | if (hw->tx_queued && hw->tx_ready != 0) { | 958 | if (hw->tx_queued && hw->tx_ready) { |
953 | int priority; | 959 | int priority; |
954 | struct ipw_tx_packet *packet = NULL; | 960 | struct ipw_tx_packet *packet = NULL; |
955 | 961 | ||
956 | hw->tx_ready--; | ||
957 | |||
958 | /* Pick a packet */ | 962 | /* Pick a packet */ |
959 | for (priority = 0; priority < priority_limit; priority++) { | 963 | for (priority = 0; priority < priority_limit; priority++) { |
960 | if (!list_empty(&hw->tx_queue[priority])) { | 964 | if (!list_empty(&hw->tx_queue[priority])) { |
@@ -963,6 +967,7 @@ static int send_pending_packet(struct ipw_hardware *hw, int priority_limit) | |||
963 | struct ipw_tx_packet, | 967 | struct ipw_tx_packet, |
964 | queue); | 968 | queue); |
965 | 969 | ||
970 | hw->tx_queued--; | ||
966 | list_del(&packet->queue); | 971 | list_del(&packet->queue); |
967 | 972 | ||
968 | break; | 973 | break; |
@@ -973,6 +978,7 @@ static int send_pending_packet(struct ipw_hardware *hw, int priority_limit) | |||
973 | spin_unlock_irqrestore(&hw->spinlock, flags); | 978 | spin_unlock_irqrestore(&hw->spinlock, flags); |
974 | return 0; | 979 | return 0; |
975 | } | 980 | } |
981 | |||
976 | spin_unlock_irqrestore(&hw->spinlock, flags); | 982 | spin_unlock_irqrestore(&hw->spinlock, flags); |
977 | 983 | ||
978 | /* Send */ | 984 | /* Send */ |
@@ -1063,7 +1069,7 @@ static irqreturn_t ipwireless_handle_v1_interrupt(int irq, | |||
1063 | if (irqn & IR_TXINTR) { | 1069 | if (irqn & IR_TXINTR) { |
1064 | ack |= IR_TXINTR; | 1070 | ack |= IR_TXINTR; |
1065 | spin_lock_irqsave(&hw->spinlock, flags); | 1071 | spin_lock_irqsave(&hw->spinlock, flags); |
1066 | hw->tx_ready++; | 1072 | hw->tx_ready = 1; |
1067 | spin_unlock_irqrestore(&hw->spinlock, flags); | 1073 | spin_unlock_irqrestore(&hw->spinlock, flags); |
1068 | } | 1074 | } |
1069 | /* Received data */ | 1075 | /* Received data */ |
@@ -1170,7 +1176,7 @@ static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq, | |||
1170 | if (memrxdone & MEMRX_RX_DONE) { | 1176 | if (memrxdone & MEMRX_RX_DONE) { |
1171 | writew(0, &hw->memory_info_regs->memreg_rx_done); | 1177 | writew(0, &hw->memory_info_regs->memreg_rx_done); |
1172 | spin_lock_irqsave(&hw->spinlock, flags); | 1178 | spin_lock_irqsave(&hw->spinlock, flags); |
1173 | hw->tx_ready++; | 1179 | hw->tx_ready = 1; |
1174 | spin_unlock_irqrestore(&hw->spinlock, flags); | 1180 | spin_unlock_irqrestore(&hw->spinlock, flags); |
1175 | tx = 1; | 1181 | tx = 1; |
1176 | } | 1182 | } |
@@ -1234,7 +1240,7 @@ static void send_packet(struct ipw_hardware *hw, int priority, | |||
1234 | 1240 | ||
1235 | spin_lock_irqsave(&hw->spinlock, flags); | 1241 | spin_lock_irqsave(&hw->spinlock, flags); |
1236 | list_add_tail(&packet->queue, &hw->tx_queue[priority]); | 1242 | list_add_tail(&packet->queue, &hw->tx_queue[priority]); |
1237 | hw->tx_queued = 1; | 1243 | hw->tx_queued++; |
1238 | spin_unlock_irqrestore(&hw->spinlock, flags); | 1244 | spin_unlock_irqrestore(&hw->spinlock, flags); |
1239 | 1245 | ||
1240 | flush_packets_to_hw(hw); | 1246 | flush_packets_to_hw(hw); |