aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/airo.c
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2009-01-24 09:04:12 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-01-29 16:01:38 -0500
commitf55d4517ebdd6de627d42a24baefaeb689978087 (patch)
tree78451db08c876d5d536d0f6a15a3e3bef0a7cfca /drivers/net/wireless/airo.c
parent0d21044effa10044930419c6f837f75191229c3a (diff)
airo: clean up and clarify interrupt-time task handling
Split each specific interrupt-time task out into its own function to make airo_interrupt() actually readable. Signed-off-by: Dan Williams <dcbw@redhat.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/airo.c')
-rw-r--r--drivers/net/wireless/airo.c613
1 files changed, 327 insertions, 286 deletions
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 2ff588bb0a7c..a192c4472e02 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -981,6 +981,14 @@ typedef struct {
981 dma_addr_t host_addr; 981 dma_addr_t host_addr;
982} TxFid; 982} TxFid;
983 983
984struct rx_hdr {
985 __le16 status, len;
986 u8 rssi[2];
987 u8 rate;
988 u8 freq;
989 __le16 tmp[4];
990} __attribute__ ((packed));
991
984typedef struct { 992typedef struct {
985 unsigned int ctl: 15; 993 unsigned int ctl: 15;
986 unsigned int rdy: 1; 994 unsigned int rdy: 1;
@@ -3123,314 +3131,354 @@ static int header_len(__le16 ctl)
3123 return 24; 3131 return 24;
3124} 3132}
3125 3133
3126static irqreturn_t airo_interrupt(int irq, void *dev_id) 3134static void airo_handle_cisco_mic(struct airo_info *ai)
3127{ 3135{
3128 struct net_device *dev = dev_id; 3136 if (test_bit(FLAG_MIC_CAPABLE, &ai->flags)) {
3137 set_bit(JOB_MIC, &ai->jobs);
3138 wake_up_interruptible(&ai->thr_wait);
3139 }
3140}
3141
3142/* Airo Status codes */
3143#define STAT_NOBEACON 0x8000 /* Loss of sync - missed beacons */
3144#define STAT_MAXRETRIES 0x8001 /* Loss of sync - max retries */
3145#define STAT_MAXARL 0x8002 /* Loss of sync - average retry level exceeded*/
3146#define STAT_FORCELOSS 0x8003 /* Loss of sync - host request */
3147#define STAT_TSFSYNC 0x8004 /* Loss of sync - TSF synchronization */
3148#define STAT_DEAUTH 0x8100 /* low byte is 802.11 reason code */
3149#define STAT_DISASSOC 0x8200 /* low byte is 802.11 reason code */
3150#define STAT_ASSOC_FAIL 0x8400 /* low byte is 802.11 reason code */
3151#define STAT_AUTH_FAIL 0x0300 /* low byte is 802.11 reason code */
3152#define STAT_ASSOC 0x0400 /* Associated */
3153#define STAT_REASSOC 0x0600 /* Reassociated? Only on firmware >= 5.30.17 */
3154
3155static void airo_print_status(const char *devname, u16 status)
3156{
3157 u8 reason = status & 0xFF;
3158
3159 switch (status) {
3160 case STAT_NOBEACON:
3161 airo_print_dbg(devname, "link lost (missed beacons)");
3162 break;
3163 case STAT_MAXRETRIES:
3164 case STAT_MAXARL:
3165 airo_print_dbg(devname, "link lost (max retries)");
3166 break;
3167 case STAT_FORCELOSS:
3168 airo_print_dbg(devname, "link lost (local choice)");
3169 break;
3170 case STAT_TSFSYNC:
3171 airo_print_dbg(devname, "link lost (TSF sync lost)");
3172 break;
3173 case STAT_DEAUTH:
3174 airo_print_dbg(devname, "deauthenticated (reason: %d)", reason);
3175 break;
3176 case STAT_DISASSOC:
3177 airo_print_dbg(devname, "disassociated (reason: %d)", reason);
3178 break;
3179 case STAT_ASSOC_FAIL:
3180 airo_print_dbg(devname, "association failed (reason: %d)",
3181 reason);
3182 break;
3183 case STAT_AUTH_FAIL:
3184 airo_print_dbg(devname, "authentication failed (reason: %d)",
3185 reason);
3186 break;
3187 default:
3188 break;
3189 }
3190}
3191
3192static void airo_handle_link(struct airo_info *ai)
3193{
3194 union iwreq_data wrqu;
3195 int scan_forceloss = 0;
3129 u16 status; 3196 u16 status;
3130 u16 fid;
3131 struct airo_info *apriv = dev->ml_priv;
3132 u16 savedInterrupts = 0;
3133 int handled = 0;
3134 3197
3135 if (!netif_device_present(dev)) 3198 /* Get new status and acknowledge the link change */
3136 return IRQ_NONE; 3199 status = le16_to_cpu(IN4500(ai, LINKSTAT));
3200 OUT4500(ai, EVACK, EV_LINK);
3137 3201
3138 for (;;) { 3202 if ((status == STAT_FORCELOSS) && (ai->scan_timeout > 0))
3139 status = IN4500( apriv, EVSTAT ); 3203 scan_forceloss = 1;
3140 if ( !(status & STATUS_INTS) || status == 0xffff ) break;
3141 3204
3142 handled = 1; 3205 airo_print_status(ai->dev->name, status);
3143 3206
3144 if ( status & EV_AWAKE ) { 3207 if ((status == STAT_ASSOC) || (status == STAT_REASSOC)) {
3145 OUT4500( apriv, EVACK, EV_AWAKE ); 3208 if (auto_wep)
3146 OUT4500( apriv, EVACK, EV_AWAKE ); 3209 ai->expires = 0;
3147 } 3210 if (ai->list_bss_task)
3211 wake_up_process(ai->list_bss_task);
3212 set_bit(FLAG_UPDATE_UNI, &ai->flags);
3213 set_bit(FLAG_UPDATE_MULTI, &ai->flags);
3148 3214
3149 if (!savedInterrupts) { 3215 if (down_trylock(&ai->sem) != 0) {
3150 savedInterrupts = IN4500( apriv, EVINTEN ); 3216 set_bit(JOB_EVENT, &ai->jobs);
3151 OUT4500( apriv, EVINTEN, 0 ); 3217 wake_up_interruptible(&ai->thr_wait);
3218 } else
3219 airo_send_event(ai->dev);
3220 } else if (!scan_forceloss) {
3221 if (auto_wep && !ai->expires) {
3222 ai->expires = RUN_AT(3*HZ);
3223 wake_up_interruptible(&ai->thr_wait);
3152 } 3224 }
3153 3225
3154 if ( status & EV_MIC ) { 3226 /* Send event to user space */
3155 OUT4500( apriv, EVACK, EV_MIC ); 3227 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
3156 if (test_bit(FLAG_MIC_CAPABLE, &apriv->flags)) { 3228 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3157 set_bit(JOB_MIC, &apriv->jobs); 3229 wireless_send_event(ai->dev, SIOCGIWAP, &wrqu, NULL);
3158 wake_up_interruptible(&apriv->thr_wait); 3230 }
3159 } 3231}
3160 }
3161 if ( status & EV_LINK ) {
3162 union iwreq_data wrqu;
3163 int scan_forceloss = 0;
3164 /* The link status has changed, if you want to put a
3165 monitor hook in, do it here. (Remember that
3166 interrupts are still disabled!)
3167 */
3168 u16 newStatus = IN4500(apriv, LINKSTAT);
3169 OUT4500( apriv, EVACK, EV_LINK);
3170 /* Here is what newStatus means: */
3171#define NOBEACON 0x8000 /* Loss of sync - missed beacons */
3172#define MAXRETRIES 0x8001 /* Loss of sync - max retries */
3173#define MAXARL 0x8002 /* Loss of sync - average retry level exceeded*/
3174#define FORCELOSS 0x8003 /* Loss of sync - host request */
3175#define TSFSYNC 0x8004 /* Loss of sync - TSF synchronization */
3176#define DEAUTH 0x8100 /* Deauthentication (low byte is reason code) */
3177#define DISASS 0x8200 /* Disassociation (low byte is reason code) */
3178#define ASSFAIL 0x8400 /* Association failure (low byte is reason
3179 code) */
3180#define AUTHFAIL 0x0300 /* Authentication failure (low byte is reason
3181 code) */
3182#define ASSOCIATED 0x0400 /* Associated */
3183#define REASSOCIATED 0x0600 /* Reassociated? Only on firmware >= 5.30.17 */
3184#define RC_RESERVED 0 /* Reserved return code */
3185#define RC_NOREASON 1 /* Unspecified reason */
3186#define RC_AUTHINV 2 /* Previous authentication invalid */
3187#define RC_DEAUTH 3 /* Deauthenticated because sending station is
3188 leaving */
3189#define RC_NOACT 4 /* Disassociated due to inactivity */
3190#define RC_MAXLOAD 5 /* Disassociated because AP is unable to handle
3191 all currently associated stations */
3192#define RC_BADCLASS2 6 /* Class 2 frame received from
3193 non-Authenticated station */
3194#define RC_BADCLASS3 7 /* Class 3 frame received from
3195 non-Associated station */
3196#define RC_STATLEAVE 8 /* Disassociated because sending station is
3197 leaving BSS */
3198#define RC_NOAUTH 9 /* Station requesting (Re)Association is not
3199 Authenticated with the responding station */
3200 if (newStatus == FORCELOSS && apriv->scan_timeout > 0)
3201 scan_forceloss = 1;
3202 if(newStatus == ASSOCIATED || newStatus == REASSOCIATED) {
3203 if (auto_wep)
3204 apriv->expires = 0;
3205 if (apriv->list_bss_task)
3206 wake_up_process(apriv->list_bss_task);
3207 set_bit(FLAG_UPDATE_UNI, &apriv->flags);
3208 set_bit(FLAG_UPDATE_MULTI, &apriv->flags);
3209
3210 if (down_trylock(&apriv->sem) != 0) {
3211 set_bit(JOB_EVENT, &apriv->jobs);
3212 wake_up_interruptible(&apriv->thr_wait);
3213 } else
3214 airo_send_event(dev);
3215 } else if (!scan_forceloss) {
3216 if (auto_wep && !apriv->expires) {
3217 apriv->expires = RUN_AT(3*HZ);
3218 wake_up_interruptible(&apriv->thr_wait);
3219 }
3220 3232
3221 /* Send event to user space */ 3233static void airo_handle_rx(struct airo_info *ai)
3222 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN); 3234{
3223 wrqu.ap_addr.sa_family = ARPHRD_ETHER; 3235 struct sk_buff *skb = NULL;
3224 wireless_send_event(dev, SIOCGIWAP, &wrqu,NULL); 3236 __le16 fc, v, *buffer, tmpbuf[4];
3225 } 3237 u16 len, hdrlen = 0, gap, fid;
3226 } 3238 struct rx_hdr hdr;
3239 int success = 0;
3227 3240
3228 /* Check to see if there is something to receive */ 3241 if (test_bit(FLAG_MPI, &ai->flags)) {
3229 if ( status & EV_RX ) { 3242 if (test_bit(FLAG_802_11, &ai->flags))
3230 struct sk_buff *skb = NULL; 3243 mpi_receive_802_11(ai);
3231 __le16 fc, v; 3244 else
3232 u16 len, hdrlen = 0; 3245 mpi_receive_802_3(ai);
3233#pragma pack(1) 3246 OUT4500(ai, EVACK, EV_RX);
3234 struct { 3247 return;
3235 __le16 status, len; 3248 }
3236 u8 rssi[2];
3237 u8 rate;
3238 u8 freq;
3239 __le16 tmp[4];
3240 } hdr;
3241#pragma pack()
3242 u16 gap;
3243 __le16 tmpbuf[4];
3244 __le16 *buffer;
3245
3246 if (test_bit(FLAG_MPI,&apriv->flags)) {
3247 if (test_bit(FLAG_802_11, &apriv->flags))
3248 mpi_receive_802_11(apriv);
3249 else
3250 mpi_receive_802_3(apriv);
3251 OUT4500(apriv, EVACK, EV_RX);
3252 goto exitrx;
3253 }
3254 3249
3255 fid = IN4500( apriv, RXFID ); 3250 fid = IN4500(ai, RXFID);
3256
3257 /* Get the packet length */
3258 if (test_bit(FLAG_802_11, &apriv->flags)) {
3259 bap_setup (apriv, fid, 4, BAP0);
3260 bap_read (apriv, (__le16*)&hdr, sizeof(hdr), BAP0);
3261 /* Bad CRC. Ignore packet */
3262 if (le16_to_cpu(hdr.status) & 2)
3263 hdr.len = 0;
3264 if (apriv->wifidev == NULL)
3265 hdr.len = 0;
3266 } else {
3267 bap_setup (apriv, fid, 0x36, BAP0);
3268 bap_read (apriv, &hdr.len, 2, BAP0);
3269 }
3270 len = le16_to_cpu(hdr.len);
3271 3251
3272 if (len > AIRO_DEF_MTU) { 3252 /* Get the packet length */
3273 airo_print_err(apriv->dev->name, "Bad size %d", len); 3253 if (test_bit(FLAG_802_11, &ai->flags)) {
3274 goto badrx; 3254 bap_setup (ai, fid, 4, BAP0);
3275 } 3255 bap_read (ai, (__le16*)&hdr, sizeof(hdr), BAP0);
3276 if (len == 0) 3256 /* Bad CRC. Ignore packet */
3277 goto badrx; 3257 if (le16_to_cpu(hdr.status) & 2)
3258 hdr.len = 0;
3259 if (ai->wifidev == NULL)
3260 hdr.len = 0;
3261 } else {
3262 bap_setup(ai, fid, 0x36, BAP0);
3263 bap_read(ai, &hdr.len, 2, BAP0);
3264 }
3265 len = le16_to_cpu(hdr.len);
3278 3266
3279 if (test_bit(FLAG_802_11, &apriv->flags)) { 3267 if (len > AIRO_DEF_MTU) {
3280 bap_read (apriv, &fc, sizeof(fc), BAP0); 3268 airo_print_err(ai->dev->name, "Bad size %d", len);
3281 hdrlen = header_len(fc); 3269 goto done;
3282 } else 3270 }
3283 hdrlen = ETH_ALEN * 2; 3271 if (len == 0)
3272 goto done;
3284 3273
3285 skb = dev_alloc_skb( len + hdrlen + 2 + 2 ); 3274 if (test_bit(FLAG_802_11, &ai->flags)) {
3286 if ( !skb ) { 3275 bap_read(ai, &fc, sizeof (fc), BAP0);
3287 dev->stats.rx_dropped++; 3276 hdrlen = header_len(fc);
3288 goto badrx; 3277 } else
3289 } 3278 hdrlen = ETH_ALEN * 2;
3290 skb_reserve(skb, 2); /* This way the IP header is aligned */ 3279
3291 buffer = (__le16*)skb_put (skb, len + hdrlen); 3280 skb = dev_alloc_skb(len + hdrlen + 2 + 2);
3292 if (test_bit(FLAG_802_11, &apriv->flags)) { 3281 if (!skb) {
3293 buffer[0] = fc; 3282 ai->dev->stats.rx_dropped++;
3294 bap_read (apriv, buffer + 1, hdrlen - 2, BAP0); 3283 goto done;
3295 if (hdrlen == 24) 3284 }
3296 bap_read (apriv, tmpbuf, 6, BAP0); 3285
3297 3286 skb_reserve(skb, 2); /* This way the IP header is aligned */
3298 bap_read (apriv, &v, sizeof(v), BAP0); 3287 buffer = (__le16 *) skb_put(skb, len + hdrlen);
3299 gap = le16_to_cpu(v); 3288 if (test_bit(FLAG_802_11, &ai->flags)) {
3300 if (gap) { 3289 buffer[0] = fc;
3301 if (gap <= 8) { 3290 bap_read(ai, buffer + 1, hdrlen - 2, BAP0);
3302 bap_read (apriv, tmpbuf, gap, BAP0); 3291 if (hdrlen == 24)
3303 } else { 3292 bap_read(ai, tmpbuf, 6, BAP0);
3304 airo_print_err(apriv->dev->name, "gaplen too " 3293
3305 "big. Problems will follow..."); 3294 bap_read(ai, &v, sizeof(v), BAP0);
3306 } 3295 gap = le16_to_cpu(v);
3307 } 3296 if (gap) {
3308 bap_read (apriv, buffer + hdrlen/2, len, BAP0); 3297 if (gap <= 8) {
3298 bap_read(ai, tmpbuf, gap, BAP0);
3309 } else { 3299 } else {
3310 MICBuffer micbuf; 3300 airo_print_err(ai->dev->name, "gaplen too "
3311 bap_read (apriv, buffer, ETH_ALEN*2, BAP0); 3301 "big. Problems will follow...");
3312 if (apriv->micstats.enabled) { 3302 }
3313 bap_read (apriv,(__le16*)&micbuf,sizeof(micbuf),BAP0); 3303 }
3314 if (ntohs(micbuf.typelen) > 0x05DC) 3304 bap_read(ai, buffer + hdrlen/2, len, BAP0);
3315 bap_setup (apriv, fid, 0x44, BAP0); 3305 } else {
3316 else { 3306 MICBuffer micbuf;
3317 if (len <= sizeof(micbuf)) 3307
3318 goto badmic; 3308 bap_read(ai, buffer, ETH_ALEN * 2, BAP0);
3319 3309 if (ai->micstats.enabled) {
3320 len -= sizeof(micbuf); 3310 bap_read(ai, (__le16 *) &micbuf, sizeof (micbuf), BAP0);
3321 skb_trim (skb, len + hdrlen); 3311 if (ntohs(micbuf.typelen) > 0x05DC)
3322 } 3312 bap_setup(ai, fid, 0x44, BAP0);
3323 } 3313 else {
3324 bap_read(apriv,buffer+ETH_ALEN,len,BAP0); 3314 if (len <= sizeof (micbuf)) {
3325 if (decapsulate(apriv,&micbuf,(etherHead*)buffer,len)) { 3315 dev_kfree_skb_irq(skb);
3326badmic: 3316 goto done;
3327 dev_kfree_skb_irq (skb);
3328badrx:
3329 OUT4500( apriv, EVACK, EV_RX);
3330 goto exitrx;
3331 } 3317 }
3318
3319 len -= sizeof(micbuf);
3320 skb_trim(skb, len + hdrlen);
3332 } 3321 }
3322 }
3323
3324 bap_read(ai, buffer + ETH_ALEN, len, BAP0);
3325 if (decapsulate(ai, &micbuf, (etherHead*) buffer, len))
3326 dev_kfree_skb_irq (skb);
3327 else
3328 success = 1;
3329 }
3330
3333#ifdef WIRELESS_SPY 3331#ifdef WIRELESS_SPY
3334 if (apriv->spy_data.spy_number > 0) { 3332 if (success && (ai->spy_data.spy_number > 0)) {
3335 char *sa; 3333 char *sa;
3336 struct iw_quality wstats; 3334 struct iw_quality wstats;
3337 /* Prepare spy data : addr + qual */ 3335
3338 if (!test_bit(FLAG_802_11, &apriv->flags)) { 3336 /* Prepare spy data : addr + qual */
3339 sa = (char*)buffer + 6; 3337 if (!test_bit(FLAG_802_11, &ai->flags)) {
3340 bap_setup (apriv, fid, 8, BAP0); 3338 sa = (char *) buffer + 6;
3341 bap_read (apriv, (__le16*)hdr.rssi, 2, BAP0); 3339 bap_setup(ai, fid, 8, BAP0);
3342 } else 3340 bap_read(ai, (__le16 *) hdr.rssi, 2, BAP0);
3343 sa = (char*)buffer + 10; 3341 } else
3344 wstats.qual = hdr.rssi[0]; 3342 sa = (char *) buffer + 10;
3345 if (apriv->rssi) 3343 wstats.qual = hdr.rssi[0];
3346 wstats.level = 0x100 - apriv->rssi[hdr.rssi[1]].rssidBm; 3344 if (ai->rssi)
3347 else 3345 wstats.level = 0x100 - ai->rssi[hdr.rssi[1]].rssidBm;
3348 wstats.level = (hdr.rssi[1] + 321) / 2; 3346 else
3349 wstats.noise = apriv->wstats.qual.noise; 3347 wstats.level = (hdr.rssi[1] + 321) / 2;
3350 wstats.updated = IW_QUAL_LEVEL_UPDATED 3348 wstats.noise = ai->wstats.qual.noise;
3351 | IW_QUAL_QUAL_UPDATED 3349 wstats.updated = IW_QUAL_LEVEL_UPDATED
3352 | IW_QUAL_DBM; 3350 | IW_QUAL_QUAL_UPDATED
3353 /* Update spy records */ 3351 | IW_QUAL_DBM;
3354 wireless_spy_update(dev, sa, &wstats); 3352 /* Update spy records */
3355 } 3353 wireless_spy_update(ai->dev, sa, &wstats);
3354 }
3356#endif /* WIRELESS_SPY */ 3355#endif /* WIRELESS_SPY */
3357 OUT4500( apriv, EVACK, EV_RX);
3358 3356
3359 if (test_bit(FLAG_802_11, &apriv->flags)) { 3357done:
3360 skb_reset_mac_header(skb); 3358 OUT4500(ai, EVACK, EV_RX);
3361 skb->pkt_type = PACKET_OTHERHOST; 3359
3362 skb->dev = apriv->wifidev; 3360 if (success) {
3363 skb->protocol = htons(ETH_P_802_2); 3361 if (test_bit(FLAG_802_11, &ai->flags)) {
3364 } else 3362 skb_reset_mac_header(skb);
3365 skb->protocol = eth_type_trans(skb,dev); 3363 skb->pkt_type = PACKET_OTHERHOST;
3366 skb->ip_summed = CHECKSUM_NONE; 3364 skb->dev = ai->wifidev;
3365 skb->protocol = htons(ETH_P_802_2);
3366 } else
3367 skb->protocol = eth_type_trans(skb, ai->dev);
3368 skb->ip_summed = CHECKSUM_NONE;
3369
3370 netif_rx(skb);
3371 }
3372}
3373
3374static void airo_handle_tx(struct airo_info *ai, u16 status)
3375{
3376 int i, len = 0, index = -1;
3377 u16 fid;
3367 3378
3368 netif_rx( skb ); 3379 if (test_bit(FLAG_MPI, &ai->flags)) {
3380 unsigned long flags;
3381
3382 if (status & EV_TXEXC)
3383 get_tx_error(ai, -1);
3384
3385 spin_lock_irqsave(&ai->aux_lock, flags);
3386 if (!skb_queue_empty(&ai->txq)) {
3387 spin_unlock_irqrestore(&ai->aux_lock,flags);
3388 mpi_send_packet(ai->dev);
3389 } else {
3390 clear_bit(FLAG_PENDING_XMIT, &ai->flags);
3391 spin_unlock_irqrestore(&ai->aux_lock,flags);
3392 netif_wake_queue(ai->dev);
3369 } 3393 }
3370exitrx: 3394 OUT4500(ai, EVACK, status & (EV_TX | EV_TXCPY | EV_TXEXC));
3395 return;
3396 }
3371 3397
3372 /* Check to see if a packet has been transmitted */ 3398 fid = IN4500(ai, TXCOMPLFID);
3373 if ( status & ( EV_TX|EV_TXCPY|EV_TXEXC ) ) { 3399
3374 int i; 3400 for(i = 0; i < MAX_FIDS; i++) {
3375 int len = 0; 3401 if ((ai->fids[i] & 0xffff) == fid) {
3376 int index = -1; 3402 len = ai->fids[i] >> 16;
3377 3403 index = i;
3378 if (test_bit(FLAG_MPI,&apriv->flags)) { 3404 }
3379 unsigned long flags; 3405 }
3380
3381 if (status & EV_TXEXC)
3382 get_tx_error(apriv, -1);
3383 spin_lock_irqsave(&apriv->aux_lock, flags);
3384 if (!skb_queue_empty(&apriv->txq)) {
3385 spin_unlock_irqrestore(&apriv->aux_lock,flags);
3386 mpi_send_packet (dev);
3387 } else {
3388 clear_bit(FLAG_PENDING_XMIT, &apriv->flags);
3389 spin_unlock_irqrestore(&apriv->aux_lock,flags);
3390 netif_wake_queue (dev);
3391 }
3392 OUT4500( apriv, EVACK,
3393 status & (EV_TX|EV_TXCPY|EV_TXEXC));
3394 goto exittx;
3395 }
3396 3406
3397 fid = IN4500(apriv, TXCOMPLFID); 3407 if (index != -1) {
3408 if (status & EV_TXEXC)
3409 get_tx_error(ai, index);
3398 3410
3399 for( i = 0; i < MAX_FIDS; i++ ) { 3411 OUT4500(ai, EVACK, status & (EV_TX | EV_TXEXC));
3400 if ( ( apriv->fids[i] & 0xffff ) == fid ) { 3412
3401 len = apriv->fids[i] >> 16; 3413 /* Set up to be used again */
3402 index = i; 3414 ai->fids[index] &= 0xffff;
3403 } 3415 if (index < MAX_FIDS / 2) {
3404 } 3416 if (!test_bit(FLAG_PENDING_XMIT, &ai->flags))
3405 if (index != -1) { 3417 netif_wake_queue(ai->dev);
3406 if (status & EV_TXEXC) 3418 } else {
3407 get_tx_error(apriv, index); 3419 if (!test_bit(FLAG_PENDING_XMIT11, &ai->flags))
3408 OUT4500( apriv, EVACK, status & (EV_TX | EV_TXEXC)); 3420 netif_wake_queue(ai->wifidev);
3409 /* Set up to be used again */
3410 apriv->fids[index] &= 0xffff;
3411 if (index < MAX_FIDS / 2) {
3412 if (!test_bit(FLAG_PENDING_XMIT, &apriv->flags))
3413 netif_wake_queue(dev);
3414 } else {
3415 if (!test_bit(FLAG_PENDING_XMIT11, &apriv->flags))
3416 netif_wake_queue(apriv->wifidev);
3417 }
3418 } else {
3419 OUT4500( apriv, EVACK, status & (EV_TX | EV_TXCPY | EV_TXEXC));
3420 airo_print_err(apriv->dev->name, "Unallocated FID was "
3421 "used to xmit" );
3422 }
3423 } 3421 }
3424exittx: 3422 } else {
3425 if ( status & ~STATUS_INTS & ~IGNORE_INTS ) 3423 OUT4500(ai, EVACK, status & (EV_TX | EV_TXCPY | EV_TXEXC));
3426 airo_print_warn(apriv->dev->name, "Got weird status %x", 3424 airo_print_err(ai->dev->name, "Unallocated FID was used to xmit");
3425 }
3426}
3427
3428static irqreturn_t airo_interrupt(int irq, void *dev_id)
3429{
3430 struct net_device *dev = dev_id;
3431 u16 status, savedInterrupts = 0;
3432 struct airo_info *ai = dev->ml_priv;
3433 int handled = 0;
3434
3435 if (!netif_device_present(dev))
3436 return IRQ_NONE;
3437
3438 for (;;) {
3439 status = IN4500(ai, EVSTAT);
3440 if (!(status & STATUS_INTS) || (status == 0xffff))
3441 break;
3442
3443 handled = 1;
3444
3445 if (status & EV_AWAKE) {
3446 OUT4500(ai, EVACK, EV_AWAKE);
3447 OUT4500(ai, EVACK, EV_AWAKE);
3448 }
3449
3450 if (!savedInterrupts) {
3451 savedInterrupts = IN4500(ai, EVINTEN);
3452 OUT4500(ai, EVINTEN, 0);
3453 }
3454
3455 if (status & EV_MIC) {
3456 OUT4500(ai, EVACK, EV_MIC);
3457 airo_handle_cisco_mic(ai);
3458 }
3459
3460 if (status & EV_LINK) {
3461 /* Link status changed */
3462 airo_handle_link(ai);
3463 }
3464
3465 /* Check to see if there is something to receive */
3466 if (status & EV_RX)
3467 airo_handle_rx(ai);
3468
3469 /* Check to see if a packet has been transmitted */
3470 if (status & (EV_TX | EV_TXCPY | EV_TXEXC))
3471 airo_handle_tx(ai, status);
3472
3473 if ( status & ~STATUS_INTS & ~IGNORE_INTS ) {
3474 airo_print_warn(ai->dev->name, "Got weird status %x",
3427 status & ~STATUS_INTS & ~IGNORE_INTS ); 3475 status & ~STATUS_INTS & ~IGNORE_INTS );
3476 }
3428 } 3477 }
3429 3478
3430 if (savedInterrupts) 3479 if (savedInterrupts)
3431 OUT4500( apriv, EVINTEN, savedInterrupts ); 3480 OUT4500(ai, EVINTEN, savedInterrupts);
3432 3481
3433 /* done.. */
3434 return IRQ_RETVAL(handled); 3482 return IRQ_RETVAL(handled);
3435} 3483}
3436 3484
@@ -3609,18 +3657,10 @@ static void mpi_receive_802_11(struct airo_info *ai)
3609 struct sk_buff *skb = NULL; 3657 struct sk_buff *skb = NULL;
3610 u16 len, hdrlen = 0; 3658 u16 len, hdrlen = 0;
3611 __le16 fc; 3659 __le16 fc;
3612#pragma pack(1) 3660 struct rx_hdr hdr;
3613 struct {
3614 __le16 status, len;
3615 u8 rssi[2];
3616 u8 rate;
3617 u8 freq;
3618 __le16 tmp[4];
3619 } hdr;
3620#pragma pack()
3621 u16 gap; 3661 u16 gap;
3622 u16 *buffer; 3662 u16 *buffer;
3623 char *ptr = ai->rxfids[0].virtual_host_addr+4; 3663 char *ptr = ai->rxfids[0].virtual_host_addr + 4;
3624 3664
3625 memcpy_fromio(&rxd, ai->rxfids[0].card_ram_off, sizeof(rxd)); 3665 memcpy_fromio(&rxd, ai->rxfids[0].card_ram_off, sizeof(rxd));
3626 memcpy ((char *)&hdr, ptr, sizeof(hdr)); 3666 memcpy ((char *)&hdr, ptr, sizeof(hdr));
@@ -3687,6 +3727,7 @@ static void mpi_receive_802_11(struct airo_info *ai)
3687 skb->protocol = htons(ETH_P_802_2); 3727 skb->protocol = htons(ETH_P_802_2);
3688 skb->ip_summed = CHECKSUM_NONE; 3728 skb->ip_summed = CHECKSUM_NONE;
3689 netif_rx( skb ); 3729 netif_rx( skb );
3730
3690badrx: 3731badrx:
3691 if (rxd.valid == 0) { 3732 if (rxd.valid == 0) {
3692 rxd.valid = 1; 3733 rxd.valid = 1;