diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index fa7eb39dbf3c..a769c89a3690 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -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 {
 
@@ -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;
@@ -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)
@@ -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;
@@ -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,
@@ -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
@@ -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);
 }
 
 /*
@@ -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 */
@@ -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;
 }
 
@@ -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 */
@@ -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 */
 
@@ -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