1*56051948SVladimir Oltean // SPDX-License-Identifier: GPL-2.0 2*56051948SVladimir Oltean /* Copyright 2019 NXP Semiconductors 3*56051948SVladimir Oltean */ 4*56051948SVladimir Oltean #include <uapi/linux/if_bridge.h> 5*56051948SVladimir Oltean #include <soc/mscc/ocelot.h> 6*56051948SVladimir Oltean #include <linux/module.h> 7*56051948SVladimir Oltean #include <linux/pci.h> 8*56051948SVladimir Oltean #include <linux/of.h> 9*56051948SVladimir Oltean #include <net/dsa.h> 10*56051948SVladimir Oltean #include "felix.h" 11*56051948SVladimir Oltean 12*56051948SVladimir Oltean static enum dsa_tag_protocol felix_get_tag_protocol(struct dsa_switch *ds, 13*56051948SVladimir Oltean int port) 14*56051948SVladimir Oltean { 15*56051948SVladimir Oltean return DSA_TAG_PROTO_OCELOT; 16*56051948SVladimir Oltean } 17*56051948SVladimir Oltean 18*56051948SVladimir Oltean static int felix_set_ageing_time(struct dsa_switch *ds, 19*56051948SVladimir Oltean unsigned int ageing_time) 20*56051948SVladimir Oltean { 21*56051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 22*56051948SVladimir Oltean 23*56051948SVladimir Oltean ocelot_set_ageing_time(ocelot, ageing_time); 24*56051948SVladimir Oltean 25*56051948SVladimir Oltean return 0; 26*56051948SVladimir Oltean } 27*56051948SVladimir Oltean 28*56051948SVladimir Oltean static void felix_adjust_link(struct dsa_switch *ds, int port, 29*56051948SVladimir Oltean struct phy_device *phydev) 30*56051948SVladimir Oltean { 31*56051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 32*56051948SVladimir Oltean 33*56051948SVladimir Oltean ocelot_adjust_link(ocelot, port, phydev); 34*56051948SVladimir Oltean } 35*56051948SVladimir Oltean 36*56051948SVladimir Oltean static int felix_fdb_dump(struct dsa_switch *ds, int port, 37*56051948SVladimir Oltean dsa_fdb_dump_cb_t *cb, void *data) 38*56051948SVladimir Oltean { 39*56051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 40*56051948SVladimir Oltean 41*56051948SVladimir Oltean return ocelot_fdb_dump(ocelot, port, cb, data); 42*56051948SVladimir Oltean } 43*56051948SVladimir Oltean 44*56051948SVladimir Oltean static int felix_fdb_add(struct dsa_switch *ds, int port, 45*56051948SVladimir Oltean const unsigned char *addr, u16 vid) 46*56051948SVladimir Oltean { 47*56051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 48*56051948SVladimir Oltean bool vlan_aware; 49*56051948SVladimir Oltean 50*56051948SVladimir Oltean vlan_aware = dsa_port_is_vlan_filtering(dsa_to_port(ds, port)); 51*56051948SVladimir Oltean 52*56051948SVladimir Oltean return ocelot_fdb_add(ocelot, port, addr, vid, vlan_aware); 53*56051948SVladimir Oltean } 54*56051948SVladimir Oltean 55*56051948SVladimir Oltean static int felix_fdb_del(struct dsa_switch *ds, int port, 56*56051948SVladimir Oltean const unsigned char *addr, u16 vid) 57*56051948SVladimir Oltean { 58*56051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 59*56051948SVladimir Oltean 60*56051948SVladimir Oltean return ocelot_fdb_del(ocelot, port, addr, vid); 61*56051948SVladimir Oltean } 62*56051948SVladimir Oltean 63*56051948SVladimir Oltean static void felix_bridge_stp_state_set(struct dsa_switch *ds, int port, 64*56051948SVladimir Oltean u8 state) 65*56051948SVladimir Oltean { 66*56051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 67*56051948SVladimir Oltean 68*56051948SVladimir Oltean return ocelot_bridge_stp_state_set(ocelot, port, state); 69*56051948SVladimir Oltean } 70*56051948SVladimir Oltean 71*56051948SVladimir Oltean static int felix_bridge_join(struct dsa_switch *ds, int port, 72*56051948SVladimir Oltean struct net_device *br) 73*56051948SVladimir Oltean { 74*56051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 75*56051948SVladimir Oltean 76*56051948SVladimir Oltean return ocelot_port_bridge_join(ocelot, port, br); 77*56051948SVladimir Oltean } 78*56051948SVladimir Oltean 79*56051948SVladimir Oltean static void felix_bridge_leave(struct dsa_switch *ds, int port, 80*56051948SVladimir Oltean struct net_device *br) 81*56051948SVladimir Oltean { 82*56051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 83*56051948SVladimir Oltean 84*56051948SVladimir Oltean ocelot_port_bridge_leave(ocelot, port, br); 85*56051948SVladimir Oltean } 86*56051948SVladimir Oltean 87*56051948SVladimir Oltean /* This callback needs to be present */ 88*56051948SVladimir Oltean static int felix_vlan_prepare(struct dsa_switch *ds, int port, 89*56051948SVladimir Oltean const struct switchdev_obj_port_vlan *vlan) 90*56051948SVladimir Oltean { 91*56051948SVladimir Oltean return 0; 92*56051948SVladimir Oltean } 93*56051948SVladimir Oltean 94*56051948SVladimir Oltean static int felix_vlan_filtering(struct dsa_switch *ds, int port, bool enabled) 95*56051948SVladimir Oltean { 96*56051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 97*56051948SVladimir Oltean 98*56051948SVladimir Oltean ocelot_port_vlan_filtering(ocelot, port, enabled); 99*56051948SVladimir Oltean 100*56051948SVladimir Oltean return 0; 101*56051948SVladimir Oltean } 102*56051948SVladimir Oltean 103*56051948SVladimir Oltean static void felix_vlan_add(struct dsa_switch *ds, int port, 104*56051948SVladimir Oltean const struct switchdev_obj_port_vlan *vlan) 105*56051948SVladimir Oltean { 106*56051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 107*56051948SVladimir Oltean u16 vid; 108*56051948SVladimir Oltean int err; 109*56051948SVladimir Oltean 110*56051948SVladimir Oltean for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) { 111*56051948SVladimir Oltean err = ocelot_vlan_add(ocelot, port, vid, 112*56051948SVladimir Oltean vlan->flags & BRIDGE_VLAN_INFO_PVID, 113*56051948SVladimir Oltean vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED); 114*56051948SVladimir Oltean if (err) { 115*56051948SVladimir Oltean dev_err(ds->dev, "Failed to add VLAN %d to port %d: %d\n", 116*56051948SVladimir Oltean vid, port, err); 117*56051948SVladimir Oltean return; 118*56051948SVladimir Oltean } 119*56051948SVladimir Oltean } 120*56051948SVladimir Oltean } 121*56051948SVladimir Oltean 122*56051948SVladimir Oltean static int felix_vlan_del(struct dsa_switch *ds, int port, 123*56051948SVladimir Oltean const struct switchdev_obj_port_vlan *vlan) 124*56051948SVladimir Oltean { 125*56051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 126*56051948SVladimir Oltean u16 vid; 127*56051948SVladimir Oltean int err; 128*56051948SVladimir Oltean 129*56051948SVladimir Oltean for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) { 130*56051948SVladimir Oltean err = ocelot_vlan_del(ocelot, port, vid); 131*56051948SVladimir Oltean if (err) { 132*56051948SVladimir Oltean dev_err(ds->dev, "Failed to remove VLAN %d from port %d: %d\n", 133*56051948SVladimir Oltean vid, port, err); 134*56051948SVladimir Oltean return err; 135*56051948SVladimir Oltean } 136*56051948SVladimir Oltean } 137*56051948SVladimir Oltean return 0; 138*56051948SVladimir Oltean } 139*56051948SVladimir Oltean 140*56051948SVladimir Oltean static int felix_port_enable(struct dsa_switch *ds, int port, 141*56051948SVladimir Oltean struct phy_device *phy) 142*56051948SVladimir Oltean { 143*56051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 144*56051948SVladimir Oltean 145*56051948SVladimir Oltean ocelot_port_enable(ocelot, port, phy); 146*56051948SVladimir Oltean 147*56051948SVladimir Oltean return 0; 148*56051948SVladimir Oltean } 149*56051948SVladimir Oltean 150*56051948SVladimir Oltean static void felix_port_disable(struct dsa_switch *ds, int port) 151*56051948SVladimir Oltean { 152*56051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 153*56051948SVladimir Oltean 154*56051948SVladimir Oltean return ocelot_port_disable(ocelot, port); 155*56051948SVladimir Oltean } 156*56051948SVladimir Oltean 157*56051948SVladimir Oltean static void felix_get_strings(struct dsa_switch *ds, int port, 158*56051948SVladimir Oltean u32 stringset, u8 *data) 159*56051948SVladimir Oltean { 160*56051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 161*56051948SVladimir Oltean 162*56051948SVladimir Oltean return ocelot_get_strings(ocelot, port, stringset, data); 163*56051948SVladimir Oltean } 164*56051948SVladimir Oltean 165*56051948SVladimir Oltean static void felix_get_ethtool_stats(struct dsa_switch *ds, int port, u64 *data) 166*56051948SVladimir Oltean { 167*56051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 168*56051948SVladimir Oltean 169*56051948SVladimir Oltean ocelot_get_ethtool_stats(ocelot, port, data); 170*56051948SVladimir Oltean } 171*56051948SVladimir Oltean 172*56051948SVladimir Oltean static int felix_get_sset_count(struct dsa_switch *ds, int port, int sset) 173*56051948SVladimir Oltean { 174*56051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 175*56051948SVladimir Oltean 176*56051948SVladimir Oltean return ocelot_get_sset_count(ocelot, port, sset); 177*56051948SVladimir Oltean } 178*56051948SVladimir Oltean 179*56051948SVladimir Oltean static int felix_get_ts_info(struct dsa_switch *ds, int port, 180*56051948SVladimir Oltean struct ethtool_ts_info *info) 181*56051948SVladimir Oltean { 182*56051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 183*56051948SVladimir Oltean 184*56051948SVladimir Oltean return ocelot_get_ts_info(ocelot, port, info); 185*56051948SVladimir Oltean } 186*56051948SVladimir Oltean 187*56051948SVladimir Oltean static int felix_init_structs(struct felix *felix, int num_phys_ports) 188*56051948SVladimir Oltean { 189*56051948SVladimir Oltean struct ocelot *ocelot = &felix->ocelot; 190*56051948SVladimir Oltean resource_size_t base; 191*56051948SVladimir Oltean int port, i, err; 192*56051948SVladimir Oltean 193*56051948SVladimir Oltean ocelot->num_phys_ports = num_phys_ports; 194*56051948SVladimir Oltean ocelot->ports = devm_kcalloc(ocelot->dev, num_phys_ports, 195*56051948SVladimir Oltean sizeof(struct ocelot_port *), GFP_KERNEL); 196*56051948SVladimir Oltean if (!ocelot->ports) 197*56051948SVladimir Oltean return -ENOMEM; 198*56051948SVladimir Oltean 199*56051948SVladimir Oltean ocelot->map = felix->info->map; 200*56051948SVladimir Oltean ocelot->stats_layout = felix->info->stats_layout; 201*56051948SVladimir Oltean ocelot->num_stats = felix->info->num_stats; 202*56051948SVladimir Oltean ocelot->shared_queue_sz = felix->info->shared_queue_sz; 203*56051948SVladimir Oltean ocelot->ops = felix->info->ops; 204*56051948SVladimir Oltean 205*56051948SVladimir Oltean base = pci_resource_start(felix->pdev, felix->info->pci_bar); 206*56051948SVladimir Oltean 207*56051948SVladimir Oltean for (i = 0; i < TARGET_MAX; i++) { 208*56051948SVladimir Oltean struct regmap *target; 209*56051948SVladimir Oltean struct resource *res; 210*56051948SVladimir Oltean 211*56051948SVladimir Oltean if (!felix->info->target_io_res[i].name) 212*56051948SVladimir Oltean continue; 213*56051948SVladimir Oltean 214*56051948SVladimir Oltean res = &felix->info->target_io_res[i]; 215*56051948SVladimir Oltean res->flags = IORESOURCE_MEM; 216*56051948SVladimir Oltean res->start += base; 217*56051948SVladimir Oltean res->end += base; 218*56051948SVladimir Oltean 219*56051948SVladimir Oltean target = ocelot_regmap_init(ocelot, res); 220*56051948SVladimir Oltean if (IS_ERR(target)) { 221*56051948SVladimir Oltean dev_err(ocelot->dev, 222*56051948SVladimir Oltean "Failed to map device memory space\n"); 223*56051948SVladimir Oltean return PTR_ERR(target); 224*56051948SVladimir Oltean } 225*56051948SVladimir Oltean 226*56051948SVladimir Oltean ocelot->targets[i] = target; 227*56051948SVladimir Oltean } 228*56051948SVladimir Oltean 229*56051948SVladimir Oltean err = ocelot_regfields_init(ocelot, felix->info->regfields); 230*56051948SVladimir Oltean if (err) { 231*56051948SVladimir Oltean dev_err(ocelot->dev, "failed to init reg fields map\n"); 232*56051948SVladimir Oltean return err; 233*56051948SVladimir Oltean } 234*56051948SVladimir Oltean 235*56051948SVladimir Oltean for (port = 0; port < num_phys_ports; port++) { 236*56051948SVladimir Oltean struct ocelot_port *ocelot_port; 237*56051948SVladimir Oltean void __iomem *port_regs; 238*56051948SVladimir Oltean struct resource *res; 239*56051948SVladimir Oltean 240*56051948SVladimir Oltean ocelot_port = devm_kzalloc(ocelot->dev, 241*56051948SVladimir Oltean sizeof(struct ocelot_port), 242*56051948SVladimir Oltean GFP_KERNEL); 243*56051948SVladimir Oltean if (!ocelot_port) { 244*56051948SVladimir Oltean dev_err(ocelot->dev, 245*56051948SVladimir Oltean "failed to allocate port memory\n"); 246*56051948SVladimir Oltean return -ENOMEM; 247*56051948SVladimir Oltean } 248*56051948SVladimir Oltean 249*56051948SVladimir Oltean res = &felix->info->port_io_res[port]; 250*56051948SVladimir Oltean res->flags = IORESOURCE_MEM; 251*56051948SVladimir Oltean res->start += base; 252*56051948SVladimir Oltean res->end += base; 253*56051948SVladimir Oltean 254*56051948SVladimir Oltean port_regs = devm_ioremap_resource(ocelot->dev, res); 255*56051948SVladimir Oltean if (IS_ERR(port_regs)) { 256*56051948SVladimir Oltean dev_err(ocelot->dev, 257*56051948SVladimir Oltean "failed to map registers for port %d\n", port); 258*56051948SVladimir Oltean return PTR_ERR(port_regs); 259*56051948SVladimir Oltean } 260*56051948SVladimir Oltean 261*56051948SVladimir Oltean ocelot_port->ocelot = ocelot; 262*56051948SVladimir Oltean ocelot_port->regs = port_regs; 263*56051948SVladimir Oltean ocelot->ports[port] = ocelot_port; 264*56051948SVladimir Oltean } 265*56051948SVladimir Oltean 266*56051948SVladimir Oltean return 0; 267*56051948SVladimir Oltean } 268*56051948SVladimir Oltean 269*56051948SVladimir Oltean /* Hardware initialization done here so that we can allocate structures with 270*56051948SVladimir Oltean * devm without fear of dsa_register_switch returning -EPROBE_DEFER and causing 271*56051948SVladimir Oltean * us to allocate structures twice (leak memory) and map PCI memory twice 272*56051948SVladimir Oltean * (which will not work). 273*56051948SVladimir Oltean */ 274*56051948SVladimir Oltean static int felix_setup(struct dsa_switch *ds) 275*56051948SVladimir Oltean { 276*56051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 277*56051948SVladimir Oltean struct felix *felix = ocelot_to_felix(ocelot); 278*56051948SVladimir Oltean int port, err; 279*56051948SVladimir Oltean 280*56051948SVladimir Oltean err = felix_init_structs(felix, ds->num_ports); 281*56051948SVladimir Oltean if (err) 282*56051948SVladimir Oltean return err; 283*56051948SVladimir Oltean 284*56051948SVladimir Oltean ocelot_init(ocelot); 285*56051948SVladimir Oltean 286*56051948SVladimir Oltean for (port = 0; port < ds->num_ports; port++) { 287*56051948SVladimir Oltean ocelot_init_port(ocelot, port); 288*56051948SVladimir Oltean 289*56051948SVladimir Oltean if (port == dsa_upstream_port(ds, port)) 290*56051948SVladimir Oltean ocelot_set_cpu_port(ocelot, port, 291*56051948SVladimir Oltean OCELOT_TAG_PREFIX_NONE, 292*56051948SVladimir Oltean OCELOT_TAG_PREFIX_LONG); 293*56051948SVladimir Oltean } 294*56051948SVladimir Oltean 295*56051948SVladimir Oltean return 0; 296*56051948SVladimir Oltean } 297*56051948SVladimir Oltean 298*56051948SVladimir Oltean static void felix_teardown(struct dsa_switch *ds) 299*56051948SVladimir Oltean { 300*56051948SVladimir Oltean struct ocelot *ocelot = ds->priv; 301*56051948SVladimir Oltean 302*56051948SVladimir Oltean /* stop workqueue thread */ 303*56051948SVladimir Oltean ocelot_deinit(ocelot); 304*56051948SVladimir Oltean } 305*56051948SVladimir Oltean 306*56051948SVladimir Oltean static const struct dsa_switch_ops felix_switch_ops = { 307*56051948SVladimir Oltean .get_tag_protocol = felix_get_tag_protocol, 308*56051948SVladimir Oltean .setup = felix_setup, 309*56051948SVladimir Oltean .teardown = felix_teardown, 310*56051948SVladimir Oltean .set_ageing_time = felix_set_ageing_time, 311*56051948SVladimir Oltean .get_strings = felix_get_strings, 312*56051948SVladimir Oltean .get_ethtool_stats = felix_get_ethtool_stats, 313*56051948SVladimir Oltean .get_sset_count = felix_get_sset_count, 314*56051948SVladimir Oltean .get_ts_info = felix_get_ts_info, 315*56051948SVladimir Oltean .adjust_link = felix_adjust_link, 316*56051948SVladimir Oltean .port_enable = felix_port_enable, 317*56051948SVladimir Oltean .port_disable = felix_port_disable, 318*56051948SVladimir Oltean .port_fdb_dump = felix_fdb_dump, 319*56051948SVladimir Oltean .port_fdb_add = felix_fdb_add, 320*56051948SVladimir Oltean .port_fdb_del = felix_fdb_del, 321*56051948SVladimir Oltean .port_bridge_join = felix_bridge_join, 322*56051948SVladimir Oltean .port_bridge_leave = felix_bridge_leave, 323*56051948SVladimir Oltean .port_stp_state_set = felix_bridge_stp_state_set, 324*56051948SVladimir Oltean .port_vlan_prepare = felix_vlan_prepare, 325*56051948SVladimir Oltean .port_vlan_filtering = felix_vlan_filtering, 326*56051948SVladimir Oltean .port_vlan_add = felix_vlan_add, 327*56051948SVladimir Oltean .port_vlan_del = felix_vlan_del, 328*56051948SVladimir Oltean }; 329*56051948SVladimir Oltean 330*56051948SVladimir Oltean static struct felix_info *felix_instance_tbl[] = { 331*56051948SVladimir Oltean [FELIX_INSTANCE_VSC9959] = &felix_info_vsc9959, 332*56051948SVladimir Oltean }; 333*56051948SVladimir Oltean 334*56051948SVladimir Oltean static int felix_pci_probe(struct pci_dev *pdev, 335*56051948SVladimir Oltean const struct pci_device_id *id) 336*56051948SVladimir Oltean { 337*56051948SVladimir Oltean enum felix_instance instance = id->driver_data; 338*56051948SVladimir Oltean struct dsa_switch *ds; 339*56051948SVladimir Oltean struct ocelot *ocelot; 340*56051948SVladimir Oltean struct felix *felix; 341*56051948SVladimir Oltean int err; 342*56051948SVladimir Oltean 343*56051948SVladimir Oltean err = pci_enable_device(pdev); 344*56051948SVladimir Oltean if (err) { 345*56051948SVladimir Oltean dev_err(&pdev->dev, "device enable failed\n"); 346*56051948SVladimir Oltean goto err_pci_enable; 347*56051948SVladimir Oltean } 348*56051948SVladimir Oltean 349*56051948SVladimir Oltean /* set up for high or low dma */ 350*56051948SVladimir Oltean err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); 351*56051948SVladimir Oltean if (err) { 352*56051948SVladimir Oltean err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); 353*56051948SVladimir Oltean if (err) { 354*56051948SVladimir Oltean dev_err(&pdev->dev, 355*56051948SVladimir Oltean "DMA configuration failed: 0x%x\n", err); 356*56051948SVladimir Oltean goto err_dma; 357*56051948SVladimir Oltean } 358*56051948SVladimir Oltean } 359*56051948SVladimir Oltean 360*56051948SVladimir Oltean felix = kzalloc(sizeof(struct felix), GFP_KERNEL); 361*56051948SVladimir Oltean if (!felix) { 362*56051948SVladimir Oltean err = -ENOMEM; 363*56051948SVladimir Oltean dev_err(&pdev->dev, "Failed to allocate driver memory\n"); 364*56051948SVladimir Oltean goto err_alloc_felix; 365*56051948SVladimir Oltean } 366*56051948SVladimir Oltean 367*56051948SVladimir Oltean pci_set_drvdata(pdev, felix); 368*56051948SVladimir Oltean ocelot = &felix->ocelot; 369*56051948SVladimir Oltean ocelot->dev = &pdev->dev; 370*56051948SVladimir Oltean felix->pdev = pdev; 371*56051948SVladimir Oltean felix->info = felix_instance_tbl[instance]; 372*56051948SVladimir Oltean 373*56051948SVladimir Oltean pci_set_master(pdev); 374*56051948SVladimir Oltean 375*56051948SVladimir Oltean ds = kzalloc(sizeof(struct dsa_switch), GFP_KERNEL); 376*56051948SVladimir Oltean if (!ds) { 377*56051948SVladimir Oltean err = -ENOMEM; 378*56051948SVladimir Oltean dev_err(&pdev->dev, "Failed to allocate DSA switch\n"); 379*56051948SVladimir Oltean goto err_alloc_ds; 380*56051948SVladimir Oltean } 381*56051948SVladimir Oltean 382*56051948SVladimir Oltean ds->dev = &pdev->dev; 383*56051948SVladimir Oltean ds->num_ports = felix->info->num_ports; 384*56051948SVladimir Oltean ds->ops = &felix_switch_ops; 385*56051948SVladimir Oltean ds->priv = ocelot; 386*56051948SVladimir Oltean felix->ds = ds; 387*56051948SVladimir Oltean 388*56051948SVladimir Oltean err = dsa_register_switch(ds); 389*56051948SVladimir Oltean if (err) { 390*56051948SVladimir Oltean dev_err(&pdev->dev, "Failed to register DSA switch: %d\n", err); 391*56051948SVladimir Oltean goto err_register_ds; 392*56051948SVladimir Oltean } 393*56051948SVladimir Oltean 394*56051948SVladimir Oltean return 0; 395*56051948SVladimir Oltean 396*56051948SVladimir Oltean err_register_ds: 397*56051948SVladimir Oltean kfree(ds); 398*56051948SVladimir Oltean err_alloc_ds: 399*56051948SVladimir Oltean err_alloc_felix: 400*56051948SVladimir Oltean kfree(felix); 401*56051948SVladimir Oltean err_dma: 402*56051948SVladimir Oltean pci_disable_device(pdev); 403*56051948SVladimir Oltean err_pci_enable: 404*56051948SVladimir Oltean return err; 405*56051948SVladimir Oltean } 406*56051948SVladimir Oltean 407*56051948SVladimir Oltean static void felix_pci_remove(struct pci_dev *pdev) 408*56051948SVladimir Oltean { 409*56051948SVladimir Oltean struct felix *felix; 410*56051948SVladimir Oltean 411*56051948SVladimir Oltean felix = pci_get_drvdata(pdev); 412*56051948SVladimir Oltean 413*56051948SVladimir Oltean dsa_unregister_switch(felix->ds); 414*56051948SVladimir Oltean 415*56051948SVladimir Oltean kfree(felix->ds); 416*56051948SVladimir Oltean kfree(felix); 417*56051948SVladimir Oltean 418*56051948SVladimir Oltean pci_disable_device(pdev); 419*56051948SVladimir Oltean } 420*56051948SVladimir Oltean 421*56051948SVladimir Oltean static struct pci_device_id felix_ids[] = { 422*56051948SVladimir Oltean { 423*56051948SVladimir Oltean /* NXP LS1028A */ 424*56051948SVladimir Oltean PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, 0xEEF0), 425*56051948SVladimir Oltean .driver_data = FELIX_INSTANCE_VSC9959, 426*56051948SVladimir Oltean }, 427*56051948SVladimir Oltean { 0, } 428*56051948SVladimir Oltean }; 429*56051948SVladimir Oltean MODULE_DEVICE_TABLE(pci, felix_ids); 430*56051948SVladimir Oltean 431*56051948SVladimir Oltean static struct pci_driver felix_pci_driver = { 432*56051948SVladimir Oltean .name = KBUILD_MODNAME, 433*56051948SVladimir Oltean .id_table = felix_ids, 434*56051948SVladimir Oltean .probe = felix_pci_probe, 435*56051948SVladimir Oltean .remove = felix_pci_remove, 436*56051948SVladimir Oltean }; 437*56051948SVladimir Oltean 438*56051948SVladimir Oltean module_pci_driver(felix_pci_driver); 439*56051948SVladimir Oltean 440*56051948SVladimir Oltean MODULE_DESCRIPTION("Felix Switch driver"); 441*56051948SVladimir Oltean MODULE_LICENSE("GPL v2"); 442