1658d439bSTaku Izumi /* 2658d439bSTaku Izumi * FUJITSU Extended Socket Network Device driver 3658d439bSTaku Izumi * Copyright (c) 2015 FUJITSU LIMITED 4658d439bSTaku Izumi * 5658d439bSTaku Izumi * This program is free software; you can redistribute it and/or modify it 6658d439bSTaku Izumi * under the terms and conditions of the GNU General Public License, 7658d439bSTaku Izumi * version 2, as published by the Free Software Foundation. 8658d439bSTaku Izumi * 9658d439bSTaku Izumi * This program is distributed in the hope it will be useful, but WITHOUT 10658d439bSTaku Izumi * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11658d439bSTaku Izumi * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12658d439bSTaku Izumi * more details. 13658d439bSTaku Izumi * 14658d439bSTaku Izumi * You should have received a copy of the GNU General Public License along with 15658d439bSTaku Izumi * this program; if not, see <http://www.gnu.org/licenses/>. 16658d439bSTaku Izumi * 17658d439bSTaku Izumi * The full GNU General Public License is included in this distribution in 18658d439bSTaku Izumi * the file called "COPYING". 19658d439bSTaku Izumi * 20658d439bSTaku Izumi */ 21658d439bSTaku Izumi 22658d439bSTaku Izumi #include <linux/module.h> 23658d439bSTaku Izumi #include <linux/types.h> 24658d439bSTaku Izumi #include <linux/nls.h> 25658d439bSTaku Izumi #include <linux/platform_device.h> 262fcbca68STaku Izumi #include <linux/netdevice.h> 27*e5d486dcSTaku Izumi #include <linux/interrupt.h> 28658d439bSTaku Izumi 29658d439bSTaku Izumi #include "fjes.h" 30658d439bSTaku Izumi 31658d439bSTaku Izumi #define MAJ 1 32658d439bSTaku Izumi #define MIN 0 33658d439bSTaku Izumi #define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) 34658d439bSTaku Izumi #define DRV_NAME "fjes" 35658d439bSTaku Izumi char fjes_driver_name[] = DRV_NAME; 36658d439bSTaku Izumi char fjes_driver_version[] = DRV_VERSION; 37658d439bSTaku Izumi static const char fjes_driver_string[] = 38658d439bSTaku Izumi "FUJITSU Extended Socket Network Device Driver"; 39658d439bSTaku Izumi static const char fjes_copyright[] = 40658d439bSTaku Izumi "Copyright (c) 2015 FUJITSU LIMITED"; 41658d439bSTaku Izumi 42658d439bSTaku Izumi MODULE_AUTHOR("Taku Izumi <izumi.taku@jp.fujitsu.com>"); 43658d439bSTaku Izumi MODULE_DESCRIPTION("FUJITSU Extended Socket Network Device Driver"); 44658d439bSTaku Izumi MODULE_LICENSE("GPL"); 45658d439bSTaku Izumi MODULE_VERSION(DRV_VERSION); 46658d439bSTaku Izumi 47*e5d486dcSTaku Izumi static int fjes_request_irq(struct fjes_adapter *); 48*e5d486dcSTaku Izumi static void fjes_free_irq(struct fjes_adapter *); 49*e5d486dcSTaku Izumi 50*e5d486dcSTaku Izumi static int fjes_open(struct net_device *); 51*e5d486dcSTaku Izumi static int fjes_close(struct net_device *); 52*e5d486dcSTaku Izumi static int fjes_setup_resources(struct fjes_adapter *); 53*e5d486dcSTaku Izumi static void fjes_free_resources(struct fjes_adapter *); 54*e5d486dcSTaku Izumi static irqreturn_t fjes_intr(int, void*); 55*e5d486dcSTaku Izumi 56658d439bSTaku Izumi static int fjes_acpi_add(struct acpi_device *); 57658d439bSTaku Izumi static int fjes_acpi_remove(struct acpi_device *); 58658d439bSTaku Izumi static acpi_status fjes_get_acpi_resource(struct acpi_resource *, void*); 59658d439bSTaku Izumi 60658d439bSTaku Izumi static int fjes_probe(struct platform_device *); 61658d439bSTaku Izumi static int fjes_remove(struct platform_device *); 62658d439bSTaku Izumi 632fcbca68STaku Izumi static int fjes_sw_init(struct fjes_adapter *); 642fcbca68STaku Izumi static void fjes_netdev_setup(struct net_device *); 652fcbca68STaku Izumi 66658d439bSTaku Izumi static const struct acpi_device_id fjes_acpi_ids[] = { 67658d439bSTaku Izumi {"PNP0C02", 0}, 68658d439bSTaku Izumi {"", 0}, 69658d439bSTaku Izumi }; 70658d439bSTaku Izumi MODULE_DEVICE_TABLE(acpi, fjes_acpi_ids); 71658d439bSTaku Izumi 72658d439bSTaku Izumi static struct acpi_driver fjes_acpi_driver = { 73658d439bSTaku Izumi .name = DRV_NAME, 74658d439bSTaku Izumi .class = DRV_NAME, 75658d439bSTaku Izumi .owner = THIS_MODULE, 76658d439bSTaku Izumi .ids = fjes_acpi_ids, 77658d439bSTaku Izumi .ops = { 78658d439bSTaku Izumi .add = fjes_acpi_add, 79658d439bSTaku Izumi .remove = fjes_acpi_remove, 80658d439bSTaku Izumi }, 81658d439bSTaku Izumi }; 82658d439bSTaku Izumi 83658d439bSTaku Izumi static struct platform_driver fjes_driver = { 84658d439bSTaku Izumi .driver = { 85658d439bSTaku Izumi .name = DRV_NAME, 86658d439bSTaku Izumi .owner = THIS_MODULE, 87658d439bSTaku Izumi }, 88658d439bSTaku Izumi .probe = fjes_probe, 89658d439bSTaku Izumi .remove = fjes_remove, 90658d439bSTaku Izumi }; 91658d439bSTaku Izumi 92658d439bSTaku Izumi static struct resource fjes_resource[] = { 93658d439bSTaku Izumi { 94658d439bSTaku Izumi .flags = IORESOURCE_MEM, 95658d439bSTaku Izumi .start = 0, 96658d439bSTaku Izumi .end = 0, 97658d439bSTaku Izumi }, 98658d439bSTaku Izumi { 99658d439bSTaku Izumi .flags = IORESOURCE_IRQ, 100658d439bSTaku Izumi .start = 0, 101658d439bSTaku Izumi .end = 0, 102658d439bSTaku Izumi }, 103658d439bSTaku Izumi }; 104658d439bSTaku Izumi 105658d439bSTaku Izumi static int fjes_acpi_add(struct acpi_device *device) 106658d439bSTaku Izumi { 107658d439bSTaku Izumi struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL}; 108658d439bSTaku Izumi char str_buf[sizeof(FJES_ACPI_SYMBOL) + 1]; 109658d439bSTaku Izumi struct platform_device *plat_dev; 110658d439bSTaku Izumi union acpi_object *str; 111658d439bSTaku Izumi acpi_status status; 112658d439bSTaku Izumi int result; 113658d439bSTaku Izumi 114658d439bSTaku Izumi status = acpi_evaluate_object(device->handle, "_STR", NULL, &buffer); 115658d439bSTaku Izumi if (ACPI_FAILURE(status)) 116658d439bSTaku Izumi return -ENODEV; 117658d439bSTaku Izumi 118658d439bSTaku Izumi str = buffer.pointer; 119658d439bSTaku Izumi result = utf16s_to_utf8s((wchar_t *)str->string.pointer, 120658d439bSTaku Izumi str->string.length, UTF16_LITTLE_ENDIAN, 121658d439bSTaku Izumi str_buf, sizeof(str_buf) - 1); 122658d439bSTaku Izumi str_buf[result] = 0; 123658d439bSTaku Izumi 124658d439bSTaku Izumi if (strncmp(FJES_ACPI_SYMBOL, str_buf, strlen(FJES_ACPI_SYMBOL)) != 0) { 125658d439bSTaku Izumi kfree(buffer.pointer); 126658d439bSTaku Izumi return -ENODEV; 127658d439bSTaku Izumi } 128658d439bSTaku Izumi kfree(buffer.pointer); 129658d439bSTaku Izumi 130658d439bSTaku Izumi status = acpi_walk_resources(device->handle, METHOD_NAME__CRS, 131658d439bSTaku Izumi fjes_get_acpi_resource, fjes_resource); 132658d439bSTaku Izumi if (ACPI_FAILURE(status)) 133658d439bSTaku Izumi return -ENODEV; 134658d439bSTaku Izumi 135658d439bSTaku Izumi /* create platform_device */ 136658d439bSTaku Izumi plat_dev = platform_device_register_simple(DRV_NAME, 0, fjes_resource, 137658d439bSTaku Izumi ARRAY_SIZE(fjes_resource)); 138658d439bSTaku Izumi device->driver_data = plat_dev; 139658d439bSTaku Izumi 140658d439bSTaku Izumi return 0; 141658d439bSTaku Izumi } 142658d439bSTaku Izumi 143658d439bSTaku Izumi static int fjes_acpi_remove(struct acpi_device *device) 144658d439bSTaku Izumi { 145658d439bSTaku Izumi struct platform_device *plat_dev; 146658d439bSTaku Izumi 147658d439bSTaku Izumi plat_dev = (struct platform_device *)acpi_driver_data(device); 148658d439bSTaku Izumi platform_device_unregister(plat_dev); 149658d439bSTaku Izumi 150658d439bSTaku Izumi return 0; 151658d439bSTaku Izumi } 152658d439bSTaku Izumi 153658d439bSTaku Izumi static acpi_status 154658d439bSTaku Izumi fjes_get_acpi_resource(struct acpi_resource *acpi_res, void *data) 155658d439bSTaku Izumi { 156658d439bSTaku Izumi struct acpi_resource_address32 *addr; 157658d439bSTaku Izumi struct acpi_resource_irq *irq; 158658d439bSTaku Izumi struct resource *res = data; 159658d439bSTaku Izumi 160658d439bSTaku Izumi switch (acpi_res->type) { 161658d439bSTaku Izumi case ACPI_RESOURCE_TYPE_ADDRESS32: 162658d439bSTaku Izumi addr = &acpi_res->data.address32; 163658d439bSTaku Izumi res[0].start = addr->address.minimum; 164658d439bSTaku Izumi res[0].end = addr->address.minimum + 165658d439bSTaku Izumi addr->address.address_length - 1; 166658d439bSTaku Izumi break; 167658d439bSTaku Izumi 168658d439bSTaku Izumi case ACPI_RESOURCE_TYPE_IRQ: 169658d439bSTaku Izumi irq = &acpi_res->data.irq; 170658d439bSTaku Izumi if (irq->interrupt_count != 1) 171658d439bSTaku Izumi return AE_ERROR; 172658d439bSTaku Izumi res[1].start = irq->interrupts[0]; 173658d439bSTaku Izumi res[1].end = irq->interrupts[0]; 174658d439bSTaku Izumi break; 175658d439bSTaku Izumi 176658d439bSTaku Izumi default: 177658d439bSTaku Izumi break; 178658d439bSTaku Izumi } 179658d439bSTaku Izumi 180658d439bSTaku Izumi return AE_OK; 181658d439bSTaku Izumi } 182658d439bSTaku Izumi 183*e5d486dcSTaku Izumi static int fjes_request_irq(struct fjes_adapter *adapter) 184*e5d486dcSTaku Izumi { 185*e5d486dcSTaku Izumi struct net_device *netdev = adapter->netdev; 186*e5d486dcSTaku Izumi int result = -1; 187*e5d486dcSTaku Izumi 188*e5d486dcSTaku Izumi if (!adapter->irq_registered) { 189*e5d486dcSTaku Izumi result = request_irq(adapter->hw.hw_res.irq, fjes_intr, 190*e5d486dcSTaku Izumi IRQF_SHARED, netdev->name, adapter); 191*e5d486dcSTaku Izumi if (result) 192*e5d486dcSTaku Izumi adapter->irq_registered = false; 193*e5d486dcSTaku Izumi else 194*e5d486dcSTaku Izumi adapter->irq_registered = true; 195*e5d486dcSTaku Izumi } 196*e5d486dcSTaku Izumi 197*e5d486dcSTaku Izumi return result; 198*e5d486dcSTaku Izumi } 199*e5d486dcSTaku Izumi 200*e5d486dcSTaku Izumi static void fjes_free_irq(struct fjes_adapter *adapter) 201*e5d486dcSTaku Izumi { 202*e5d486dcSTaku Izumi struct fjes_hw *hw = &adapter->hw; 203*e5d486dcSTaku Izumi 204*e5d486dcSTaku Izumi fjes_hw_set_irqmask(hw, REG_ICTL_MASK_ALL, true); 205*e5d486dcSTaku Izumi 206*e5d486dcSTaku Izumi if (adapter->irq_registered) { 207*e5d486dcSTaku Izumi free_irq(adapter->hw.hw_res.irq, adapter); 208*e5d486dcSTaku Izumi adapter->irq_registered = false; 209*e5d486dcSTaku Izumi } 210*e5d486dcSTaku Izumi } 211*e5d486dcSTaku Izumi 2122fcbca68STaku Izumi static const struct net_device_ops fjes_netdev_ops = { 213*e5d486dcSTaku Izumi .ndo_open = fjes_open, 214*e5d486dcSTaku Izumi .ndo_stop = fjes_close, 2152fcbca68STaku Izumi }; 2162fcbca68STaku Izumi 217*e5d486dcSTaku Izumi /* fjes_open - Called when a network interface is made active */ 218*e5d486dcSTaku Izumi static int fjes_open(struct net_device *netdev) 219*e5d486dcSTaku Izumi { 220*e5d486dcSTaku Izumi struct fjes_adapter *adapter = netdev_priv(netdev); 221*e5d486dcSTaku Izumi struct fjes_hw *hw = &adapter->hw; 222*e5d486dcSTaku Izumi int result; 223*e5d486dcSTaku Izumi 224*e5d486dcSTaku Izumi if (adapter->open_guard) 225*e5d486dcSTaku Izumi return -ENXIO; 226*e5d486dcSTaku Izumi 227*e5d486dcSTaku Izumi result = fjes_setup_resources(adapter); 228*e5d486dcSTaku Izumi if (result) 229*e5d486dcSTaku Izumi goto err_setup_res; 230*e5d486dcSTaku Izumi 231*e5d486dcSTaku Izumi hw->txrx_stop_req_bit = 0; 232*e5d486dcSTaku Izumi hw->epstop_req_bit = 0; 233*e5d486dcSTaku Izumi 234*e5d486dcSTaku Izumi fjes_hw_capture_interrupt_status(hw); 235*e5d486dcSTaku Izumi 236*e5d486dcSTaku Izumi result = fjes_request_irq(adapter); 237*e5d486dcSTaku Izumi if (result) 238*e5d486dcSTaku Izumi goto err_req_irq; 239*e5d486dcSTaku Izumi 240*e5d486dcSTaku Izumi fjes_hw_set_irqmask(hw, REG_ICTL_MASK_ALL, false); 241*e5d486dcSTaku Izumi 242*e5d486dcSTaku Izumi netif_tx_start_all_queues(netdev); 243*e5d486dcSTaku Izumi netif_carrier_on(netdev); 244*e5d486dcSTaku Izumi 245*e5d486dcSTaku Izumi return 0; 246*e5d486dcSTaku Izumi 247*e5d486dcSTaku Izumi err_req_irq: 248*e5d486dcSTaku Izumi fjes_free_irq(adapter); 249*e5d486dcSTaku Izumi 250*e5d486dcSTaku Izumi err_setup_res: 251*e5d486dcSTaku Izumi fjes_free_resources(adapter); 252*e5d486dcSTaku Izumi return result; 253*e5d486dcSTaku Izumi } 254*e5d486dcSTaku Izumi 255*e5d486dcSTaku Izumi /* fjes_close - Disables a network interface */ 256*e5d486dcSTaku Izumi static int fjes_close(struct net_device *netdev) 257*e5d486dcSTaku Izumi { 258*e5d486dcSTaku Izumi struct fjes_adapter *adapter = netdev_priv(netdev); 259*e5d486dcSTaku Izumi struct fjes_hw *hw = &adapter->hw; 260*e5d486dcSTaku Izumi int epidx; 261*e5d486dcSTaku Izumi 262*e5d486dcSTaku Izumi netif_tx_stop_all_queues(netdev); 263*e5d486dcSTaku Izumi netif_carrier_off(netdev); 264*e5d486dcSTaku Izumi 265*e5d486dcSTaku Izumi fjes_hw_raise_epstop(hw); 266*e5d486dcSTaku Izumi 267*e5d486dcSTaku Izumi for (epidx = 0; epidx < hw->max_epid; epidx++) { 268*e5d486dcSTaku Izumi if (epidx == hw->my_epid) 269*e5d486dcSTaku Izumi continue; 270*e5d486dcSTaku Izumi 271*e5d486dcSTaku Izumi adapter->hw.ep_shm_info[epidx].tx.info->v1i.rx_status &= 272*e5d486dcSTaku Izumi ~FJES_RX_POLL_WORK; 273*e5d486dcSTaku Izumi } 274*e5d486dcSTaku Izumi 275*e5d486dcSTaku Izumi fjes_free_irq(adapter); 276*e5d486dcSTaku Izumi 277*e5d486dcSTaku Izumi fjes_hw_wait_epstop(hw); 278*e5d486dcSTaku Izumi 279*e5d486dcSTaku Izumi fjes_free_resources(adapter); 280*e5d486dcSTaku Izumi 281*e5d486dcSTaku Izumi return 0; 282*e5d486dcSTaku Izumi } 283*e5d486dcSTaku Izumi 284*e5d486dcSTaku Izumi static int fjes_setup_resources(struct fjes_adapter *adapter) 285*e5d486dcSTaku Izumi { 286*e5d486dcSTaku Izumi struct net_device *netdev = adapter->netdev; 287*e5d486dcSTaku Izumi struct ep_share_mem_info *buf_pair; 288*e5d486dcSTaku Izumi struct fjes_hw *hw = &adapter->hw; 289*e5d486dcSTaku Izumi int result; 290*e5d486dcSTaku Izumi int epidx; 291*e5d486dcSTaku Izumi 292*e5d486dcSTaku Izumi mutex_lock(&hw->hw_info.lock); 293*e5d486dcSTaku Izumi result = fjes_hw_request_info(hw); 294*e5d486dcSTaku Izumi switch (result) { 295*e5d486dcSTaku Izumi case 0: 296*e5d486dcSTaku Izumi for (epidx = 0; epidx < hw->max_epid; epidx++) { 297*e5d486dcSTaku Izumi hw->ep_shm_info[epidx].es_status = 298*e5d486dcSTaku Izumi hw->hw_info.res_buf->info.info[epidx].es_status; 299*e5d486dcSTaku Izumi hw->ep_shm_info[epidx].zone = 300*e5d486dcSTaku Izumi hw->hw_info.res_buf->info.info[epidx].zone; 301*e5d486dcSTaku Izumi } 302*e5d486dcSTaku Izumi break; 303*e5d486dcSTaku Izumi default: 304*e5d486dcSTaku Izumi case -ENOMSG: 305*e5d486dcSTaku Izumi case -EBUSY: 306*e5d486dcSTaku Izumi adapter->force_reset = true; 307*e5d486dcSTaku Izumi 308*e5d486dcSTaku Izumi mutex_unlock(&hw->hw_info.lock); 309*e5d486dcSTaku Izumi return result; 310*e5d486dcSTaku Izumi } 311*e5d486dcSTaku Izumi mutex_unlock(&hw->hw_info.lock); 312*e5d486dcSTaku Izumi 313*e5d486dcSTaku Izumi for (epidx = 0; epidx < (hw->max_epid); epidx++) { 314*e5d486dcSTaku Izumi if ((epidx != hw->my_epid) && 315*e5d486dcSTaku Izumi (hw->ep_shm_info[epidx].es_status == 316*e5d486dcSTaku Izumi FJES_ZONING_STATUS_ENABLE)) { 317*e5d486dcSTaku Izumi fjes_hw_raise_interrupt(hw, epidx, 318*e5d486dcSTaku Izumi REG_ICTL_MASK_INFO_UPDATE); 319*e5d486dcSTaku Izumi } 320*e5d486dcSTaku Izumi } 321*e5d486dcSTaku Izumi 322*e5d486dcSTaku Izumi msleep(FJES_OPEN_ZONE_UPDATE_WAIT * hw->max_epid); 323*e5d486dcSTaku Izumi 324*e5d486dcSTaku Izumi for (epidx = 0; epidx < (hw->max_epid); epidx++) { 325*e5d486dcSTaku Izumi if (epidx == hw->my_epid) 326*e5d486dcSTaku Izumi continue; 327*e5d486dcSTaku Izumi 328*e5d486dcSTaku Izumi buf_pair = &hw->ep_shm_info[epidx]; 329*e5d486dcSTaku Izumi 330*e5d486dcSTaku Izumi fjes_hw_setup_epbuf(&buf_pair->tx, netdev->dev_addr, 331*e5d486dcSTaku Izumi netdev->mtu); 332*e5d486dcSTaku Izumi 333*e5d486dcSTaku Izumi if (fjes_hw_epid_is_same_zone(hw, epidx)) { 334*e5d486dcSTaku Izumi mutex_lock(&hw->hw_info.lock); 335*e5d486dcSTaku Izumi result = 336*e5d486dcSTaku Izumi fjes_hw_register_buff_addr(hw, epidx, buf_pair); 337*e5d486dcSTaku Izumi mutex_unlock(&hw->hw_info.lock); 338*e5d486dcSTaku Izumi 339*e5d486dcSTaku Izumi switch (result) { 340*e5d486dcSTaku Izumi case 0: 341*e5d486dcSTaku Izumi break; 342*e5d486dcSTaku Izumi case -ENOMSG: 343*e5d486dcSTaku Izumi case -EBUSY: 344*e5d486dcSTaku Izumi default: 345*e5d486dcSTaku Izumi adapter->force_reset = true; 346*e5d486dcSTaku Izumi return result; 347*e5d486dcSTaku Izumi } 348*e5d486dcSTaku Izumi } 349*e5d486dcSTaku Izumi } 350*e5d486dcSTaku Izumi 351*e5d486dcSTaku Izumi return 0; 352*e5d486dcSTaku Izumi } 353*e5d486dcSTaku Izumi 354*e5d486dcSTaku Izumi static void fjes_free_resources(struct fjes_adapter *adapter) 355*e5d486dcSTaku Izumi { 356*e5d486dcSTaku Izumi struct net_device *netdev = adapter->netdev; 357*e5d486dcSTaku Izumi struct fjes_device_command_param param; 358*e5d486dcSTaku Izumi struct ep_share_mem_info *buf_pair; 359*e5d486dcSTaku Izumi struct fjes_hw *hw = &adapter->hw; 360*e5d486dcSTaku Izumi bool reset_flag = false; 361*e5d486dcSTaku Izumi int result; 362*e5d486dcSTaku Izumi int epidx; 363*e5d486dcSTaku Izumi 364*e5d486dcSTaku Izumi for (epidx = 0; epidx < hw->max_epid; epidx++) { 365*e5d486dcSTaku Izumi if (epidx == hw->my_epid) 366*e5d486dcSTaku Izumi continue; 367*e5d486dcSTaku Izumi 368*e5d486dcSTaku Izumi mutex_lock(&hw->hw_info.lock); 369*e5d486dcSTaku Izumi result = fjes_hw_unregister_buff_addr(hw, epidx); 370*e5d486dcSTaku Izumi mutex_unlock(&hw->hw_info.lock); 371*e5d486dcSTaku Izumi 372*e5d486dcSTaku Izumi if (result) 373*e5d486dcSTaku Izumi reset_flag = true; 374*e5d486dcSTaku Izumi 375*e5d486dcSTaku Izumi buf_pair = &hw->ep_shm_info[epidx]; 376*e5d486dcSTaku Izumi 377*e5d486dcSTaku Izumi fjes_hw_setup_epbuf(&buf_pair->tx, 378*e5d486dcSTaku Izumi netdev->dev_addr, netdev->mtu); 379*e5d486dcSTaku Izumi 380*e5d486dcSTaku Izumi clear_bit(epidx, &hw->txrx_stop_req_bit); 381*e5d486dcSTaku Izumi } 382*e5d486dcSTaku Izumi 383*e5d486dcSTaku Izumi if (reset_flag || adapter->force_reset) { 384*e5d486dcSTaku Izumi result = fjes_hw_reset(hw); 385*e5d486dcSTaku Izumi 386*e5d486dcSTaku Izumi adapter->force_reset = false; 387*e5d486dcSTaku Izumi 388*e5d486dcSTaku Izumi if (result) 389*e5d486dcSTaku Izumi adapter->open_guard = true; 390*e5d486dcSTaku Izumi 391*e5d486dcSTaku Izumi hw->hw_info.buffer_share_bit = 0; 392*e5d486dcSTaku Izumi 393*e5d486dcSTaku Izumi memset((void *)¶m, 0, sizeof(param)); 394*e5d486dcSTaku Izumi 395*e5d486dcSTaku Izumi param.req_len = hw->hw_info.req_buf_size; 396*e5d486dcSTaku Izumi param.req_start = __pa(hw->hw_info.req_buf); 397*e5d486dcSTaku Izumi param.res_len = hw->hw_info.res_buf_size; 398*e5d486dcSTaku Izumi param.res_start = __pa(hw->hw_info.res_buf); 399*e5d486dcSTaku Izumi param.share_start = __pa(hw->hw_info.share->ep_status); 400*e5d486dcSTaku Izumi 401*e5d486dcSTaku Izumi fjes_hw_init_command_registers(hw, ¶m); 402*e5d486dcSTaku Izumi } 403*e5d486dcSTaku Izumi } 404*e5d486dcSTaku Izumi 405*e5d486dcSTaku Izumi static irqreturn_t fjes_intr(int irq, void *data) 406*e5d486dcSTaku Izumi { 407*e5d486dcSTaku Izumi struct fjes_adapter *adapter = data; 408*e5d486dcSTaku Izumi struct fjes_hw *hw = &adapter->hw; 409*e5d486dcSTaku Izumi irqreturn_t ret; 410*e5d486dcSTaku Izumi u32 icr; 411*e5d486dcSTaku Izumi 412*e5d486dcSTaku Izumi icr = fjes_hw_capture_interrupt_status(hw); 413*e5d486dcSTaku Izumi 414*e5d486dcSTaku Izumi if (icr & REG_IS_MASK_IS_ASSERT) 415*e5d486dcSTaku Izumi ret = IRQ_HANDLED; 416*e5d486dcSTaku Izumi else 417*e5d486dcSTaku Izumi ret = IRQ_NONE; 418*e5d486dcSTaku Izumi 419*e5d486dcSTaku Izumi return ret; 420*e5d486dcSTaku Izumi } 421*e5d486dcSTaku Izumi 422658d439bSTaku Izumi /* fjes_probe - Device Initialization Routine */ 423658d439bSTaku Izumi static int fjes_probe(struct platform_device *plat_dev) 424658d439bSTaku Izumi { 4252fcbca68STaku Izumi struct fjes_adapter *adapter; 4262fcbca68STaku Izumi struct net_device *netdev; 4272fcbca68STaku Izumi struct resource *res; 4282fcbca68STaku Izumi struct fjes_hw *hw; 4292fcbca68STaku Izumi int err; 4302fcbca68STaku Izumi 4312fcbca68STaku Izumi err = -ENOMEM; 4322fcbca68STaku Izumi netdev = alloc_netdev_mq(sizeof(struct fjes_adapter), "es%d", 4332fcbca68STaku Izumi NET_NAME_UNKNOWN, fjes_netdev_setup, 4342fcbca68STaku Izumi FJES_MAX_QUEUES); 4352fcbca68STaku Izumi 4362fcbca68STaku Izumi if (!netdev) 4372fcbca68STaku Izumi goto err_out; 4382fcbca68STaku Izumi 4392fcbca68STaku Izumi SET_NETDEV_DEV(netdev, &plat_dev->dev); 4402fcbca68STaku Izumi 4412fcbca68STaku Izumi dev_set_drvdata(&plat_dev->dev, netdev); 4422fcbca68STaku Izumi adapter = netdev_priv(netdev); 4432fcbca68STaku Izumi adapter->netdev = netdev; 4442fcbca68STaku Izumi adapter->plat_dev = plat_dev; 4452fcbca68STaku Izumi hw = &adapter->hw; 4462fcbca68STaku Izumi hw->back = adapter; 4472fcbca68STaku Izumi 4482fcbca68STaku Izumi /* setup the private structure */ 4492fcbca68STaku Izumi err = fjes_sw_init(adapter); 4502fcbca68STaku Izumi if (err) 4512fcbca68STaku Izumi goto err_free_netdev; 4522fcbca68STaku Izumi 4532fcbca68STaku Izumi adapter->force_reset = false; 4542fcbca68STaku Izumi adapter->open_guard = false; 4552fcbca68STaku Izumi 4562fcbca68STaku Izumi res = platform_get_resource(plat_dev, IORESOURCE_MEM, 0); 4572fcbca68STaku Izumi hw->hw_res.start = res->start; 4582fcbca68STaku Izumi hw->hw_res.size = res->end - res->start + 1; 4592fcbca68STaku Izumi hw->hw_res.irq = platform_get_irq(plat_dev, 0); 4602fcbca68STaku Izumi err = fjes_hw_init(&adapter->hw); 4612fcbca68STaku Izumi if (err) 4622fcbca68STaku Izumi goto err_free_netdev; 4632fcbca68STaku Izumi 4642fcbca68STaku Izumi /* setup MAC address (02:00:00:00:00:[epid])*/ 4652fcbca68STaku Izumi netdev->dev_addr[0] = 2; 4662fcbca68STaku Izumi netdev->dev_addr[1] = 0; 4672fcbca68STaku Izumi netdev->dev_addr[2] = 0; 4682fcbca68STaku Izumi netdev->dev_addr[3] = 0; 4692fcbca68STaku Izumi netdev->dev_addr[4] = 0; 4702fcbca68STaku Izumi netdev->dev_addr[5] = hw->my_epid; /* EPID */ 4712fcbca68STaku Izumi 4722fcbca68STaku Izumi err = register_netdev(netdev); 4732fcbca68STaku Izumi if (err) 4742fcbca68STaku Izumi goto err_hw_exit; 4752fcbca68STaku Izumi 4762fcbca68STaku Izumi netif_carrier_off(netdev); 4772fcbca68STaku Izumi 478658d439bSTaku Izumi return 0; 4792fcbca68STaku Izumi 4802fcbca68STaku Izumi err_hw_exit: 4812fcbca68STaku Izumi fjes_hw_exit(&adapter->hw); 4822fcbca68STaku Izumi err_free_netdev: 4832fcbca68STaku Izumi free_netdev(netdev); 4842fcbca68STaku Izumi err_out: 4852fcbca68STaku Izumi return err; 486658d439bSTaku Izumi } 487658d439bSTaku Izumi 488658d439bSTaku Izumi /* fjes_remove - Device Removal Routine */ 489658d439bSTaku Izumi static int fjes_remove(struct platform_device *plat_dev) 490658d439bSTaku Izumi { 4912fcbca68STaku Izumi struct net_device *netdev = dev_get_drvdata(&plat_dev->dev); 4922fcbca68STaku Izumi struct fjes_adapter *adapter = netdev_priv(netdev); 4932fcbca68STaku Izumi struct fjes_hw *hw = &adapter->hw; 4942fcbca68STaku Izumi 4952fcbca68STaku Izumi unregister_netdev(netdev); 4962fcbca68STaku Izumi 4972fcbca68STaku Izumi fjes_hw_exit(hw); 4982fcbca68STaku Izumi 4992fcbca68STaku Izumi free_netdev(netdev); 5002fcbca68STaku Izumi 501658d439bSTaku Izumi return 0; 502658d439bSTaku Izumi } 503658d439bSTaku Izumi 5042fcbca68STaku Izumi static int fjes_sw_init(struct fjes_adapter *adapter) 5052fcbca68STaku Izumi { 5062fcbca68STaku Izumi return 0; 5072fcbca68STaku Izumi } 5082fcbca68STaku Izumi 5092fcbca68STaku Izumi /* fjes_netdev_setup - netdevice initialization routine */ 5102fcbca68STaku Izumi static void fjes_netdev_setup(struct net_device *netdev) 5112fcbca68STaku Izumi { 5122fcbca68STaku Izumi ether_setup(netdev); 5132fcbca68STaku Izumi 5142fcbca68STaku Izumi netdev->watchdog_timeo = FJES_TX_RETRY_INTERVAL; 5152fcbca68STaku Izumi netdev->netdev_ops = &fjes_netdev_ops; 5162fcbca68STaku Izumi netdev->mtu = fjes_support_mtu[0]; 5172fcbca68STaku Izumi netdev->flags |= IFF_BROADCAST; 5182fcbca68STaku Izumi netdev->features |= NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_CTAG_FILTER; 5192fcbca68STaku Izumi } 5202fcbca68STaku Izumi 521658d439bSTaku Izumi /* fjes_init_module - Driver Registration Routine */ 522658d439bSTaku Izumi static int __init fjes_init_module(void) 523658d439bSTaku Izumi { 524658d439bSTaku Izumi int result; 525658d439bSTaku Izumi 526658d439bSTaku Izumi pr_info("%s - version %s - %s\n", 527658d439bSTaku Izumi fjes_driver_string, fjes_driver_version, fjes_copyright); 528658d439bSTaku Izumi 529658d439bSTaku Izumi result = platform_driver_register(&fjes_driver); 530658d439bSTaku Izumi if (result < 0) 531658d439bSTaku Izumi return result; 532658d439bSTaku Izumi 533658d439bSTaku Izumi result = acpi_bus_register_driver(&fjes_acpi_driver); 534658d439bSTaku Izumi if (result < 0) 535658d439bSTaku Izumi goto fail_acpi_driver; 536658d439bSTaku Izumi 537658d439bSTaku Izumi return 0; 538658d439bSTaku Izumi 539658d439bSTaku Izumi fail_acpi_driver: 540658d439bSTaku Izumi platform_driver_unregister(&fjes_driver); 541658d439bSTaku Izumi return result; 542658d439bSTaku Izumi } 543658d439bSTaku Izumi 544658d439bSTaku Izumi module_init(fjes_init_module); 545658d439bSTaku Izumi 546658d439bSTaku Izumi /* fjes_exit_module - Driver Exit Cleanup Routine */ 547658d439bSTaku Izumi static void __exit fjes_exit_module(void) 548658d439bSTaku Izumi { 549658d439bSTaku Izumi acpi_bus_unregister_driver(&fjes_acpi_driver); 550658d439bSTaku Izumi platform_driver_unregister(&fjes_driver); 551658d439bSTaku Izumi } 552658d439bSTaku Izumi 553658d439bSTaku Izumi module_exit(fjes_exit_module); 554