diff options
Diffstat (limited to 'drivers/char/pcmcia/ipwireless/hardware.c')
| -rw-r--r-- | drivers/char/pcmcia/ipwireless/hardware.c | 20 |
1 files changed, 12 insertions, 8 deletions
diff --git a/drivers/char/pcmcia/ipwireless/hardware.c b/drivers/char/pcmcia/ipwireless/hardware.c index fa9d3c945f3..ba6340ae98a 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) |
| @@ -949,12 +953,10 @@ static int send_pending_packet(struct ipw_hardware *hw, int priority_limit) | |||
| 949 | unsigned long flags; | 953 | unsigned long flags; |
| 950 | 954 | ||
| 951 | spin_lock_irqsave(&hw->spinlock, flags); | 955 | spin_lock_irqsave(&hw->spinlock, flags); |
| 952 | if (hw->tx_queued && hw->tx_ready != 0) { | 956 | if (hw->tx_queued && hw->tx_ready) { |
| 953 | int priority; | 957 | int priority; |
| 954 | struct ipw_tx_packet *packet = NULL; | 958 | struct ipw_tx_packet *packet = NULL; |
| 955 | 959 | ||
| 956 | hw->tx_ready--; | ||
| 957 | |||
| 958 | /* Pick a packet */ | 960 | /* Pick a packet */ |
| 959 | for (priority = 0; priority < priority_limit; priority++) { | 961 | for (priority = 0; priority < priority_limit; priority++) { |
| 960 | if (!list_empty(&hw->tx_queue[priority])) { | 962 | if (!list_empty(&hw->tx_queue[priority])) { |
| @@ -963,6 +965,7 @@ static int send_pending_packet(struct ipw_hardware *hw, int priority_limit) | |||
| 963 | struct ipw_tx_packet, | 965 | struct ipw_tx_packet, |
| 964 | queue); | 966 | queue); |
| 965 | 967 | ||
| 968 | hw->tx_queued--; | ||
| 966 | list_del(&packet->queue); | 969 | list_del(&packet->queue); |
| 967 | 970 | ||
| 968 | break; | 971 | break; |
| @@ -973,6 +976,7 @@ static int send_pending_packet(struct ipw_hardware *hw, int priority_limit) | |||
| 973 | spin_unlock_irqrestore(&hw->spinlock, flags); | 976 | spin_unlock_irqrestore(&hw->spinlock, flags); |
| 974 | return 0; | 977 | return 0; |
| 975 | } | 978 | } |
| 979 | |||
| 976 | spin_unlock_irqrestore(&hw->spinlock, flags); | 980 | spin_unlock_irqrestore(&hw->spinlock, flags); |
| 977 | 981 | ||
| 978 | /* Send */ | 982 | /* Send */ |
| @@ -1063,7 +1067,7 @@ static irqreturn_t ipwireless_handle_v1_interrupt(int irq, | |||
| 1063 | if (irqn & IR_TXINTR) { | 1067 | if (irqn & IR_TXINTR) { |
| 1064 | ack |= IR_TXINTR; | 1068 | ack |= IR_TXINTR; |
| 1065 | spin_lock_irqsave(&hw->spinlock, flags); | 1069 | spin_lock_irqsave(&hw->spinlock, flags); |
| 1066 | hw->tx_ready++; | 1070 | hw->tx_ready = 1; |
| 1067 | spin_unlock_irqrestore(&hw->spinlock, flags); | 1071 | spin_unlock_irqrestore(&hw->spinlock, flags); |
| 1068 | } | 1072 | } |
| 1069 | /* Received data */ | 1073 | /* Received data */ |
| @@ -1170,7 +1174,7 @@ static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq, | |||
| 1170 | if (memrxdone & MEMRX_RX_DONE) { | 1174 | if (memrxdone & MEMRX_RX_DONE) { |
| 1171 | writew(0, &hw->memory_info_regs->memreg_rx_done); | 1175 | writew(0, &hw->memory_info_regs->memreg_rx_done); |
| 1172 | spin_lock_irqsave(&hw->spinlock, flags); | 1176 | spin_lock_irqsave(&hw->spinlock, flags); |
| 1173 | hw->tx_ready++; | 1177 | hw->tx_ready = 1; |
| 1174 | spin_unlock_irqrestore(&hw->spinlock, flags); | 1178 | spin_unlock_irqrestore(&hw->spinlock, flags); |
| 1175 | tx = 1; | 1179 | tx = 1; |
| 1176 | } | 1180 | } |
| @@ -1234,7 +1238,7 @@ static void send_packet(struct ipw_hardware *hw, int priority, | |||
| 1234 | 1238 | ||
| 1235 | spin_lock_irqsave(&hw->spinlock, flags); | 1239 | spin_lock_irqsave(&hw->spinlock, flags); |
| 1236 | list_add_tail(&packet->queue, &hw->tx_queue[priority]); | 1240 | list_add_tail(&packet->queue, &hw->tx_queue[priority]); |
| 1237 | hw->tx_queued = 1; | 1241 | hw->tx_queued++; |
| 1238 | spin_unlock_irqrestore(&hw->spinlock, flags); | 1242 | spin_unlock_irqrestore(&hw->spinlock, flags); |
| 1239 | 1243 | ||
| 1240 | flush_packets_to_hw(hw); | 1244 | flush_packets_to_hw(hw); |
