Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 85605
b: refs/heads/master
c: 9a2f037
h: refs/heads/master
i:
  85603: 7ea4323
v: v3
  • Loading branch information
Ben Dooks authored and Jeff Garzik committed Feb 11, 2008
1 parent 6911628 commit 6081983
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 15 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 86c62fab5aafe33d033d2f616ba8be0527e1c286
refs/heads/master: 9a2f037cdbe8409c5ff92e8dce5fcdfe2ebb2084
53 changes: 39 additions & 14 deletions trunk/drivers/net/dm9000.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,24 @@ static int watchdog = 5000;
module_param(watchdog, int, 0400);
MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");

/* DM9000 register address locking.
*
* The DM9000 uses an address register to control where data written
* to the data register goes. This means that the address register
* must be preserved over interrupts or similar calls.
*
* During interrupt and other critical calls, a spinlock is used to
* protect the system, but the calls themselves save the address
* in the address register in case they are interrupting another
* access to the device.
*
* For general accesses a lock is provided so that calls which are
* allowed to sleep are serialised so that the address register does
* not need to be saved. This lock also serves to serialise access
* to the EEPROM and PHY access registers which are shared between
* these two devices.
*/

/* Structure/enum declaration ------------------------------- */
typedef struct board_info {

Expand Down Expand Up @@ -132,6 +150,8 @@ typedef struct board_info {
struct resource *data_req;
struct resource *irq_res;

struct mutex addr_lock; /* phy and eeprom access lock */

spinlock_t lock;

struct mii_if_info mii;
Expand Down Expand Up @@ -365,26 +385,16 @@ static void dm9000_get_drvinfo(struct net_device *dev,
static int dm9000_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
board_info_t *dm = to_dm9000_board(dev);
unsigned long flags;

spin_lock_irqsave(&dm->lock, flags);
mii_ethtool_gset(&dm->mii, cmd);
spin_lock_irqsave(&dm->lock, flags);

return 0;
}

static int dm9000_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
board_info_t *dm = to_dm9000_board(dev);
unsigned long flags;
int rc;

spin_lock_irqsave(&dm->lock, flags);
rc = mii_ethtool_sset(&dm->mii, cmd);
spin_lock_irqsave(&dm->lock, flags);

return rc;
return mii_ethtool_sset(&dm->mii, cmd);
}

static int dm9000_nway_reset(struct net_device *dev)
Expand Down Expand Up @@ -475,6 +485,7 @@ dm9000_probe(struct platform_device *pdev)
db->dev = &pdev->dev;

spin_lock_init(&db->lock);
mutex_init(&db->addr_lock);

if (pdev->num_resources < 2) {
ret = -ENODEV;
Expand Down Expand Up @@ -997,8 +1008,10 @@ dm9000_rx(struct net_device *dev)
* Read a word data from EEPROM
*/
static void
dm9000_read_eeprom(board_info_t * db, int offset, unsigned char *to)
dm9000_read_eeprom(board_info_t *db, int offset, unsigned char *to)
{
mutex_lock(&db->addr_lock);

iow(db, DM9000_EPAR, offset);
iow(db, DM9000_EPCR, EPCR_ERPRR);
mdelay(8); /* according to the datasheet 200us should be enough,
Expand All @@ -1007,6 +1020,8 @@ dm9000_read_eeprom(board_info_t * db, int offset, unsigned char *to)

to[0] = ior(db, DM9000_EPDRL);
to[1] = ior(db, DM9000_EPDRH);

mutex_unlock(&db->addr_lock);
}

#ifdef DM9000_PROGRAM_EEPROM
Expand All @@ -1016,12 +1031,16 @@ dm9000_read_eeprom(board_info_t * db, int offset, unsigned char *to)
static void
write_srom_word(board_info_t * db, int offset, u16 val)
{
mutex_lock(&db->addr_lock);

iow(db, DM9000_EPAR, offset);
iow(db, DM9000_EPDRH, ((val >> 8) & 0xff));
iow(db, DM9000_EPDRL, (val & 0xff));
iow(db, DM9000_EPCR, EPCR_WEP | EPCR_ERPRW);
mdelay(8); /* same shit */
iow(db, DM9000_EPCR, 0);

mutex_unlock(&db->addr_lock);
}

/*
Expand Down Expand Up @@ -1129,6 +1148,8 @@ dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
unsigned int reg_save;
int ret;

mutex_lock(&db->addr_lock);

spin_lock_irqsave(&db->lock,flags);

/* Save previous register address */
Expand Down Expand Up @@ -1156,6 +1177,7 @@ dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
writeb(reg_save, db->io_addr);
spin_unlock_irqrestore(&db->lock,flags);

mutex_unlock(&db->addr_lock);
return ret;
}

Expand All @@ -1169,6 +1191,8 @@ dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg, int value)
unsigned long flags;
unsigned long reg_save;

mutex_lock(&db->addr_lock);

spin_lock_irqsave(&db->lock,flags);

/* Save previous register address */
Expand All @@ -1184,7 +1208,7 @@ dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg, int value)
iow(db, DM9000_EPCR, 0xa); /* Issue phyxcer write command */

writeb(reg_save, db->io_addr);
spin_unlock_irqrestore(&db->lock,flags);
spin_unlock_irqrestore(&db->lock, flags);

dm9000_msleep(db, 1); /* Wait write complete */

Expand All @@ -1196,7 +1220,8 @@ dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg, int value)
/* restore the previous address */
writeb(reg_save, db->io_addr);

spin_unlock_irqrestore(&db->lock,flags);
spin_unlock_irqrestore(&db->lock, flags);
mutex_unlock(&db->addr_lock);
}

static int
Expand Down

0 comments on commit 6081983

Please sign in to comment.