2 * FUJITSU Extended Socket Network Device driver
3 * Copyright (c) 2015 FUJITSU LIMITED
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, see <http://www.gnu.org/licenses/>.
17 * The full GNU General Public License is included in this distribution in
18 * the file called "COPYING".
22 #include <linux/module.h>
23 #include <linux/types.h>
24 #include <linux/nls.h>
25 #include <linux/platform_device.h>
26 #include <linux/netdevice.h>
32 #define DRV_VERSION __stringify(MAJ) "." __stringify(MIN)
33 #define DRV_NAME "fjes"
34 char fjes_driver_name
[] = DRV_NAME
;
35 char fjes_driver_version
[] = DRV_VERSION
;
36 static const char fjes_driver_string
[] =
37 "FUJITSU Extended Socket Network Device Driver";
38 static const char fjes_copyright
[] =
39 "Copyright (c) 2015 FUJITSU LIMITED";
41 MODULE_AUTHOR("Taku Izumi <izumi.taku@jp.fujitsu.com>");
42 MODULE_DESCRIPTION("FUJITSU Extended Socket Network Device Driver");
43 MODULE_LICENSE("GPL");
44 MODULE_VERSION(DRV_VERSION
);
46 static int fjes_acpi_add(struct acpi_device
*);
47 static int fjes_acpi_remove(struct acpi_device
*);
48 static acpi_status
fjes_get_acpi_resource(struct acpi_resource
*, void*);
50 static int fjes_probe(struct platform_device
*);
51 static int fjes_remove(struct platform_device
*);
53 static int fjes_sw_init(struct fjes_adapter
*);
54 static void fjes_netdev_setup(struct net_device
*);
56 static const struct acpi_device_id fjes_acpi_ids
[] = {
60 MODULE_DEVICE_TABLE(acpi
, fjes_acpi_ids
);
62 static struct acpi_driver fjes_acpi_driver
= {
69 .remove
= fjes_acpi_remove
,
73 static struct platform_driver fjes_driver
= {
79 .remove
= fjes_remove
,
82 static struct resource fjes_resource
[] = {
84 .flags
= IORESOURCE_MEM
,
89 .flags
= IORESOURCE_IRQ
,
95 static int fjes_acpi_add(struct acpi_device
*device
)
97 struct acpi_buffer buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
98 char str_buf
[sizeof(FJES_ACPI_SYMBOL
) + 1];
99 struct platform_device
*plat_dev
;
100 union acpi_object
*str
;
104 status
= acpi_evaluate_object(device
->handle
, "_STR", NULL
, &buffer
);
105 if (ACPI_FAILURE(status
))
108 str
= buffer
.pointer
;
109 result
= utf16s_to_utf8s((wchar_t *)str
->string
.pointer
,
110 str
->string
.length
, UTF16_LITTLE_ENDIAN
,
111 str_buf
, sizeof(str_buf
) - 1);
114 if (strncmp(FJES_ACPI_SYMBOL
, str_buf
, strlen(FJES_ACPI_SYMBOL
)) != 0) {
115 kfree(buffer
.pointer
);
118 kfree(buffer
.pointer
);
120 status
= acpi_walk_resources(device
->handle
, METHOD_NAME__CRS
,
121 fjes_get_acpi_resource
, fjes_resource
);
122 if (ACPI_FAILURE(status
))
125 /* create platform_device */
126 plat_dev
= platform_device_register_simple(DRV_NAME
, 0, fjes_resource
,
127 ARRAY_SIZE(fjes_resource
));
128 device
->driver_data
= plat_dev
;
133 static int fjes_acpi_remove(struct acpi_device
*device
)
135 struct platform_device
*plat_dev
;
137 plat_dev
= (struct platform_device
*)acpi_driver_data(device
);
138 platform_device_unregister(plat_dev
);
144 fjes_get_acpi_resource(struct acpi_resource
*acpi_res
, void *data
)
146 struct acpi_resource_address32
*addr
;
147 struct acpi_resource_irq
*irq
;
148 struct resource
*res
= data
;
150 switch (acpi_res
->type
) {
151 case ACPI_RESOURCE_TYPE_ADDRESS32
:
152 addr
= &acpi_res
->data
.address32
;
153 res
[0].start
= addr
->address
.minimum
;
154 res
[0].end
= addr
->address
.minimum
+
155 addr
->address
.address_length
- 1;
158 case ACPI_RESOURCE_TYPE_IRQ
:
159 irq
= &acpi_res
->data
.irq
;
160 if (irq
->interrupt_count
!= 1)
162 res
[1].start
= irq
->interrupts
[0];
163 res
[1].end
= irq
->interrupts
[0];
173 static const struct net_device_ops fjes_netdev_ops
= {
176 /* fjes_probe - Device Initialization Routine */
177 static int fjes_probe(struct platform_device
*plat_dev
)
179 struct fjes_adapter
*adapter
;
180 struct net_device
*netdev
;
181 struct resource
*res
;
186 netdev
= alloc_netdev_mq(sizeof(struct fjes_adapter
), "es%d",
187 NET_NAME_UNKNOWN
, fjes_netdev_setup
,
193 SET_NETDEV_DEV(netdev
, &plat_dev
->dev
);
195 dev_set_drvdata(&plat_dev
->dev
, netdev
);
196 adapter
= netdev_priv(netdev
);
197 adapter
->netdev
= netdev
;
198 adapter
->plat_dev
= plat_dev
;
202 /* setup the private structure */
203 err
= fjes_sw_init(adapter
);
205 goto err_free_netdev
;
207 adapter
->force_reset
= false;
208 adapter
->open_guard
= false;
210 res
= platform_get_resource(plat_dev
, IORESOURCE_MEM
, 0);
211 hw
->hw_res
.start
= res
->start
;
212 hw
->hw_res
.size
= res
->end
- res
->start
+ 1;
213 hw
->hw_res
.irq
= platform_get_irq(plat_dev
, 0);
214 err
= fjes_hw_init(&adapter
->hw
);
216 goto err_free_netdev
;
218 /* setup MAC address (02:00:00:00:00:[epid])*/
219 netdev
->dev_addr
[0] = 2;
220 netdev
->dev_addr
[1] = 0;
221 netdev
->dev_addr
[2] = 0;
222 netdev
->dev_addr
[3] = 0;
223 netdev
->dev_addr
[4] = 0;
224 netdev
->dev_addr
[5] = hw
->my_epid
; /* EPID */
226 err
= register_netdev(netdev
);
230 netif_carrier_off(netdev
);
235 fjes_hw_exit(&adapter
->hw
);
242 /* fjes_remove - Device Removal Routine */
243 static int fjes_remove(struct platform_device
*plat_dev
)
245 struct net_device
*netdev
= dev_get_drvdata(&plat_dev
->dev
);
246 struct fjes_adapter
*adapter
= netdev_priv(netdev
);
247 struct fjes_hw
*hw
= &adapter
->hw
;
249 unregister_netdev(netdev
);
258 static int fjes_sw_init(struct fjes_adapter
*adapter
)
263 /* fjes_netdev_setup - netdevice initialization routine */
264 static void fjes_netdev_setup(struct net_device
*netdev
)
268 netdev
->watchdog_timeo
= FJES_TX_RETRY_INTERVAL
;
269 netdev
->netdev_ops
= &fjes_netdev_ops
;
270 netdev
->mtu
= fjes_support_mtu
[0];
271 netdev
->flags
|= IFF_BROADCAST
;
272 netdev
->features
|= NETIF_F_HW_CSUM
| NETIF_F_HW_VLAN_CTAG_FILTER
;
275 /* fjes_init_module - Driver Registration Routine */
276 static int __init
fjes_init_module(void)
280 pr_info("%s - version %s - %s\n",
281 fjes_driver_string
, fjes_driver_version
, fjes_copyright
);
283 result
= platform_driver_register(&fjes_driver
);
287 result
= acpi_bus_register_driver(&fjes_acpi_driver
);
289 goto fail_acpi_driver
;
294 platform_driver_unregister(&fjes_driver
);
298 module_init(fjes_init_module
);
300 /* fjes_exit_module - Driver Exit Cleanup Routine */
301 static void __exit
fjes_exit_module(void)
303 acpi_bus_unregister_driver(&fjes_acpi_driver
);
304 platform_driver_unregister(&fjes_driver
);
307 module_exit(fjes_exit_module
);