From: David Woodhouse <dwmw2@infradead.org>
To: davem@davemloft.net
Cc: netdev@vger.kernel.org
Subject: [PATCH 1/2] phylib: Support phy module autoloading
Date: Wed, 31 Mar 2010 02:18:54 +0100 [thread overview]
Message-ID: <1269998334.18090.278.camel@macbook.infradead.org> (raw)
We don't use the normal hotplug mechanism because it doesn't work. It will
load the module some time after the device appears, but that's not good
enough for us -- we need the driver loaded _immediately_ because otherwise
the NIC driver may just abort and then the phy 'device' goes away.
Instead, we just issue a request_module() directly in phy_device_create().
The device aliases take the form 'phy:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
with a binary representation of the phy_id. This means that the "don't
care" bits of driver's phy_id_mask can be question marks which modprobe
will interpret correctly as wildcards.
So a driver with { .phy_id = 0x02345600, .phy_id_mask = 0x0fffff00 }
will have an alias of phy:????00100011010001010110???????? and will be
loaded whenever any matching phy is created by phy_device_create().
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
---
drivers/net/phy/phy_device.c | 13 +++++++++++++
include/linux/mod_devicetable.h | 20 ++++++++++++++++++++
include/linux/phy.h | 1 +
scripts/mod/file2alias.c | 25 +++++++++++++++++++++++++
4 files changed, 59 insertions(+), 0 deletions(-)
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index db17945..b35ec7e 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -149,6 +149,8 @@ EXPORT_SYMBOL(phy_scan_fixups);
struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id)
{
struct phy_device *dev;
+ char modid[37];
+
/* We allocate the device, and initialize the
* default values */
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
@@ -179,6 +181,17 @@ struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id)
mutex_init(&dev->lock);
INIT_DELAYED_WORK(&dev->state_queue, phy_state_machine);
+#ifdef CONFIG_MODULES
+ /* Request the appropriate module unconditionally. A hotplug
+ event would have done so anyway. But normal hotplug won't
+ work for MDIO -- because it relies on the device staying
+ around for long enough for the driver to get loaded. With
+ MDIO, the NIC driver will get bored and give up as soon
+ as it finds that there's no driver _already_ loaded. */
+ sprintf(modid, "phy:" PHYID_FMT, PHYID_ARGS(phy_id));
+ request_module(modid);
+#endif
+
return dev;
}
EXPORT_SYMBOL(phy_device_create);
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index f58e9d8..0c3e300 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -474,4 +474,24 @@ struct platform_device_id {
__attribute__((aligned(sizeof(kernel_ulong_t))));
};
+#define PHY_MODULE_PREFIX "phy:"
+
+#define PHYID_FMT "%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d"
+#define PHYID_ARGS(_id) \
+ (_id)>>31, ((_id)>>30) & 1, ((_id)>>29) & 1, ((_id)>>28) & 1, \
+ ((_id)>>27) & 1, ((_id)>>26) & 1, ((_id)>>25) & 1, ((_id)>>24) & 1, \
+ ((_id)>>23) & 1, ((_id)>>22) & 1, ((_id)>>21) & 1, ((_id)>>20) & 1, \
+ ((_id)>>19) & 1, ((_id)>>18) & 1, ((_id)>>17) & 1, ((_id)>>16) & 1, \
+ ((_id)>>15) & 1, ((_id)>>14) & 1, ((_id)>>13) & 1, ((_id)>>12) & 1, \
+ ((_id)>>11) & 1, ((_id)>>10) & 1, ((_id)>>9) & 1, ((_id)>>8) & 1, \
+ ((_id)>>7) & 1, ((_id)>>6) & 1, ((_id)>>5) & 1, ((_id)>>4) & 1, \
+ ((_id)>>3) & 1, ((_id)>>2) & 1, ((_id)>>1) & 1, (_id) & 1
+
+
+
+struct phy_device_id {
+ uint32_t phy_id;
+ uint32_t phy_id_mask;
+};
+
#endif /* LINUX_MOD_DEVICETABLE_H */
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 14d7fdf..f269f1b 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -24,6 +24,7 @@
#include <linux/mii.h>
#include <linux/timer.h>
#include <linux/workqueue.h>
+#include <linux/mod_devicetable.h>
#include <asm/atomic.h>
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 220213e..b412185 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -796,6 +796,27 @@ static int do_platform_entry(const char *filename,
return 1;
}
+static int do_phy_entry(const char *filename,
+ struct phy_device_id *id, char *alias)
+{
+ char str[33];
+ int i;
+
+ str[32] = 0;
+
+ for (i = 0; i < 32; i++) {
+ if (!((id->phy_id_mask >> (31-i)) & 1))
+ str[i] = '?';
+ else if ((id->phy_id >> (31-i)) & 1)
+ str[i] = '1';
+ else
+ str[i] = '0';
+ }
+
+ sprintf(alias, PHY_MODULE_PREFIX "%s", str);
+ return 1;
+}
+
/* Ignore any prefix, eg. some architectures prepend _ */
static inline int sym_is(const char *symbol, const char *name)
{
@@ -943,6 +964,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
do_table(symval, sym->st_size,
sizeof(struct platform_device_id), "platform",
do_platform_entry, mod);
+ else if (sym_is(symname, "__mod_phy_device_table"))
+ do_table(symval, sym->st_size,
+ sizeof(struct phy_device_id), "phy",
+ do_phy_entry, mod);
free(zeros);
}
--
1.6.6.1
--
David Woodhouse Open Source Technology Centre
David.Woodhouse@intel.com Intel Corporation
next reply other threads:[~2010-03-31 1:18 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-03-31 1:18 David Woodhouse [this message]
2010-04-01 4:34 ` [PATCH 1/2] phylib: Support phy module autoloading Ben Hutchings
2010-04-01 17:03 ` David Woodhouse
2010-04-01 18:05 ` Ben Hutchings
2010-04-02 2:38 ` David Miller
2010-04-02 11:05 ` David Woodhouse
2010-04-02 17:51 ` Andy Fleming
2010-04-02 21:31 ` David Miller
2010-04-02 11:05 ` [PATCH 2/2] phylib: Add module table to all existing phy drivers David Woodhouse
2010-04-02 21:31 ` David Miller
2010-04-02 11:14 ` [PATCH 1/2] phylib: Support phy module autoloading David Woodhouse
2010-04-02 15:51 ` Ben Hutchings
2010-04-02 10:38 ` David Woodhouse
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1269998334.18090.278.camel@macbook.infradead.org \
--to=dwmw2@infradead.org \
--cc=davem@davemloft.net \
--cc=netdev@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).