aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@vyatta.com>2008-05-30 12:49:57 -0400
committerJeff Garzik <jgarzik@redhat.com>2008-05-30 22:18:00 -0400
commita3ccc78968f00b6589653c1cccadb7940594935a (patch)
treea17ea50db7a99003eba6ccc3947ed691a897c9d4
parent9ded65a1d79a2ca9aa44ee0989fd7924304c31cc (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>
-rw-r--r--drivers/net/tlan.c61
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;
218module_param(bbuf, int, 0); 218module_param(bbuf, int, 0);
219MODULE_PARM_DESC(bbuf, "ThunderLAN use big buffer (0-1)"); 219MODULE_PARM_DESC(bbuf, "ThunderLAN use big buffer (0-1)");
220 220
221static char TLanSignature[] = "TLAN"; 221static const char TLanSignature[] = "TLAN";
222static const char tlan_banner[] = "ThunderLAN driver v1.15\n"; 222static const char tlan_banner[] = "ThunderLAN driver v1.15\n";
223static int tlan_have_pci; 223static int tlan_have_pci;
224static int tlan_have_eisa; 224static int tlan_have_eisa;
@@ -297,7 +297,6 @@ static void TLan_tx_timeout( struct net_device *dev);
297static void TLan_tx_timeout_work(struct work_struct *work); 297static void TLan_tx_timeout_work(struct work_struct *work);
298static int tlan_init_one( struct pci_dev *pdev, const struct pci_device_id *ent); 298static int tlan_init_one( struct pci_dev *pdev, const struct pci_device_id *ent);
299 299
300static u32 TLan_HandleInvalid( struct net_device *, u16 );
301static u32 TLan_HandleTxEOF( struct net_device *, u16 ); 300static u32 TLan_HandleTxEOF( struct net_device *, u16 );
302static u32 TLan_HandleStatOverflow( struct net_device *, u16 ); 301static u32 TLan_HandleStatOverflow( struct net_device *, u16 );
303static u32 TLan_HandleRxEOF( struct net_device *, u16 ); 302static u32 TLan_HandleRxEOF( struct net_device *, u16 );
@@ -366,7 +365,7 @@ TLan_GetSKB( const struct tlan_list_tag *tag)
366 365
367 366
368static TLanIntVectorFunc *TLanIntVector[TLAN_INT_NUMBER_OF_INTS] = { 367static 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
1168static irqreturn_t TLan_HandleInterrupt(int irq, void *dev_id) 1168static 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
1379static 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 /***************************************************************