diff options
author | Stephen Hemminger <shemminger@vyatta.com> | 2008-05-30 12:49:57 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2008-05-30 22:18:00 -0400 |
commit | a3ccc78968f00b6589653c1cccadb7940594935a (patch) | |
tree | a17ea50db7a99003eba6ccc3947ed691a897c9d4 /drivers | |
parent | 9ded65a1d79a2ca9aa44ee0989fd7924304c31cc (diff) |
tlan: proper shared IRQ support
Handle shared IRQ correctly. If IRQ is shared, it typically will show up
as an IRQ with an empty status field. So check in driver and handle it
without crapping out with invalid interrupt message.
Compile tested only.
Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/tlan.c | 61 |
1 files changed, 17 insertions, 44 deletions
diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c index afc831002db2..01aa331e1838 100644 --- a/drivers/net/tlan.c +++ b/drivers/net/tlan.c | |||
@@ -218,7 +218,7 @@ static int bbuf; | |||
218 | module_param(bbuf, int, 0); | 218 | module_param(bbuf, int, 0); |
219 | MODULE_PARM_DESC(bbuf, "ThunderLAN use big buffer (0-1)"); | 219 | MODULE_PARM_DESC(bbuf, "ThunderLAN use big buffer (0-1)"); |
220 | 220 | ||
221 | static char TLanSignature[] = "TLAN"; | 221 | static const char TLanSignature[] = "TLAN"; |
222 | static const char tlan_banner[] = "ThunderLAN driver v1.15\n"; | 222 | static const char tlan_banner[] = "ThunderLAN driver v1.15\n"; |
223 | static int tlan_have_pci; | 223 | static int tlan_have_pci; |
224 | static int tlan_have_eisa; | 224 | static int tlan_have_eisa; |
@@ -297,7 +297,6 @@ static void TLan_tx_timeout( struct net_device *dev); | |||
297 | static void TLan_tx_timeout_work(struct work_struct *work); | 297 | static void TLan_tx_timeout_work(struct work_struct *work); |
298 | static int tlan_init_one( struct pci_dev *pdev, const struct pci_device_id *ent); | 298 | static int tlan_init_one( struct pci_dev *pdev, const struct pci_device_id *ent); |
299 | 299 | ||
300 | static u32 TLan_HandleInvalid( struct net_device *, u16 ); | ||
301 | static u32 TLan_HandleTxEOF( struct net_device *, u16 ); | 300 | static u32 TLan_HandleTxEOF( struct net_device *, u16 ); |
302 | static u32 TLan_HandleStatOverflow( struct net_device *, u16 ); | 301 | static u32 TLan_HandleStatOverflow( struct net_device *, u16 ); |
303 | static u32 TLan_HandleRxEOF( struct net_device *, u16 ); | 302 | static u32 TLan_HandleRxEOF( struct net_device *, u16 ); |
@@ -366,7 +365,7 @@ TLan_GetSKB( const struct tlan_list_tag *tag) | |||
366 | 365 | ||
367 | 366 | ||
368 | static TLanIntVectorFunc *TLanIntVector[TLAN_INT_NUMBER_OF_INTS] = { | 367 | static TLanIntVectorFunc *TLanIntVector[TLAN_INT_NUMBER_OF_INTS] = { |
369 | TLan_HandleInvalid, | 368 | NULL, |
370 | TLan_HandleTxEOF, | 369 | TLan_HandleTxEOF, |
371 | TLan_HandleStatOverflow, | 370 | TLan_HandleStatOverflow, |
372 | TLan_HandleRxEOF, | 371 | TLan_HandleRxEOF, |
@@ -935,7 +934,8 @@ static int TLan_Open( struct net_device *dev ) | |||
935 | int err; | 934 | int err; |
936 | 935 | ||
937 | priv->tlanRev = TLan_DioRead8( dev->base_addr, TLAN_DEF_REVISION ); | 936 | priv->tlanRev = TLan_DioRead8( dev->base_addr, TLAN_DEF_REVISION ); |
938 | err = request_irq( dev->irq, TLan_HandleInterrupt, IRQF_SHARED, TLanSignature, dev ); | 937 | err = request_irq( dev->irq, TLan_HandleInterrupt, IRQF_SHARED, |
938 | dev->name, dev ); | ||
939 | 939 | ||
940 | if ( err ) { | 940 | if ( err ) { |
941 | printk(KERN_ERR "TLAN: Cannot open %s because IRQ %d is already in use.\n", dev->name, dev->irq ); | 941 | printk(KERN_ERR "TLAN: Cannot open %s because IRQ %d is already in use.\n", dev->name, dev->irq ); |
@@ -1167,33 +1167,31 @@ static int TLan_StartTx( struct sk_buff *skb, struct net_device *dev ) | |||
1167 | 1167 | ||
1168 | static irqreturn_t TLan_HandleInterrupt(int irq, void *dev_id) | 1168 | static irqreturn_t TLan_HandleInterrupt(int irq, void *dev_id) |
1169 | { | 1169 | { |
1170 | u32 ack; | 1170 | struct net_device *dev = dev_id; |
1171 | struct net_device *dev; | 1171 | TLanPrivateInfo *priv = netdev_priv(dev); |
1172 | u32 host_cmd; | ||
1173 | u16 host_int; | 1172 | u16 host_int; |
1174 | int type; | 1173 | u16 type; |
1175 | TLanPrivateInfo *priv; | ||
1176 | |||
1177 | dev = dev_id; | ||
1178 | priv = netdev_priv(dev); | ||
1179 | 1174 | ||
1180 | spin_lock(&priv->lock); | 1175 | spin_lock(&priv->lock); |
1181 | 1176 | ||
1182 | host_int = inw( dev->base_addr + TLAN_HOST_INT ); | 1177 | host_int = inw( dev->base_addr + TLAN_HOST_INT ); |
1183 | outw( host_int, dev->base_addr + TLAN_HOST_INT ); | ||
1184 | |||
1185 | type = ( host_int & TLAN_HI_IT_MASK ) >> 2; | 1178 | type = ( host_int & TLAN_HI_IT_MASK ) >> 2; |
1179 | if ( type ) { | ||
1180 | u32 ack; | ||
1181 | u32 host_cmd; | ||
1186 | 1182 | ||
1187 | ack = TLanIntVector[type]( dev, host_int ); | 1183 | outw( host_int, dev->base_addr + TLAN_HOST_INT ); |
1184 | ack = TLanIntVector[type]( dev, host_int ); | ||
1188 | 1185 | ||
1189 | if ( ack ) { | 1186 | if ( ack ) { |
1190 | host_cmd = TLAN_HC_ACK | ack | ( type << 18 ); | 1187 | host_cmd = TLAN_HC_ACK | ack | ( type << 18 ); |
1191 | outl( host_cmd, dev->base_addr + TLAN_HOST_CMD ); | 1188 | outl( host_cmd, dev->base_addr + TLAN_HOST_CMD ); |
1189 | } | ||
1192 | } | 1190 | } |
1193 | 1191 | ||
1194 | spin_unlock(&priv->lock); | 1192 | spin_unlock(&priv->lock); |
1195 | 1193 | ||
1196 | return IRQ_HANDLED; | 1194 | return IRQ_RETVAL(type); |
1197 | } /* TLan_HandleInterrupts */ | 1195 | } /* TLan_HandleInterrupts */ |
1198 | 1196 | ||
1199 | 1197 | ||
@@ -1359,31 +1357,6 @@ static void TLan_SetMulticastList( struct net_device *dev ) | |||
1359 | *****************************************************************************/ | 1357 | *****************************************************************************/ |
1360 | 1358 | ||
1361 | 1359 | ||
1362 | /*************************************************************** | ||
1363 | * TLan_HandleInvalid | ||
1364 | * | ||
1365 | * Returns: | ||
1366 | * 0 | ||
1367 | * Parms: | ||
1368 | * dev Device assigned the IRQ that was | ||
1369 | * raised. | ||
1370 | * host_int The contents of the HOST_INT | ||
1371 | * port. | ||
1372 | * | ||
1373 | * This function handles invalid interrupts. This should | ||
1374 | * never happen unless some other adapter is trying to use | ||
1375 | * the IRQ line assigned to the device. | ||
1376 | * | ||
1377 | **************************************************************/ | ||
1378 | |||
1379 | static u32 TLan_HandleInvalid( struct net_device *dev, u16 host_int ) | ||
1380 | { | ||
1381 | /* printk( "TLAN: Invalid interrupt on %s.\n", dev->name ); */ | ||
1382 | return 0; | ||
1383 | |||
1384 | } /* TLan_HandleInvalid */ | ||
1385 | |||
1386 | |||
1387 | 1360 | ||
1388 | 1361 | ||
1389 | /*************************************************************** | 1362 | /*************************************************************** |